更新2(17/21/17)
我发现只有在删除模块中的一个(或全部)导入工作表时,才会在点击“提交”按钮后尝试打开Excel工作簿。 (该过程会在重新提交之前删除旧工作表以清除工作簿以重新开始)。对于手动测试,我点击提交按钮,删除任何导入的工作表,然后尝试打开任何 excel文件,然后崩溃。我还确保在删除工作表时删除所有已解散的命名范围。我还在一个只导入空白表的文件上对此进行了测试。然后我删除它,并能够打开工作簿就好了。我想避免创建我的模块(因为它是一种拖累)。
原始问题
我有一个Excel工作簿工具,可以在处理完一些信息后打开其他Excel工作簿并从这些工作簿中导入工作表。
总共有5个模块工作簿。在较高的层次上,这些工作簿是相同的 - 表单结构,通用代码结构等。有不同的公式,一些命名的范围是不同的等等。
在主工具中,可以重新运行从不同工作簿中提取信息的代码。它基本上重置原始工作簿,然后再次运行代码。这是在不关闭原始工作簿的情况下完成的。 (用户可以刷新Web服务数据并重新运行该工具)。
我面临的问题是,当我重新运行两个模块工作簿的过程时,Excel会在重新运行期间崩溃,此时代码会尝试打开模块工作簿。其他3个模块工作簿运行良好。我可以运行并重新运行并重新运行......其他2次每次都会崩溃。
我已经对文件进行了大量研究,看看为什么会发生这种情况,但还没有找到原因。进程运行后,主工作簿中没有任何链接,没有数据连接,没有错误的链接等。
另外,有趣的是我存储在UAT环境文件夹中的文件一直运行良好。生产文件夹中的文件失败。我甚至将文件直接从UAT环境文件夹复制到生产环境文件夹,但仍然失败。我还排除了文件夹级别的权限和安全性。
我也可以在第一次提交代码后手动打开文件。
我意识到这可能略微超出了SO的范围并且有点模糊,但是希望有人可能有类似的经历并且可以解释一些。
更新
相关代码如下。基于@Ralph的评论,我通过添加行Set wbLOB = Nothing
强制进行内存擦除,但不幸的是,问题仍然存在。
Function LoadLOB(sLOB As String, sXMLFile As String) As Boolean
Dim sLOBFile As String
sLOBFile = wsReference.Range("ModuleFolder").Value2 & sLOB & "\" & sLOB & ".xlsb"
Dim wbLOB As Workbook
Set wbLOB = Workbooks.Open(sLOBFile) '--> 2nd run crashes on this line.
If TieXMLToExcel(wbLOB, sXMLFile, sLOB) Then
MapXMLFieldsToExcelCells wbLOB, sLOB
Select Case sLOB
Case Is = "Property"
SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tCommonLocationProperty", "Location_ID"
SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tLocationByCoverageTypeProperty", "Location_ID"
Case Is = "GeneralLiability": SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tClassCodesByLocationGeneralLiability", "Location_ID"
Case Is = "CommercialAuto": SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tVehicleSummaryCommercialAuto", "AuVehicleNo"
Case Is = "Crime": SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tCommonLocationCrime", "Location_ID"
End Select
Application.Run wbLOB.Name & "!PrepareSheetForMasterFile", ThisWorkbook
wbLOB.Close False
LoadLOB = True
End If
Set wbLOB = Nothing
End Function
答案 0 :(得分:2)
我怀疑这是答案,但我认为这是一个更好的论坛,可以交换我在这个问题上的想法。我做的是我抓住了一些Windows API来检查该文件是否打开,然后再尝试打开它。我还添加了一个关闭文件的方法,并使SaveChanges参数更加明确。我还在那里添加了一些DoEvents,以防有些东西等待完成。
希望这是其他想法的起点。我希望其中一些有帮助。
'Determine whether a file is already open or not
#If VBA7 And Win64 Then
Private Declare PtrSafe Function lOpen Lib "kernel32" Alias "_lopen" (ByVal lpPathName As String, ByVal iReadWrite As Long) As Long
Private Declare PtrSafe Function lClose Lib "kernel32" Alias "_lclose" (ByVal hFile As Long) As Long
#Else
Private Declare Function lOpen Lib "kernel32" Alias "_lopen" (ByVal lpPathName As String, ByVal iReadWrite As Long) As Long
Private Declare Function lClose Lib "kernel32" Alias "_lclose" (ByVal hFile As Long) As Long
#End If
Function LoadLOB(ByVal sLOB As String, _
ByVal sXMLFile As String) As Boolean
Dim sLOBFile As String
Dim wbLOB As Workbook
sLOBFile = wsReference.Range("ModuleFolder").Value2 & sLOB & "\" & sLOB & ".xlsb"
'Make sure the file is closed before processing
If Not isFileOpen(sLOBFile) Then
Set wbLOB = Workbooks.Open(sLOBFile, 0, False)
Else
'Close it if it is open
closeWB sLOBFile
Set wbLOB = Workbooks.Open(sLOBFile, 0, False)
End If
If TieXMLToExcel(wbLOB, sXMLFile, sLOB) Then
MapXMLFieldsToExcelCells wbLOB, sLOB
Select Case sLOB
Case Is = "Property"
SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tCommonLocationProperty", "Location_ID"
SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tLocationByCoverageTypeProperty", "Location_ID"
Case Is = "GeneralLiability": SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tClassCodesByLocationGeneralLiability", "Location_ID"
Case Is = "CommercialAuto": SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tVehicleSummaryCommercialAuto", "AuVehicleNo"
Case Is = "Crime": SortTableByAscendingColumn wbLOB, "xml" & sLOB, "tCommonLocationCrime", "Location_ID"
End Select
Application.Run wbLOB.Name & "!PrepareSheetForMasterFile", ThisWorkbook
DoEvents
wbLOB.Close SaveChanges:=False
LoadLOB = True
End If
Set wbLOB = Nothing
End Function
Sub closeWB(ByVal FilePath As String)
Dim wb As Workbook
For Each wb In Application.Workbooks
If wb.FullName = FilePath Then
wb.Close SaveChanges:=False
Set wb = Nothing
DoEvents
Exit For
End If
Next
End Sub
Function isFileOpen(ByVal FileName As String) As Boolean
Dim FileNumb As Long: FileNumb = -1
Dim lastErr As Long
FileNumb = lOpen(FileName, &H10)
'Determine if we can open the file
If FileNumb = -1 Then
lastErr = Err.LastDllError
Else
lClose (FileNumb)
End If
' Check if there is a sharing violation and report back status
isFileOpen = (FileNumb = -1) And (lastErr = 32)
End Function
答案 1 :(得分:1)
不确定这个答案会有多大帮助,但我从头开始重新创建模块文件,它们适用于所有环境。很可能是文件中的一个小腐败,我找不到。