Как эффективно буферизовать и очищать поток в Open XML SDK - PullRequest
7 голосов
/ 21 августа 2009

Я использую OpenXML SDK 2.0 для создания файла Excel с большим объемом данных, appox. 1000000 строк, и мне нужно оптимизировать использование памяти, потому что моя машина тормозит очень быстро.

Я хочу решить эту проблему путем сброса части сгенерированного дерева DOM в файл во время выполнения. Я делаю свою собственную буферизацию для данных. Например, у меня есть 100000 записей для записи, и я хочу сбросить поток в файл, когда я добавляю 1000 строк в таблицу Excel. Я делаю это с помощью метода worksheetPart.Worksheet.Save (). В документации говорится, что этот метод 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 ]

3 голосов
/ 21 августа 2009

SpreadsheetGear for .NET может создать книгу xlsx с 1 000 000 строк на 40 столбцов случайных чисел (это 40 миллионов ячеек) за 74 секунды (что включает в себя создание книги в памяти из случайных чисел и сохранение в диск на разогнанном Intel QX 6850 и Windows Vista 32).

Какую производительность вы видите с Open XML SDK?

Вы можете скачать бесплатную пробную версию SpreadsheetGear здесь и попробовать сами.

Я пропущу код, чтобы сгенерировать рабочую книгу на 40 миллионов ячеек ниже.

Отказ от ответственности: я владею 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 голос
/ 26 ноября 2014

Существует противоположный подход к «буферизации и сбросу» для задачи записи больших файлов Excel. Подход основан на использовании класса OpenXmlWriter и использует последовательную запись вместо буферизации и очистки. Типичное решение также использует заменяющую часть и OpenXmlReader для получения неизменного содержимого из шаблона. Посмотрите «Запись больших файлов Excel с помощью Open XML SDK» (с несколькими примерами кода) и «Запись больших документов OpenXML» (с полным примером кода).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...