OpenXML - 在不消耗内存的情况下编辑大型 Excel 文件

OpenXML - Edit large Excel file without memory drain

提问人:Lucy82 提问时间:10/13/2023 更新时间:10/13/2023 访问量:46

问:

我正在使用 SAX 方法直接使用 DataReader(无内存中)写入 .xlsx 文件,这效果很好。但我也希望 Excel 文件中的列是自动调整的。

使用 SAX 方法意味着直接使用 OpenXmlWriter 编写 .xlsx 文件,不幸的是,仅在一个方向上(在 xml 树上)。由于 xml 顺序,列必须在实际数据之前写入,这意味着我无法计算它们的宽度,因为 DataReader 尚未打开。

过去,我通过执行两次DataReader来实现自动调整 - 第一次用于搜索最长的字符串以计算列宽,然后用于将实际数据写入.xlsx文件。这在编写大文件时很耗时,所以我对此不满意。

我看到的唯一选项是编辑 .xlsx 文件,但我找不到任何 SAX 方法。

我设法使用下面的方法进行自动调整,但是当 Linq 参与其中时,它会消耗巨大的内存(2Mb 文件需要 300GB 内存,大约 1 mio 行):

private void Autofit(string _filename) 
{
   using (SpreadsheetDocument Excel = SpreadsheetDocument.Open(_filename, true))
   {
      foreach (var wp in Excel.WorkbookPart.WorksheetParts)
      {
        //This line drains 2GB memory, tested on 1 mio rows for .xlsx file  
        var sd = wp.Worksheet.Descendants<SheetData>().First();

        var cs = new Columns();
     
        uint Col_index = 1;

        //MaxText is List<string>, containing longest strings of each column
        foreach (var longest_string in MaxText) 
        { 
          //CalculateWidth is a method for calculating column width
          double cell_width = CalculateWidth(new System.Drawing.Font("Arial", 10), longest_string) + 1.5;

          Column c = new Column { Min = Col_index, Max = Col_index, Width = cell_width, CustomWidth = true };

          cs.Append(c);

          Col_index++;
        }
        wp.Worksheet.InsertAfter(cs, sd);       
      }
   }           
 }

我还有什么可以尝试使用 OpenXml 的吗?或者也许是 xlst 转换,XStreamingElement ?或者我可以修复上层 Linq 方法以不消耗此类内存? 任何示例或链接将不胜感激。

Excel XSLT LINQ-to-XML OpenXML

评论

0赞 dbc 10/14/2023
是从某个本地数据库读取数据,还是通过网络获取数据?DataReader
0赞 Lucy82 10/14/2023
@dbc,不知道为什么这很重要,或者本地数据库和有线数据库之间到底有什么区别,但我在我的机器上安装了 Oracle 客户端,它允许我通过连接字符串连接到位于服务器上的数据库。所以我想我有远程数据库,但我也可以访问它(表和其他对象)。
0赞 dbc 10/14/2023
XML 文件只是一个文本文件,因此在编写它时实际上没有办法向后寻求更新一些以前编写的元素。但是,如果 DataReader 通过网络读取数据,则将结果流式传输到某个本地临时文件并在执行此操作时计算最大宽度,然后将临时文件的内容流式传输到最终的 OpenXML 文件可能会更快。
0赞 Lucy82 10/15/2023
@dbc有趣的意见,我会考虑一下。但是,流式传输也意味着一些内存消耗。

答: 暂无答案