OpenXML SDK是处理此任务的正确工具,但您需要小心使用
SAX(用于XML的简单API)方法,而不是
DOM方法。从SAX的维基百科文章中得知:
“DOM操作整个文档,而SAX解析器按顺序处理XML文档的每个部分。”
这大大减少了处理大型Excel文件时消耗的内存量。
这里有一篇很好的文章 -
http://polymathprogrammer.com/2012/08/06/how-to-properly-use-openxmlwriter-to-write-large-excel-files/
从那篇文章中改编出一个示例,输出了115k行和30列。
public static void LargeExport(string filename)
{
using (SpreadsheetDocument document = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
{
List<OpenXmlAttribute> attributes;
OpenXmlWriter writer;
document.AddWorkbookPart();
WorksheetPart workSheetPart = document.WorkbookPart.AddNewPart<WorksheetPart>();
writer = OpenXmlWriter.Create(workSheetPart);
writer.WriteStartElement(new Worksheet());
writer.WriteStartElement(new SheetData());
for (int rowNum = 1; rowNum <= 115000; ++rowNum)
{
attributes = new List<OpenXmlAttribute>();
attributes.Add(new OpenXmlAttribute("r", null, rowNum.ToString()));
writer.WriteStartElement(new Row(), attributes);
for (int columnNum = 1; columnNum <= 30; ++columnNum)
{
attributes = new List<OpenXmlAttribute>();
attributes.Add(new OpenXmlAttribute("t", null, "str"));
attributes.Add(new OpenXmlAttribute("r", "", string.Format("{0}{1}", GetColumnName(columnNum), rowNum)));
writer.WriteStartElement(new Cell(), attributes);
writer.WriteElement(new CellValue(string.Format("This is Row {0}, Cell {1}", rowNum, columnNum)));
writer.WriteEndElement();
}
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndElement();
writer.Close();
writer = OpenXmlWriter.Create(document.WorkbookPart);
writer.WriteStartElement(new Workbook());
writer.WriteStartElement(new Sheets());
writer.WriteElement(new Sheet()
{
Name = "Large Sheet",
SheetId = 1,
Id = document.WorkbookPart.GetIdOfPart(workSheetPart)
});
writer.WriteEndElement();
writer.WriteEndElement();
writer.Close();
document.Close();
}
}
private static string GetColumnName(int columnIndex)
{
int dividend = columnIndex;
string columnName = String.Empty;
int modifier;
while (dividend > 0)
{
modifier = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modifier).ToString() + columnName;
dividend = (int)((dividend - modifier) / 26);
}
return columnName;
}