2013-06-19 11 views
1

У меня есть следующий код и его не сохраняются значения в ячейке, а также в файле. Он показывает значение в поле cell.cellvalue, но его не пишут, чтобы преуспеть. Я не знаю, как сохранить файл. Я использовал OpenXml-SDK, и я пишу datatable значений для каждого cell/row созданного документа электронной таблицы.Библиотека OpenXML save excel file

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

Есть некоторые возможные проблемы здесь:

  • Вы можете создать и добавить новые строки и ячейки: она предполагает рабочий лист полностью пустой, когда вы открываете его (т.е. нет строк или ячеек с тот же индекс/адрес).

  • Так как вы установите CellType в InlineString, вам необходимо установить 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(); 
    

    Адрес ячейки должен быть примерно таким «А1». Вы должны просмотреть свой код, чтобы установить правильный адрес. У вас уже есть rowIndex. Вам нужно получить имя столбца. Это может помочь Translate a column index into an Excel Column Name.

+0

@ user1848739 Я обновил свой ответ, так как понял, что есть другие проблемы. – Chris

+0

Я пробовал ваше решение и показывал мне тот же результат. У него чистый лист. Как сохранить данные на листе Excel? – rach

+0

@ user1848739 Невозможно сказать, если вы не показываете модифицированный код с правильным адресом cellAddress. Кроме того, я не вижу кода, который сохраняет книгу (она сохраняет только рабочий лист) – Chris