медленный экспорт из доступа к Excel - PullRequest
0 голосов
/ 09 октября 2009

Мне нужно сгенерировать около 800 файлов Excel из базы данных доступа.

Для первых 10-15 из них он работает хорошо, файл в несколько секунд / excel, но он постоянно занимает больше времени, в 150-м файле Excel - 10 минут.

Вот мой код:

Это делается для каждого nrliste в таблице доступа (около 800 из них)

Dim lista = From ls In Liste _
                        Where ls!Concatenare = nrliste(i) _
                     Select ls
            Dim table = lista.CopyToDataTable
            Dim DataArr(table.Rows.Count, 30)

            For x = 0 To table.Rows.Count - 1
                For y = 0 To 30
                    DataArr(x, y) = table.Rows(x).Item(y)
                Next
            Next


            Dim filetocopy As String
            Dim newcopy As String
            Dim tempname As String = nrliste(i).ToString
            Dim filename As String = "LISTA INV OBI(MF) LA 30.09.2009_" & tempname.Replace("#", "_")
            filetocopy = Environment.CurrentDirectory & "\MACHETA.xls"
            newcopy = FolderBD.SelectedPath & "\" & filename & ".xls"
            If System.IO.File.Exists(newcopy) = True Then
                System.IO.File.Delete(newcopy)
                System.IO.File.Copy(filetocopy, newcopy)
            Else
                System.IO.File.Copy(filetocopy, newcopy)
            End If

            'excel file
            Dim xlWBook As Excel.Workbook = xlApp.Workbooks.Open(newcopy)
            Dim xlSheet As Excel.Worksheet = CType(xlWBook.Worksheets("Lista inventar OBI de natura MF"), Excel.Worksheet)

            'insereaza liniile necesare
            For n = 11 To ((lista.Count - 1) + 11)
                With xlSheet
                    .Rows(n).Insert(Excel.XlDirection.xlDown, 1)
                End With
            Next

            'copiaza datele

            With xlSheet

                .Range(.Cells(11, 1), .Cells(table.Rows.Count + 11, 31)).Value = DataArr

            End With

Ответы [ 5 ]

1 голос
/ 10 октября 2009

Вместо вставки строк я бы попробовал CopyFromRecordset сделать весь набор записей. Конечно, вам придется существенно переработать логику.

Но что более важно, где вы закрываете объект электронной таблицы Excel, как только закончите с ним?

1 голос
/ 09 октября 2009

Вы закрываете книгу после того, как с ней покончено (внутри цикла)?

xlWBook.Close
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWBook)

Посмотрите на этот поток , который объясняет необходимость освобождения всех интерфейсов COM.

РЕДАКТИРОВАТЬ: Я видел ваши комментарии, в ответ на @ 1800 Информация.

Dim lista = From ls In Liste _
                        Where ls!Concatenare = nrliste(i) _
                     Select ls

Что делает этот запрос linq?

EDIT2: попробуйте запустить SQL внутри MS-Access, чтобы посмотреть, как он работает? Также я предлагаю отказаться от LINQ на данный момент и использовать обычный старый объект ADO.net Command с параметризованным запросом.

В качестве альтернативы, простой и глупый способ состоит в том, чтобы вытянуть все записи (где ID между вашим минимальным и максимальным значением) в DataTable, отфильтровать его в памяти и выполнить какой-то прямой перенос (без использования массива и избежать записи строки значений). строка за ячейкой).

Я постараюсь выяснить, возможно ли это. (т.е. используйте отфильтрованный набор данных и запишите его в файл Excel).

Надеюсь, что это даст вам какой-то намек на то, как действовать.

1 голос
/ 09 октября 2009

Вы можете попробовать использовать электронную таблицу перевода Docmd, так как она должна быть быстрее

DoCmd.Transferspreadsheet ....

Затем вы всегда можете открыть файл с помощью автоматизации Excel.

0 голосов
/ 09 октября 2009

Беглый взгляд на ваш код заставляет меня подвергать сомнению вызов .Rows (n) .Insert (Excel.XlDirection.xlDown, 1) для каждой строки. Вы должны быть в состоянии вызвать Insert один раз для всех строк. Вставка строк в лист стоит дорого, даже если вы просто вставляете 1 строку, особенно если вы вставляете в большой лист или в книгу с множеством формул.

SpreadsheetGear for .NET обычно ускоряет работу таких приложений, как ваше (вы можете увидеть некоторые цитаты, подтверждающие это здесь - в правой части страницы). SpreadsheetGear также имеет метод IRange.CopyFromDataTable, поэтому вам не придется копировать данные во временный массив. SpreadsheetGear API похож на Excel API, поэтому преобразование вашего кода просто. Вы можете скачать бесплатную пробную версию здесь , если хотите попробовать.

Отказ от ответственности: я владею SpreadsheetGear LLC

0 голосов
/ 09 октября 2009

Не знаю, но я бы посмотрел, сколько файлов вы открываете в Excel одновременно. Вы закрываете файлы после того, как закончите писать в них? Может быть, он держит их открытыми, поэтому к моменту открытия 150-го рабочего листа может возникнуть проблема с использованием памяти. Кроме того, я бы сказал, попробуйте пройти по коду в отладчике и посмотреть, какой бит медленный (или замедляется со временем) - это поможет сузить причину проблемы.

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