2013-06-19 49 views
1

我有下面的代碼,它沒有將值保存到單元格和文件中。它顯示cell.cellvalue字段的值,但它不寫入excel。我不知道如何保存文件。我使用了OpenXml-SDK,我正在爲創建的電子表格文檔的每個cell/row寫入datatable值。OpenXML庫保存excel文件

using (SpreadsheetDocument ssd=SpreadsheetDocument.Open(Server.MapPath(@"\ExcelPackageTemplate.xlsx"),true)) 
     { 
      WorkbookPart wbPart = ssd.WorkbookPart; 
      WorksheetPart worksheetPart = wbPart.WorksheetParts.First(); 

      SheetData sheetdata = worksheetPart.Worksheet.GetFirstChild<SheetData>(); 
      string[] headerColumns = new string[] { dt.Columns[0].ColumnName, dt.Columns[1].ColumnName,dt.Columns[2].ColumnName }; 
      DocumentFormat.OpenXml.Spreadsheet.Row r = new DocumentFormat.OpenXml.Spreadsheet.Row(); 
      int RowIndexer = 1; 
      //int colInd=0; 
      r.RowIndex = (UInt32)RowIndexer; 

      string test = ColumnName(RowIndexer); 

      foreach (DataColumn dc in dt.Columns) 
      { 

       DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
       cell.CellReference = test+RowIndexer; 
       cell.DataType = CellValues.InlineString; 
       cell.InlineString = new InlineString(new Text(dc.ColumnName.ToString())); 
       DocumentFormat.OpenXml.Spreadsheet.CellValue value = new DocumentFormat.OpenXml.Spreadsheet.CellValue(); 

       r.AppendChild(cell); 

       // colInd++; 
      } 

      //r.RowIndex = (UInt32)RowIndexer; 
      RowIndexer = 2; 
      foreach (DataRow dr in dt.Rows) 
      { 
       DocumentFormat.OpenXml.Spreadsheet.Row Row = new DocumentFormat.OpenXml.Spreadsheet.Row(); 
       string Index = ColumnName(RowIndexer); 
       Row.RowIndex = (UInt32)RowIndexer; 
       foreach (object value in dr.ItemArray) 
       { 
        DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
        cell.DataType = CellValues.InlineString; 
        cell.InlineString = new InlineString(new Text(value.ToString())); 
        cell.CellReference = Index+RowIndexer; 
        // cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(value.ToString()); 
        Row.AppendChild(cell); 

       } 
       RowIndexer++; 

      } 

      worksheetPart.Worksheet.Save(); 
      wbPart.Workbook.Save(); 
      ssd.Close(); 

回答

4

試試這個:

using (SpreadsheetDocument ssd = SpreadsheetDocument.Open(Server.MapPath(@"\ExcelPackageTemplate.xlsx"), true)) 
{ 
    WorkbookPart wbPart = ssd.WorkbookPart; 
    WorksheetPart worksheetPart = wbPart.WorksheetParts.First(); 

    SheetData sheetdata = worksheetPart.Worksheet.GetFirstChild<SheetData>(); 
    string[] headerColumns = new string[] { dt.Columns[0].ColumnName, dt.Columns[1].ColumnName, dt.Columns[2].ColumnName }; 
    DocumentFormat.OpenXml.Spreadsheet.Row r = new DocumentFormat.OpenXml.Spreadsheet.Row(); 
    DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
    int RowIndexer = 1; 
    int ColumnIndexer = 1; 

    r.RowIndex = (UInt32)RowIndexer; 
    foreach (DataColumn dc in dt.Columns) 
    { 
     cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
     cell.CellReference = ColumnName(ColumnIndexer) + RowIndexer; 
     cell.DataType = CellValues.InlineString; 
     cell.InlineString = new InlineString(new Text(dc.ColumnName.ToString())); 
     // consider using cell.CellValue. Then you don't need to use InlineString. 
     // Because it seems you're not using any rich text so you're just bloating up 
     // the XML. 

     r.AppendChild(cell); 

     ColumnIndexer++; 
    } 
    // here's the missing part you needed 
    sheetdata.Append(r); 

    RowIndexer = 2; 
    foreach (DataRow dr in dt.Rows) 
    { 
     r = new DocumentFormat.OpenXml.Spreadsheet.Row(); 
     r.RowIndex = (UInt32)RowIndexer; 
     // this follows the same starting column index as your column header. 
     // I'm assuming you start with column 1. Change as you see fit. 
     ColumnIndexer = 1; 
     foreach (object value in dr.ItemArray) 
     { 
      cell = new DocumentFormat.OpenXml.Spreadsheet.Cell(); 
      // I moved it here so it's consistent with the above part 
      // Also, the original code was using the row index to calculate 
      // the column name, which is weird. 
      cell.CellReference = ColumnName(ColumnIndexer) + RowIndexer; 
      cell.DataType = CellValues.InlineString; 
      cell.InlineString = new InlineString(new Text(value.ToString())); 

      r.AppendChild(cell); 
      ColumnIndexer++; 
     } 
     RowIndexer++; 

     // missing part 
     sheetdata.Append(r); 
    } 

    worksheetPart.Worksheet.Save(); 
    wbPart.Workbook.Save(); 
    ssd.Close(); 
} 

一些評論:

  • 的的ColumnName()函數是here
  • 我假設你想要在一行中的列標題和後續行中的數據(因爲原始代碼有用於計算列名稱的行索引)。
  • 清理了代碼的某些部分,使其更易於閱讀,並且列標題和數據行部分在書寫風格上更加一致。
  • 我建議你考慮使用CellValue而不是InlineString。根據你的代碼,你正在導入一個DataTable,而你似乎並不需要豐富的文本,所以InlineString有點矯枉過正,並且可能使得生成的文件變大(臃腫的XML)。使用其中一個,並記住相應地設置DataType。
  • 此外,代碼僅適用於完全空白的SheetData。
2

這裏有一些可能出現的問題:

  • 您創建和添加新的行和單元格:它假定工作表是完全空白的,當你打開它(即:沒有行或單元格與相同的索引/地址)。

  • 既然你設置CellTypeInlineString,你需要設置Cell.InlineString而不是Cell.CellValue

    cell.DataType = CellValues.InlineString; 
    cell.InlineString = new InlineString(New Text(value.TsString())); 
    
  • 此外,有什麼不對您的有關的 CellReference使用的代碼。這些代碼部分沒有意義:

    cell.CellReference = dc.ColumnName.ToString(); 
    cell.CellReference = value.ToString(); 
    

    單元地址應該是這樣的「A1」。您必須查看您的代碼才能設置正確的地址。你已經有了rowIndex。您需要獲取列名稱。這Translate a column index into an Excel Column Name可以幫助。

+0

@ user1848739我已經更新了我的答案,因爲我意識到存在其他可能的問題。 – Chris

+0

我試過你的解決方案,它給我展示了同樣的結果。它有空白紙。如何將數據保存在Excel表格中? – rach

+0

@ user1848739如果您沒有使用正確的cellAddress顯示已修改的代碼,則無法說明。另外,我沒有看到保存工作簿的代碼(它只保存工作表) – Chris