excel - VBA - 1004:应用程序定义或对象定义的错误仅在导出到包含大量数据的 Excel 时出现
问题描述
我最近从我的 Access VBA 代码中得到了这种奇怪的行为,我无法弄清楚为什么会发生这个错误。
我正在尝试将数据从数据库导出到 Excel 文件。我操作了一些单元格和范围(主要是插入信息,但有时合并单元格、插入新行等),但是,我不断收到此错误:
1004 应用程序定义或对象定义错误
在这条线上:
xlApp.Cells(currentRowPointer, 8) = rs_vendorNPO("Vendor_Name")
现在,这条线被调用了几十次,因为我正在循环多个记录集,而这条线在循环内。当currentRowPointer = 91
. currentRowPointer
因此,要查看91时的变量值,我在上面添加了以下内容:
If currentRowPointer = 91 Then
Stop
End If
xlApp.Cells(currentRowPointer, 8) = rs_vendorNPO("Vendor_Name")
Stop
基本上会添加一个动态断点。因此,它在 时停止currentRowPointer = 91
,并且所有值似乎都正常。我再次点击运行。这一次,它没有失败91
,它失败了114
。每次我这样做时,它都会在 114 上失败。所以我将其添加到 if 语句中:
If currentRowPointer = 91 Or currentRowPointer = 114 Then
Stop
End If
xlApp.Cells(currentRowPointer, 8) = rs_vendorNPO("Vendor_Name")
果然,它运行得很好。为了查看它是否与该迭代有任何关系,我将 if 语句更改为:
If currentRowPointer = 87 Or currentRowPointer = 114 Then
Stop
End If
只是看看会发生什么。在第一个断点之后87
,它没有失败114
,它失败了111
。下次我运行它时,它失败了112
。
这清楚地表明它与该迭代无关,并且是 Access 内部的东西。
作为最后一项测试,我在该行上放置了一个断点(并在Stop
调用中删除了 if 语句)。我遍历了整个流程,没有错误。
问题:
什么可能导致此问题?一遍又一遍地调用相同的行,但只是在一段时间后它似乎失败了。同样,当我导出到 excel 的数据很小并且运行时间很快时,也不会出现此问题。
这让我相信这是某种内存问题?如果是这样,我该怎么做才能调试/确保它不会发生?
这是我打开文件的地方:
Public xlApp As Excel.Application
Public wb As Excel.Workbook
Private Function openSpendReport(templatePath As String, filePath As String, JobID As String)
On Error GoTo ErrorHandler
Set xlApp = CreateObject("Excel.Application")
'make a copy, file must be closed
FileCopy templatePath, filePath
xlApp.Visible = True
Set wb = xlApp.Workbooks.Open(filePath)
xlApp.Sheets("Summary Template").Select
Exit Function
ErrorHandler:
DoCmd.Hourglass False
If Err.Number = 70 Then
MsgBox "Close the file before running the report"
Else
MsgBox (Err.Number & ": " & Err.Description)
End If
End
End Function
这是发生错误的函数(我添加了一行 = 符号来突出显示它):
Private Sub getVendorNonPO(JobID As Variant)
On Error GoTo ErrorHandler
Dim rs_vendorNPO As DAO.Recordset
sql = "<sql_statement>"
Set rs_vendorNPO = CurrentDb.OpenRecordset(sql)
If Not rs_vendorNPO.EOF Then
Do Until rs_vendorNPO.EOF
'add a row if necessary
If (poRowsCount >= 8) Then
If (cellsMerged = 0) Then
xlApp.Range("A" & poLineRow & ":" & "C" & currentRowPointer + 1).UnMerge 'unmerge cells
xlApp.Range("D" & poLineRow & ":" & "F" & currentRowPointer + 1).UnMerge
xlApp.Range("G" & poLineRow & ":" & "G" & currentRowPointer + 1).UnMerge
cellsMerged = 1
End If
Dim rng As Range
Set rng = xlApp.Range("A" & currentRowPointer)
xlApp.Rows(rng.Row).Copy
xlApp.Rows(rng.Row).Insert Shift:=xlDown
Debug.Print ("copying cells and shifting copied cells down")
' keep track of the added rows
poRowsAdded = poRowsAdded + 1
End If
Debug.Print ("in with 1")
Debug.Print ("current row pointer: " & currentRowPointer)
Debug.Print ("vendor name" & rs_vendorNPO("vendor_name"))
' ==========================================================================================================
' Issue is here
' ==========================================================================================================
xlApp.Worksheets("Summary Template").Cells(currentRowPointer, 8) = rs_vendorNPO("Vendor_Name")
Debug.Print ("in with 2")
xlApp.Cells(currentRowPointer, 8) = rs_vendorNPO("Vendor_Name")
xlApp.Cells(currentRowPointer, 12) = rs_vendorNPO("InvoiceNum")
xlApp.Cells(currentRowPointer, 13) = rs_vendorNPO("InvoiceDate")
xlApp.Cells(currentRowPointer, 14) = rs_vendorNPO("LineAmountConverted")
xlApp.Cells(currentRowPointer, 10) = rs_vendorNPO("InvoiceDate")
xlApp.Cells(currentRowPointer, 11) = rs_vendorNPO("LineAmountConverted")
If Not IsNull(rs_vendorNPO("ProofOfPayment")) Then
xlApp.Cells(currentRowPointer, "O") = rs_vendorNPO("ProofOfPayment")
End If
currentRowPointer = currentRowPointer + 1
poRowsCount = poRowsCount + 1
rs_vendorNPO.MoveNext
Loop
rs_vendorNPO.Close
Set rs_vendorNPO = Nothing
End If
Exit Sub
ErrorHandler:
DoCmd.Hourglass False
MsgBox (Err.Number & ": " & Err.Description & ". " & Err.Source)
wb.Save
xlApp.Quit
Set xlApp = Nothing
End
End Sub
以下是一些调试语句的输出(已删除敏感信息):
...
in with 1
current row pointer: 90
vendor name_____
in with 2
copying cells and shifting copied cells down
in with 1
current row pointer: 91
vendor name_____
调试语句从 83 开始。它们都发生在同一个循环中,所以我只显示最后一对。您可以看到它获取供应商名称并在之后立即失败。
解决方案
从外部(例如 Access)处理 Excel 对象时,最好始终严格遵循对象的层次结构,即:
Application -> Workbook -> Worksheet -> .Cells, .Range, ...
我不确定这会解决您的问题,但恕我直言,机会很大。
所以你应该这样做:
Dim sh As Excel.Worksheet ' or Public, if you really need
Set wb = xlApp.Workbooks.Open(filePath)
Set sh = wb.Worksheets("Summary Template")
' The following is not necessary for the code to work, only if you want to watch what happens
sh.Select
然后将您必须xlApp
的所有内容更改为正确的参考:
xlApp.Range => sh.Range
xlApp.Rows => sh.Rows
xlApp.Cells => sh.Cells
xlApp.Worksheets("Summary Template").Cells => sh.Cells
推荐阅读
- api - Laravel 自定义路由文件不适用于新路由
- spring-boot - Jpa ManyToMany 连接表更新
- azure-blob-storage - Kusto\KQL - 为简单计数值渲染时间图
- c++ - .so 名称冲突的 C++/CMake 可安装库
- python - pyinstaller --onefile 参数不适用于 pygame
- asp.net-core - SqlKata如何从列表中插入许多值
- html - WordPress favicon - 仅在后端显示
- photoshop - 如何在 Photoshop 文档中的所有图层的最外边缘放置 1 px 宽的黑色边框?
- python - 安装了 BS4,但当我从 macos high sierra 运行 python 脚本时得到回溯“ImportError:没有名为 bs4 的模块”
- javascript - Google App Script 将背景从驱动器设置为网络应用程序