从访问excel缓慢导出

时间:2009-10-09 07:17:07

标签: vb.net excel ms-access

我必须从访问数据库生成大约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 个答案:

答案 0 :(得分:1)

在完成工作簿后(在循环内),您是否正在关闭工作簿?

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

查看this线程,解释了释放所有COM接口的必要性。

编辑:我在回复@ 1800信息时看到了您的意见。

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

这个linq查询做了什么?

EDIT2:尝试在MS-Access中运行SQL以查看它的执行情况? 另外,我建议暂时放弃LINQ&使用普通的旧ADO.net Command对象和参数化查询。

另外,简单&愚蠢的方法是将所有记录(最小和最大值之间的ID)拉入DataTable并在内存中过滤并进行某种直接传输(不使用数组并避免逐行逐行写入值)。

如果有可能的话,我会尽力找出来。 (即使用过滤后的数据集并将其写入excel文件)。

希望能给你一些关于如何继续的提示。

答案 1 :(得分:1)

您可以尝试使用Docmd传输电子表格,因为这应该更快

DoCmd.Transferspreadsheet ....

然后您可以随后使用Excel自动打开文件

答案 2 :(得分:1)

而不是Rows Insert我会尝试使用CopyFromRecordset来完成整个记录集。当然,你必须大大改变你的逻辑。

但更重要的是,一旦完成Excel电子表格对象,你在哪里关闭它?

答案 3 :(得分:0)

我不知道,但我会查看您最终在Excel中同时打开的文件数量。完成写入后,您是否关闭文件?也许是让它们保持开放状态,所以当第150个工作表打开时,它可能会在内存使用上挣扎。另外,我会说,尝试逐步调试调试器中的代码,看看哪个位慢(或随着时间的推移变慢) - 这将有助于缩小问题的原因。

答案 4 :(得分:-1)

快速查看代码会让我质疑每行调用.Rows(n).Insert(Excel.XlDirection.xlDown,1)。您应该能够为所有行调用Insert一次。即使您只插入1行,在工作表中插入行也很昂贵 - 特别是如果要插入大型工作表或插入包含许多公式的工作簿中。

SpreadsheetGear for .NET通常会加速您的应用程序(您可以在页面的右侧看到一些确认此here的引号)。 SpreadsheetGear还有一个IRange.CopyFromDataTable方法,因此您不必将数据复制到临时数组。 SpreadsheetGear API类似于Excel的API,因此转换代码非常简单。如果您想试用,可以免费试用here

免责声明:我拥有SpreadsheetGear LLC