由于同时执行而导致运行 VBA 宏保持模式错误

时间:2021-02-03 14:20:10

标签: excel vba

由于我没有在这里或在任何其他董事会找到类似的问题,我决定提出一个新问题。

我有一个非常基本的宏,如下所示:

Sub test()

Dim path as String
Dim filename as String

path = Range("path_name").Value
filename= Range("filename_name").Value

Workbooks.Open Filename:=path & filename
Sheets("XF").Select
Cells.Select
Selection.Copy

End Sub

打开的新数据文件执行一个新的宏,它只在一个单元格中插入一个日期,就是这样。 如果我一步一步执行宏,它工作正常。如果我立即执行它,它会在 ("Sheets("XF").Select") 之前显示一个保持模式错误。 我认为它在打开新数据文件(.xls)后不知何故卡住了。我假设它执行新的宏,同时想要继续原来的宏,这当然不起作用。

我尝试在 "Sheets("XF").Select" 之前使用等待方法,但该方法无效。

我用的是Excel 2016,主数据文件格式为XSML,打开的数据文件格式为XSL。

抱歉,我不能分享我的原始脚本。希望您对如何解决问题有任何建议。

对不起,如果我在这个板上犯了任何基本错误,因为这是我的第一篇文章。

最好的问候, 亨德里克

1 个答案:

答案 0 :(得分:1)

VBA 在主 UI 线程上运行,并且不进行多线程执行:Workbooks.Open 调用在完成时返回,这将是自动打开宏完成执行之后.

逐行执行与“正常”执行时运行方式不同的代码,通常是受 implicit ActiveSheet referencesimplicit ActiveWorkbook references 影响的代码(这些是 Rubberduck 检查:Rubberduck 可以发现代码中的问题并帮助你修复它们;我管理这个开源项目),即隐式依赖全局状态,这使得代码比它需要的更加脆弱。

解决方案是避免依赖全局状态的副作用。

例如,Workbooks.Open 是一个函数,它返回对打开的工作簿的引用。它还具有使该工作簿成为 ActiveWorkbook 的副作用,但您的宏不应依赖于此。相反,使用局部变量捕获返回的引用:

Dim book As Excel.Workbook
Set book = Application.Workbooks.Open(path & filename)

现在您有了对打开的工作簿的引用,其余代码不再需要Select

<块引用>
Sheets("XF").Select
Cells.Select
Selection.Copy

变成:

book.Worksheets("XF").Cells.Copy

这段代码应该做完全相同的事情,但现在可以可靠地完成它,而不管其他什么代码可以运行以及Activate其他工作簿和工作表。

有关更多提示,请参阅 how to avoid using Select and Activate