Open XML 在处理大数据时性能不佳



Open xml 使用具有 24 列的模板几乎在 8 分钟内将 24k 行写入 excel 文件。我必须提高这种性能,所以我必须找到错误的东西。模板文件会导致性能不佳。但它没有任何宏。导致性能不佳将是一个错误。但我还没有看到任何关于这个的错误。我需要你的帮助。如何使用 Open XMl 提高性能,或者您有任何建议,什么是将大数据写入 excel 的最佳库。

  • 开放XML 2.5 .网络框架 4.5

工作表Part.Worksheet.Save();需要7分钟。

Stopwatch sw = new Stopwatch();
sw.Start();
FileInfo temp_excel_file = new FileInfo(Path.Combine(ConfigFile.ConfigsPaths["ExcelRaporFolder"], "temp", "Monitoring.xlsm"));
rapor_file = new FileInfo(Path.Combine(ConfigFile.ConfigsPaths["ExcelRaporFolder"], "excel", FileName + ".xlsm"));
                            File.Copy(temp_excel_file.FullName, rapor_file.FullName);
                            Log.LogYaz(rapor_file.Name + "-Excell Açılıyor..");
SpreadsheetDocument myDoc = SpreadsheetDocument.Open(rapor_file.FullName, true);
                            IEnumerable<Sheet> sheets = myDoc.WorkbookPart.Workbook.Descendants<Sheet>();
                            WorksheetPart worksheetPart = (WorksheetPart)myDoc.WorkbookPart.GetPartById(sheets.Skip(1).First().Id);
                            SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
foreach (var row_index in filtered_data)
{
 ...
 sheetData.AppendChild(Utils.CreateRow(row, 0, cell_data));
}
worksheetPart.Worksheet.Save();
myDoc.Close();
myDoc = null;
sw.Stop();

Open XML 有一个错误!Openxml 在超出缓冲容量时使用静态内存流。缓冲区BG容量是10 MB,我猜。所以当你在多线程中使用openxml时,会发生死锁。我不再在多线程中使用 open xml。

这可能有助于使用 Open XML 文件编写大型 Excel 文件,同时避免性能或内存不足异常。

尝试使用 OpenXML Writer。 它比简单的 foreach 语句更好。请看这里

          using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(filename, true))
            {
                //For Diagonostice Only
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
                WorkbookPart workbookPart = spreadSheet.WorkbookPart;
                WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
                string origninalSheetId = workbookPart.GetIdOfPart(worksheetPart);
                WorksheetPart replacementPart = workbookPart.AddNewPart<WorksheetPart>();
                string replacementPartId = workbookPart.GetIdOfPart(replacementPart);
                OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
                OpenXmlWriter writer = OpenXmlWriter.Create(replacementPart);

                int rec = 0;
                #region Looping through data
                while (reader.Read())
                {
                    if (reader.ElementType == typeof(SheetData))
                    {
                        if (reader.IsEndElement)
                            continue;
                        writer.WriteStartElement(new SheetData());

                        for (int row = 0; row < listData.Count; row++)
                        {
                            if (!string.IsNullOrEmpty(listData[row].WorkOrder))
                            {
                                Row newRow = new Row();
                                writer.WriteStartElement(newRow);
                                for (int col = 0; col < 5; col++)
                                {
                                    Cell newCell = new Cell();
                                    CellValue cellValue = new CellValue();
                                    //assigning value 
                                    cellValue.Text = row.ToString();
                                    //appending the value to cell
                                    newCell.Append(cellValue);
                                    writer.WriteElement(newCell);
                                }
                                writer.WriteEndElement();
                            }
                        }
                        writer.WriteEndElement();
                    }
                    else
                    {
                        if (reader.IsStartElement)
                        {
                            writer.WriteStartElement(reader);
                        }
                        else if (reader.IsEndElement)
                        {
                            writer.WriteEndElement();
                        }
                    }
                }
                #endregion
                reader.Close();
                writer.Close();
                //replace the templateSheet with DataSheet.                  
                Sheet sheet = workbookPart.Workbook.Descendants<Sheet>()
                       .Where(s => s.Id.Value.Equals(origninalSheetId)).First();
                sheet.Id.Value = replacementPartId;
                workbookPart.DeletePart(worksheetPart);
            }

尝试加载文件内容并将其写入内存流中,寻找开头并使用此内存流打开文档。保存操作后,您可以将内存流的内容写回文件。

我不确定它是否会对您有所帮助,但我自己正在打开 Word 中使用此序列。

检查 foreach 循环和 Utils.CreateRow(row, 0, cell_data) 函数所花费的时间。基于此,使用 Linq 优化代码。

谢谢!

最新更新