Reputation: 10191
I need to generate a very large Excel file from an ASP.NET MVC site, but am running into memory limitations using the Open XML SDK. Is there a memory efficient way to generate such a file?
For reference, I'm trying to generate a spreadsheet with about 500,000 rows with 20 columns each. The data set itself fits into memory just fine, but the Open XML SDK quickly eats up all of my available memory.
Upvotes: 5
Views: 5741
Reputation: 268
You can use Open XML SDK in reasonably efficiently way, the trick is to use the OpenXmlWriter class (in this CodeProject article you have more details)
I had a memory issue generating a file of 91 columns x 164,000 rows. Using OpenXmlWriter I went from 2GB of RAM consumption to 120MB, enough for me :-)
Seeing it with a code example:
Standard (and unoptimized) way:
// Table header
Row headerRow = new Row();
foreach (string fieldName in fields)
{
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(fieldName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
// Table rows
while (dataReader.Read())
{
Row dataRow = new Row();
foreach (string fieldName in fields)
{
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(reader[fieldName].ToString());
dataRow.AppendChild(cell);
}
sheetData.AppendChild(dataRow);
}
OpenXmlWriter way:
using (var writer = OpenXmlWriter.Create(worksheetPart))
{
writer.WriteStartElement(new Worksheet());
writer.WriteStartElement(new SheetData());
// Table header
writer.WriteStartElement(new Row());
foreach (string fieldName in fields)
{
writer.WriteStartElement(new Cell() { DataType = CellValues.String });
writer.WriteElement(new CellValue(fieldName));
writer.WriteEndElement();
}
writer.WriteEndElement(); //end of Row tag
// Table rows
while (dataReader.Read())
{
writer.WriteStartElement(new Row());
foreach (string fieldName in fields)
{
writer.WriteStartElement(new Cell() { DataType = CellValues.String });
writer.WriteElement(new CellValue(dataReader[fieldName].ToString()));
writer.WriteEndElement();
}
writer.WriteEndElement(); //end of Row tag
}
writer.WriteEndElement(); //end of SheetData
writer.WriteEndElement(); //end of worksheet
writer.Close();
}
Upvotes: 3