OpenXML - 继续写入下一个工作表(百万行点击)



根据Microsoft规范.xlsx每个工作表的文件限制为 1,048,576 行。从理论上讲,正如我所看到的,这意味着即使有 200 万行,我们也可以写入文件 - 在同一工作簿中使用两个工作表。

我正在使用带有SAX方法的OpenXML包,它(恕我直言)仍然是编写大型Excel文件的最佳选择。我还扩展了我的解决方案,直接从 DataReader 写入.xlsx文件,以避免任何内存不足异常,因为我们的用户通常会导出非常大量的数据。

话虽如此,当用户想要导出大于 1,048,576 行的数据时,我遇到了一个问题 - 因为限制是.xlsx(是的,他们实际上导出了该数量)。

目前,他们可以通过创建单独的.xlsx文件通过 2 个步骤来完成,但我想知道是否可以在单个文件中完成?

对于代码部分:我设置了一个检查行号 (row_number) 的变量,如果它达到 100 万,则应创建一个新工作表,以便继续将数据从同一个 DataReader 写入下一张纸。

但是,我在创建新工作表时遇到了问题,因为我的数据是由OpenXmlWriter写入的,它已经拥有 sheet1 的Sheetpart实例。在我看来,如果我可以将 sheet2 的引用传递给OpenXmlWriter,也许这会起作用:

int row_number = 0;
using (var Excel_doc = SpreadsheetDocument.Create(file_path, SpreadsheetDocumentType.Workbook))
{
var workbookPart = Excel_doc.AddWorkbookPart();
Excel_doc.WorkbookPart.Workbook = new Workbook
{
Sheets = new Sheets()
};
var sheetPart = Excel_doc.WorkbookPart.AddNewPart<WorksheetPart>();
//Add sheet
Sheets sheets = Excel_doc.WorkbookPart.Workbook.GetFirstChild<Sheets>();
string relationshipId = Excel_doc.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = "Sheet " + sheetId };
sheets.Append(sheet);
using (var XML_write = OpenXmlWriter.Create(sheetPart))
{
XML_write.WriteStartElement(new Worksheet()); 
XML_write.WriteStartElement(new SheetData());
//Writing data using DataReader...
using (OracleDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
XML_write.WriteStartElement(new Row());
for (int i = 0; i < reader.FieldCount; i++)
{
row_number++;
}
XML_write.WriteEndElement(); //End of row
//If 1 million row exceeded then proceed writing to next sheet - here is where I'm stucked
if (row_number>1000000)
{
sheetId +=1;   
Sheet sheet1 = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = "List " + sheetId };
sheets.Append(sheet1);
XML_write.WriteEndElement(); 
XML_write.WriteEndElement(); 
XML_write.WriteStartElement(new Worksheet()); 
XML_write.WriteStartElement(new SheetData());
row_number=0;
}
}
}
XML_write.WriteEndElement(); 
XML_write.WriteEndElement(); 
XML_write.Close();
}
}     

写入文件.xlsx此代码终止并显示错误:

状态为 EndRootElement 的令牌 StartElement 将导致无效的 XML 文档。如果要编写 XML 片段,请确保将"一致性级别"设置设置为"一致性级别.片段"或"一致性级别.自动

"

如果有人对此有解决方案或建议使其工作,我将非常高兴。

PS:在某些解决方案中已经存在类似的东西 - 例如 Toad for Oracle,它在达到最大 65k 行后导出到多个工作表上的.xls文件中。所以可能可以做到。

基本上,您似乎需要交换循环的顺序。打开您的连接,然后创建一个工作表并使用它,直到计数器达到 100 万,然后关闭它并创建另一个。

下面是一些基本的伪代码。

count = 0
sheet = new
writer = new writer(sheet)
using (reader)
{
foreach (row in reader)
{
if (count % 1,000,000 == 0)
{
writer.close
sheet = new
writer = new writer(sheet)
}
writer.write(reader.read)
count++
}
}
writer.close

最新更新