Excel插件中未使用的函数仅在第二次运行时以及通过VBScript运行时导致崩溃

对不起,长的标题。

我有几个共享很多代码的.xlsm文件,所以我将重复的部分移到了一个插件.xlam文件中。 我一直在使用.vbs脚本逐个打开所有文件,并在每个文件中运行一个macros。

问题

我遇到的问题是在.vbs脚本的第二次运行中,excel崩溃,并给出了一个非常普遍的错误, 这里说是“自动化错误”:

Script: C:\Users\~\Desktop\test\test.vbs Line: 5 Char: 1 Error: The server threw an exception. Code: 80010105 Source: (null) 

令我惊讶的是,即使删除了99%的文件内容,我仍然能够重现此崩溃。

test.vbs:

 Dim xlApp Dim xlBook Set xlApp = CreateObject("Excel.Application") Set xlBook = xlApp.Workbooks.Open("C:\Users\~\Desktop\test\test.xlsm") xlApp.Run "Auto.Run" '<~~ error on this line xlBook.Save xlBook.Close (True) xlApp.Quit Set xlBook = Nothing Set xlApp = Nothing 

test.xlsm:

test.xlam有一个模块Module1,test.xlsm有一个Module Auto和一个对test.xlam的引用

test.xlsm, Auto

 Sub Run() MsgBox "hello" Test.Load MsgBox "goodbye" End Sub 

test.xlam, Module1

 Sub Load() MsgBox "Load" End Sub Function Other() End Function 

Other()函数注释掉,代码工作正常(说你好,加载和再见)。 如果macros从excel内运行,它也可以正常工作。 只有在存在Other()时, Run()通过.vbs文件运行时才会出现错误(在hello之后)。

解决方法

如果我打开test.xlsm ,保存它,并在每次运行test.vbs之间重新closures它,则没有任何问题。 我相信这与插件而不是电子表格有关,因为在我的原始脚本中,打开了多个excel文件,只需要打开和保存一个文件。

我也注意到,excel文件在“问题”状态下稍微大一点,一旦我打开并保存,它就会恢复到原来的小一点。 ( 编辑:这至less部分是由vbaProject.bin文件中的新cachingstream__SRP_4和__SRP_5引起的,我使用这个答案 (哦, 这个 )提取了这个文件。手动删除所有SRP条目之后,我就可以运行了。 vbs脚本再次没有问题,虽然就像open-save-close策略一样,它只是暂时的,然后会在第三次运行而不是第二次运行时崩溃。

addins不适合共享代码? 可能他们不包含function? 除了我现在正在做的事,还有什么办法可以解决这个崩溃吗?

任何想法表示赞赏。

这听起来像第一个实例没有被卸载/第二个实例被调用之前释放。 也许使用Application.Wait方法等待几秒钟,然后在每个后续运行执行可能会有所帮助?

 'Open file1 'Run macro from file1 'Close file1 Application.Wait(Now + TimeValue("0:00:10")) 'wait 10 seconds 'Open file1 'Run macro from file1 ... ... So on 

要通过vbscript安装您的加载项,您可以使用下面的代码

 'Launch Excel set objExcel = createobject("Excel.Application") strAddIn = "ESP Assistant.xlam" '~~> Path where the XLAM resides SourcePath = "Your source path\" & strAddIn 'Add the AddIn On Error Resume Next With objExcel 'Add Workbook .Workbooks.Add 'Show Excel objExcel.Visible = True .AddIns.Add(SourcePath, False).Installed = True End With 

如果失败,可能需要先清除registry值,然后重新运行上述脚本

 'File to use just in case Add-In installation fails 'Refreshes Excel Registry Entries to allow for clean install of Add-In Dim objFSO, objShell Set objFSO = CreateObject("Scripting.FileSystemObject") Set objShell = WScript.CreateObject ("WScript.shell") objShell.Run "cmd /c ""C:\Program Files (x86)\Microsoft Office\Office14\excel.exe"" /unregserver && timeout /t 3 && tskill excel && ""C:\Program Files (x86)\Microsoft Office\Office14\excel.exe"" /regserver",1,True Set objFSO = Nothing Set objShell = Nothing x=msgbox("Excel registry refreshed." ,0, "Registry Update") wscript.quit 

不幸的是,我仍然不知道为什么会发生这种情况,但是我发现了一个我将要坚持的自动化解决scheme。

正如我在我的问题中提到的那样,test.xlsm文件在“问题”状态下有点大,至less部分是由于某种caching,在这里我只能find一个官方的提示:

2.2.6 SRPstream

指定特定于实现和依赖于版本的性能caching的stream。 阅读时必须忽略。 写作时绝不能出席。 每个这些stream的名称由以下ABNF语法指定:

SRPStreamName = "__SRP_" 1*25DIGIT

我的解决scheme是删除caching,我一开始用这个工具手动。 当这似乎工作,我写了一个Java程序自动执行( 在这里主旨)。 它是java.util.zip和Apache POIFS之间的粘合剂 。

我还添加了一行来在.vbs脚本的末尾调用Java:

 CreateObject("WScript.Shell").Run "java -jar clear-excel-cache.jar C:\Users\~\Desktop\test\test.xlsm", 1, false 

在我的实际的.vbs文件中,它在一个循环中调用多个excel文件,这一行就在循环内部。 在每个文件运行后都会打开一个小小的cmd窗口,但在第二次运行时不再崩溃,所以我称之为成功。

您的问题可能是我试图解决同样的问题 – 随机的64位Excel 2013 VBA崩溃(VBE7.dll错误)。 您可以检查应用程序事件日志中的VBE7.dll崩溃来确认这一点。

在我的情况下,通过手动使用,各种XLSM文件会间歇性地损坏。

我的修补程序作为您的替代scheme是以下VBS(任何触发VBA“重新编译”)。

 Resave "myfile.xlsm" Sub Resave(filename) Set objExcel = CreateObject("Excel.Application") currentDirectory = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName))) objExcel.Application.AutomationSecurity = 3 ' Disable to avoid crash objExcel.Application.enableevents = False objExcel.Application.Workbooks.open(currentDirectory + "\" + filename) objExcel.Application.Visible = True objExcel.Application.DisplayAlerts = False Set objSheet = objExcel.ActiveWorkbook.Sheets.Add objSheet.Delete objExcel.Application.DisplayAlerts = True objExcel.Application.enableevents = True objExcel.ActiveWorkbook.Save objExcel.ActiveWorkbook.Close objExcel.Application.Quit Set objExcel = Nothing End Sub 

仅供参考 – 微软在2016年5月3日发布了一个补丁修复了Excel 2013中的问题。

https://support.microsoft.com/en-us/kb/3085486