Улучшить производительность при записи в MS Excel

Я сталкиваюсь с проблемами производительности при чтении/записи данных из/в ячейки MS-Excel. Я использую библиотеку объектов MS Excel 11.0 для автоматизации с VB.NET.

В настоящее время чтение и запись из/в файлы Excel занимает слишком много времени. (10 минут на чтение 1000 строк :( ). Кажется, что метод чтения и записи по ячейкам не так эффективен. Есть ли способ чтения/записи данных с использованием массовой операции?


person Vinod T. Patil    schedule 09.08.2010    source источник


Ответы (2)


Вместо того, чтобы читать ячейку за ячейкой, вы можете прочитать весь диапазон и сохранить его в 2D-массиве. Затем вы можете получить доступ к 2D-массиву, как к ячейке в Excel.

Я не очень хорошо разбираюсь в VB.NET для объектов excel, но если вы понимаете C #, быстро прочитайте эту ссылку и попытайтесь реализовать ее.

http://dotnetperls.com/excel-interop Прочтите раздел "Получение данных рабочей книги"

person ChickSentMeHighE    schedule 09.08.2010

Здорово!!!

Я использовал подход с двумерным массивом и добился огромного прироста производительности!!

Раньше я использовал метод «ячейка за ячейкой», как показано ниже.

Dim cell As Excel.Range = Nothing
cell = sheet.Cells(rowIndex, colIndex)
cell.Value = "Some value"

Раньше я перебирал диапазон ячеек и копировал значение в каждой ячейке. Здесь каждый sheet.Cells и cell.Value является вызовом взаимодействия, и для каждого вызова он вызывает вызов Excel.exe, что требует больше времени.

В 2D-подходе я заполнил данные, которые должны быть скопированы в ячейки Excel, в 2D-массив, а затем присвоил 2D-массиву значение выбранного диапазона ячеек. Как показано ниже,

Dim darray(recordCount - 1, noOfCol - 1) As String
//Fill the data in darray
//startPosRange = Get the range of cell from where to start writing data
startPosRange = startPosRange.Resize(recordCount, noOfCol)
startPosRange.Value = darray

После этих модификаций я собрал данные о производительности для обоих подходов, и результаты оказались на удивление отличными! Последний подход в 25 раз быстрее предыдущего.

Точно так же я использовал подход с двумерным массивом для чтения данных из ячеек и увидел аналогичный прирост производительности. Примеры кода показаны ниже.

Поэлементный подход,

Dim usedRange As Excel.Range = sheet.UsedRange
For Each row As Excel.Range In usedRange.Rows()
For Each cellData As Excel.Range In row.Cells
    //Gather cellData.Value in some container.
Next

подход с двумерным массивом,

Dim usedRange As Excel.Range = sheet.UsedRange
//Here the array index starts from 1. why???
Dim darray(,) As Object = CType(usedRange.Value, Object(,))

Dim rows As Integer = darray.GetUpperBound(0)
Dim cols As Integer = darray.GetUpperBound(1)
For i As Integer = 1 To rows    
    For j As Integer = 1 To cols
        Dim str As String
        If darray(i, j) Is Nothing Then
            str = ""
        Else
            str = darray(i, j).ToString
        End If
        //Use value of str
    Next
Next

См. http://support.microsoft.com/kb/306023 , http://dotnetperls.com/excel-interop (спасибо ChickSentMeHighE за ссылку)

Наслаждайтесь исполнением!!!

person Vinod T. Patil    schedule 10.08.2010
comment
Винод, спасибо, что нашли время опубликовать подробные результаты! - person Joost; 03.12.2013