Excel插件中未使用的功能仅在第二次运行时以及通过VBScript

时间:2016-03-31 17:08:00

标签: excel vba excel-vba vbscript

很抱歉这个长标题。

我有几个共享大量代码的.xlsm文件,因此我将重复的部分移动到了一个addin .xlam文件中。我一直在使用.vbs脚本一个接一个地打开所有文件,并在每个文件中运行一个宏。

问题

我面临的问题是,在.vbs脚本的第二次运行中,excel崩溃并给出了一个非常普通的错误,here表示是“自动化错误”:

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 has a module Module1, test.xlsm has a Module Auto and a Reference to 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()注释掉,代码工作正常(说好,加载和再见)。如果从excel中运行宏,它也可以正常工作。只有当Other()存在且Run()通过.vbs文件运行时才会出现错误(在问候之后)。

解决方法

如果我打开test.xlsm,保存它,并在每次test.vbs运行之间再次关闭它,就没有问题。我认为这与插件而不是电子表格有关,因为在我的原始脚本中,打开多个excel文件,只需要打开并保存一个文件。

我还注意到excel文件在“问题”状态下有点大,而且一旦我打开并保存它,它就会恢复到略小的原始大小。 (编辑:这至少部分是由vbaProject.bin文件中的新缓存流__SRP_4和__SRP_5造成的,我使用this answer(哦,和this提取手动删除所有SRP条目后,我能够再次运行.vbs脚本而没有问题,虽然就像open-save-close策略一样,它只是临时的,然后会在第三次运行而不是第二次运行时崩溃。 )

问题

addins不适合共享代码吗?他们可能不包含功能吗?除了我现在正在做的事情之外,还有办法解决这次崩溃吗?

任何想法都表示赞赏。

4 个答案:

答案 0 :(得分:0)

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

'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将插件安装到Excel,您可以使用以下代码

'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

如果失败,您可能必须先清除注册表值,然后重新运行上面的脚本

'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

答案 1 :(得分:0)

不幸的是,我仍然不知道为什么会这样,但我找到了一个自动解决方案,我将会坚持下去。

正如我在我的问题中提到的那样,test.xlsm文件在它的问题中变得更大了#34;状态,至少部分归因于某种缓存,我只能找到一个官方提及here

  

2.2.6 SRP Streams

     

指定特定于实现和版本的性能缓存的流。一定是   阅读时忽略了写作时不得出现。   每个流的名称由以下ABNF语法指定:

     

SRPStreamName = "__SRP_" 1*25DIGIT

我的解决方案是删除缓存,我首先使用this tool.手动执行此操作。当这似乎有效时,我编写了一个Java程序来自动执行(gist here)。它是java.util.zipApache POIFS之间的粘合剂。

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

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

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

答案 2 :(得分:0)

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

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

我的修复作为你的替代品是以下VBS(任何触发VBA“重新编译”的东西)。

navbar

答案 3 :(得分:0)

仅供参考 - Microsoft于2016年5月3日发布了一个修补Excel 2013中此问题的补丁。

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