代码之家  ›  专栏  ›  技术社区  ›  Iulian

从访问Excel的速度较慢

  •  0
  • Iulian  · 技术社区  · 15 年前

    我必须从Access数据库生成大约800个Excel文件。

    对于前10-15个Excel文件,它工作得很好,只需要几秒钟/Excel文件,但它总是需要更长的时间,而对于第150个Excel文件,它需要10分钟。

    这是我的代码:

    它为访问表中的每个nrlist执行此操作(大约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 回复  |  直到 14 年前
        1
  •  1
  •   Tony Toews    15 年前

    我试着用copyFromRecordset来完成整个记录集,而不是插入行。当然,你必须大量修改你的逻辑。

    但更重要的是,一旦完成Excel电子表格对象,您将在何处关闭它?

        2
  •  1
  •   Mark3308    15 年前

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

    DoCmd.Transferspreadsheet ....
    

    然后,您可以在以后使用Excel自动化打开文件。

        3
  •  1
  •   shahkalpesh    15 年前

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

    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命令对象。

    或者,一种简单而愚蠢的方法是将所有记录(其中ID在最小值和最大值之间)拉到数据表中,并在内存中对其进行筛选,然后执行某种直接传输(不使用数组,并且避免逐行、逐单元写入值)。

    如果可能的话,我会设法找出答案。(即使用过滤后的数据集并将其写入Excel文件)。

    希望能给你一些关于如何进行的提示。

        4
  •  0
  •   1800 INFORMATION    15 年前

    我不知道,但我会看看你最终在Excel中同时打开了多少文件。完成对文件的写入后是否关闭这些文件?也许它保持了它们的开放性,所以当第150个工作表打开时,它可能正在为内存的使用而苦苦挣扎。另外,我会说,尝试在调试程序中单步执行代码,看看哪个位慢(或者随着时间的推移变慢)——这将有助于缩小问题的原因。

        5
  •  -1
  •   Joe Erickson    15 年前

    快速查看您的代码会让我质疑对.rows(n).insert(excel.xldirection.xldown,1)的调用。您应该能够对所有行调用一次insert。在工作表中插入行的成本很高,即使只插入一行,尤其是在插入大型工作表或具有许多公式的工作表时。

    SpreadsheetGear for .NET 通常会加快应用程序的速度,如您的应用程序(您可以看到一些报价确认这一点 here -在页面的右侧)。SpreadsheetGear还具有irange.copyFromDataTable方法,因此您不必将数据复制到临时数组。电子表格齿轮API类似于Excel的API,因此直接转换代码。你可以下载免费试用版 here 如果你想试试的话。

    免责声明:我拥有SpreadsheetGear LLC