C#打开XML SDK 2.0 Excel电子表格 – 从string数组中加载单元格范围

在.net Windows桌面应用程序中,我可以将一个string数组导入Excel电子表格中的一系列单元格中。 C#代码如下:

using Excel = Microsoft.Office.Interop.Excel; // Create Application, Workbook, and Worksheet xlApp = new Microsoft.Office.Interop.Excel.Application(); xlWorkBook = xlApp.Workbooks.Add(misValue); xlWs = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); // Move data from temp array into Excel spreadsheet. Excel.Range c1 = (Excel.Range)xlWs.Cells[startRowNum, 1]; Excel.Range c2 = (Excel.Range)xlWs.Cells[startRowNum + myTable.Rows.Count - 1, Columns.Count]; Excel.Range range = xlWs.get_Range(c1, c2); range.Value = tempArray; 

我试图在ASP.Net网页中复制这个过程。 使用Visual Studio 2010和C#。 我怎样才能将这个string数组导入Open XML SDK 2.0 Excel电子表格单元格区域?

如答复,图书馆可能更容易使用。 另一个库select是SpreadsheetLight 。 代码如下所示:

 SLDocument sl = new SLDocument("YourFile.xlsx"); // row 1 column 1 sl.SetCellValue(1, 1, "String1"); // row 1 column 2 sl.SetCellValue(1, 2, "String2"); sl.SaveAs("AnotherFile.xlsx"); 

您不必担心您设置单元格值的顺序。 在内部,SpreadsheetLight在Open XML SDK上运行。 免责声明:我写了SpreadsheetLight。

直接使用OpenXML SDK而不是通过Excel的自动化模型是非常复杂和容易出错的。 所以我build议使用这个库; 特别是如果你的任务变得更复杂(例如http://excelpackage.codeplex.com/ )。 编辑 :使用ExcelPackage做类似的例子可以在这里find: http ://excelpackage.codeplex.com/wikipage?title=Using%20a%20template%20to%20create%20an%20Excel%20spreadsheet虽然我不知道与使用原始SDK相比,期望什么样的性能,我猜想ExcelPackage无论如何都是在内部使用SDK,因此可能会产生一些开销。 也许只有对你具体情景的测量才能在这里提供一个明确的答案。

如果你想坚持SDK,虽然这是一个插入string到Excel工作簿的例子:

 string filePath = "workbook.xlsx"; string sheetName = "Sheet1"; uint startRow = 9; string columnName = "C"; string[] data = new string[] { "A", "B", "C" }; using (var spreadsheetDocument = SpreadsheetDocument.Open(filePath, true)) { // Find the Id of the worksheet in question var sheet = spreadsheetDocument.WorkbookPart.Workbook .Sheets.Elements<Sheet>() .Where(s => s.Name == sheetName).First(); var sheetReferenceId = sheet.Id; // Map the Id to the worksheet part WorksheetPart worksheetPart = (WorksheetPart)spreadsheetDocument.WorkbookPart.GetPartById(sheetReferenceId); var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>(); // Inset the data at the given location for (uint i = 0; i < data.Length; i++) { uint rowNumber = startRow + i; // Find the XML entry for row i var row = sheetData.Elements<Row>().Where(r => r.RowIndex == rowNumber).FirstOrDefault(); if (row == null) { // Row does not exist yet, create it row = new Row(); row.RowIndex = rowNumber; // Insert the row at its correct sequential position Row rowAfter = null; foreach (Row otherRow in sheetData.Elements<Row>()) { if (otherRow.RowIndex > row.RowIndex) { rowAfter = otherRow; break; } } if (rowAfter == null) // New row is the last row in the sheet sheetData.Append(row); else sheetData.InsertBefore(row, rowAfter); } // CellReferences in OpenXML are "normal" Excel cell references, eg D15 string cellReference = columnName + rowNumber.ToString(); // Find cell in row var cell = row.Elements<Cell>() .Where(c => c.CellReference == cellReference) .FirstOrDefault(); if (cell == null) { // Cell does not exist yet, create it cell = new Cell(); cell.CellReference = new StringValue(cellReference); // The cell must be in the correct position (eg column B after A) // Note: AA must be after Z, so a normal string compare is not sufficient Cell cellAfter = null; foreach (Cell otherCell in row.Elements<Cell>()) { // This is ugly, but somehow the row number must be stripped from the // cell reference for comparison string otherCellColumn = otherCell.CellReference.Value; otherCellColumn = otherCellColumn.Remove(otherCellColumn.Length - rowNumber.ToString().Length); // Now compare first to length and then alphabetically if (otherCellColumn.Length > columnName.Length || string.Compare(otherCellColumn, columnName, true) > 0) { cellAfter = otherCell; break; } } if (cellAfter == null) // New cell is last cell in row row.Append(cell); else row.InsertBefore(cell, cellAfter); } // Note: This is the most simple approach. // Normally Excel itself will store the string as a SharedString, // which is more difficult to implement. The only drawback of using // this approach though, is that the cell might have been the only // reference to its shared string value, which is not deleted from the // list here. cell.DataType = CellValues.String; cell.CellValue = new CellValue(data[i]); } } 

请注意,这个例子并不完美,因为它根本不考虑复杂的场景(例如样式,打印边距,合并的单元格…)。 对于生产用途,您可能希望将某些function提取到方法中(例如在正确的位置插入一行或一列单元格),甚至可以将所有function单独放入类中(例如,按照正确的顺序比较单元格引用的部分)。

编辑 :使用SDK而不是通过自动化模型的性能更好(这可能是SDK的第二个巨大的优势,第一个是你不需要安装Excel)。 如果你仍然看到性能瓶颈,这里有一些改进的想法:

  1. 确保已经在模板文档中创build了单元格(例如,在每个使用Excel中插入一个0)。 这可以节省您创build新单元格的工作量。
  2. 确保模板中没有任何单元格已经存在,然后按顺序创build所有单元格(节省您至less为该行查找正确的插入位置的工作量)。
  3. 直接操作XML,这更加困难,需要更多关于OpenXML内部工作的知识。 对于相当统一的文件来说,这是可以接受