如何在Open XML SDK中有效地缓冲和刷新流

时间:2009-08-21 06:59:13

标签: c# xml excel performance

我使用OpenXML SDK 2.0生成包含大量数据的appox,appox。 1000000行,我需要优化内存使用,因为我的机器速度很慢。

我想通过在运行时将部分生成的DOM树刷新到文件中来解决此问题。我为数据做了自己的缓冲。 E.g我有100000条记录要写,当我在Excel工作表中添加1000行时,我想将flush stream转换成文件。我通过使用方法worksheetPart.Worksheet.Save()来实现这一点。 Documantation说这个方法Save():“将DOM树中的数据保存回部分。它也可以多次调用。每次调用它时,流都会被刷新。”

         foreach (Record m in dataList)
         {
            Row contentRow = CreateContentRow(index, m);         // my own method to create row content

            //Append new row to sheet data.
            sheetData.AppendChild(contentRow);

            if (index % BufferSize == 0)
            {
                worksheetPart.Worksheet.Save();
            }

            index++;

        }

这种方法有效,因为内存使用图表已经看到形状,但不幸的是,内存使用量会随着时间的推移而增长。

有谁知道如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

SpreadsheetGear for .NET可以在74秒内创建一个包含1,000,000行×40列随机数(即4000万个单元格)的xlsx工作簿(包括在随机数中创建内存中的工作簿并在超频的英特尔上保存到磁盘) QX 6850和Windows Vista 32)。

您对Open XML SDK有何看法?

您可以下载SpreadsheetGear here的免费试用版并亲自试用。

我将通过代码生成下面的4000万个单元格工作簿。

免责声明:我拥有SpreadsheetGear LLC

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SpreadsheetGear;

namespace ConsoleApplication10
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Run once with 100 rows and then run forever with 1,000,000 rows.
                for (int rows = 100; rows <= 1000000; rows = 1000000)
                {
                    Console.Write("rows={0}, ", rows);
                    var startMemory = System.GC.GetTotalMemory(true);
                    var timer = System.Diagnostics.Stopwatch.StartNew();
                    var workbook = BuildWorkbook(rows);
                    var usedMemory = System.GC.GetTotalMemory(true) - startMemory;
                    Console.WriteLine("usedMemory={0}, time={1} seconds, workbook.Name={2}", usedMemory, timer.Elapsed.TotalSeconds, workbook.Name);
                    workbook = null;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("got exception={0}", e.Message);
            }
        }

        static IWorkbook BuildWorkbook(int rows)
        {
            var workbook = Factory.GetWorkbook();
            var worksheet = workbook.Worksheets[0];
            var values = (SpreadsheetGear.Advanced.Cells.IValues)worksheet;
            Random rand = new Random();
            int cols = 40;
            for (int col = 0; col < cols; col++)
            {
                for (int row = 0; row <= rows; row++)
                {
                    values.SetNumber(row, col, rand.NextDouble());
                }
            }
            workbook.SaveAs(string.Format(@"c:\tmp\Rows{0}.xlsx", rows), FileFormat.OpenXMLWorkbook);
            return workbook;
        }
    }
}

答案 1 :(得分:0)

&#34;缓冲区和刷新&#34;有相反的方法。用于编写大型Excel文件的任务。该方法基于使用OpenXmlWriter类并使用顺序写入而不是缓冲和刷新。一个典型的解决方案还使用替换部件和OpenXmlReader来从模板中获取未更改的内容。查看"Writing Large Excel Files with the Open XML SDK"(包含一些代码示例)和"Write large OpenXML docs"(完整代码示例)。