[英]C# Open XML SDK 2.0 Excel spreadsheet - load range of cells from string array
In a .Net windows desktop application, I am able to import a string array of data into a range of cells located in Excel spreadsheet. 在.Net Windows桌面应用程序中,我能够将字符串数据数组导入Excel电子表格中的一系列单元格中。 The C# code is as follows:
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;
I am trying to duplicate this process in an ASP.Net webpage. 我正在尝试在ASP.Net网页中重复此过程。 Using Visual Studio 2010 and C#.
使用Visual Studio 2010和C#。 How can I do this same import of a string array into an Open XML SDK 2.0 Excel spreadsheet range of cells?
如何将同样的字符串数组导入到Open XML SDK 2.0 Excel电子表格范围的单元格中?
As answered, a library might be easier to use. 答案是,库可能更易于使用。 An alternative library choice is SpreadsheetLight .
另一种库选择是SpreadsheetLight 。 Here's how the code might look like:
代码如下所示:
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");
You don't have to worry about which order you set the cell values. 您不必担心设置单元格值的顺序。 Internally, SpreadsheetLight runs on Open XML SDK.
在内部,SpreadsheetLight在Open XML SDK上运行。 Disclaimer: I wrote SpreadsheetLight.
免责声明:我写了SpreadsheetLight。
Using the OpenXML SDK directly instead of going through Excel's automation model is much more complex and error-prone. 直接使用OpenXML SDK而不是通过Excel的自动化模型,要复杂得多且容易出错。 Therefore I recommend using a library for this;
因此,我建议为此使用一个库。 espcially if your task gets more complex (eg http://excelpackage.codeplex.com/ ).
特别是如果您的任务变得更加复杂(例如, http : //excelpackage.codeplex.com/ )。 Edit : An example on doing something similar using ExcelPackage can be found here: http://excelpackage.codeplex.com/wikipage?title=Using%20a%20template%20to%20create%20an%20Excel%20spreadsheet Although I have no idea on what performance to expect compared to using the raw SDK, I would guess that ExcelPackage is using the SDK internally anyway and therefore it might produce some overhead.
编辑 :可以在此处找到有关使用ExcelPackage进行类似操作的示例: http ://excelpackage.codeplex.com/wikipage?title=使用%20a%20template%20to%20create%20an%20Excel%20spreadsheet,尽管我对此一无所知与使用原始SDK相比预期的性能如何,我想ExcelPackage无论如何都在内部使用SDK,因此可能会产生一些开销。 Probably only a measurement for you concrete scenario can provide a definite answer here.
在这里,可能只有针对您的具体方案的度量才能提供明确的答案。
If you want to stick to the SDK though here is an example for inserting strings into an Excel workbook: 如果您想坚持使用SDK,请参考以下示例,将字符串插入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, e.g. 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 (e.g. 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]);
}
}
Please note that this example is not perfect as it does not consider complex scenarios at all (eg styling, print margin, merged cells...). 请注意,此示例并不完美,因为它根本没有考虑复杂的情况(例如,样式,打印页边距,合并的单元格...)。 For production use you might want to extract certain functionality into a method (for example inserting a row or cell at the correct position) or even into a class all by itself (eg the part about comparing cell references in correct order).
对于生产用途,您可能希望将某些功能提取到方法中(例如,将行或单元格插入正确的位置),或者甚至全部提取到类中(例如,按正确顺序比较单元格引用的部分)。
Edit : The performance of using the SDK instead of going through the Automation Model is MUCH better (this is probably the second huge advantage of the SDK, the first being that you do not neeed to have Excel installed). 编辑 :使用SDK而不是通过自动化模型的性能要好得多(这可能是SDK的第二个巨大优势,第一个是您不需要安装Excel。) If you still see performance bottlenecks here are some ideas for improvement:
如果您仍然看到性能瓶颈,请参考以下改进建议:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.