2013-06-19 124 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