对于多次使用单个对象变量的VBA程序,最好是在循环中重置变量而不先将变量设置为空(可以在循环外的末尾完成),或者应该是在每个使用实例之后,变量始终设置为空。从引用计数的角度来看,似乎最好设置为空,因为一旦将对象更改为下一个变量,我就不需要对象的先前状态(我不确定如何检索以前的状态但是我我认为必须有这样的功能question)。我检查的另一个相关问题可以找到here。
触发此问题的应用程序是我循环浏览许多Word文档,从每个文档中提取相关信息的应用程序。见下面的例子:
dim objDoc as object, objWord as object
Set objWord = CreateObject("Word.Application")
for r=2 to 40
'Some code to set filename
Set objDoc = objWord.Documents.Open(filename, ReadOnly:=False, Visible:=False)
'Code to retrieve relevant info from document
objDoc.close
Set objDoc = nothing 'Should this go here?
next r
set objDoc = nothing 'Or should it go here?
objWord.Quit
问题:在代码效率或问题避免方面将对象变量设置为空时,这是否重要?我已经强调了以上两个选项,我认为应该选择第三个选项,即当我将变量设置为空时并不重要
答案 0 :(得分:3)
我认为,一般来说,根据上下文,拥有一个具有两个或更多不同含义的变量会使维护者的生活变得比它需要的更难。在这种情况下,无论你将它置于循环范围内部还是外部都没有任何区别 - 事实上是否完全指定了Set objDoc = Nothing
,应该制作没有区别。
你没有展示剩下的程序,但据我所知,这个特定的程序不会做其他10,000件事情的原因并不是真的。
您显示的代码应写入程序和函数的束。
'Some code to set filename
您需要一个实现逻辑的函数来获取文件名,并返回String
。
'Code to retrieve relevant info from document
您需要一个从文档中检索相关信息的过程。
将循环体拉入自己的程序:
For r = 2 To 40
filename = LogicToGetTheFilename(r)
ProcessWordDocument wordApp, filename
Next
这里有更高的抽象级别 - 通过正确的命名,您可以一眼就知道该循环 。
Private Sub ProcessWordDocument(ByVal wordApp As Object, ByVal filename As String)
Dim docx As Object 'Word.Document
Set docx = wordApp.Documents.Open(filename, ...)
'do stuff
docx.Close
'Set docx = Nothing
End Sub
现在Word文档对象变量生活在自己的范围内,只要执行退出该范围(即每次循环迭代一次),VBA 应该适当地销毁底层对象。
因为将循环重构为适当的抽象级别意味着Word文档仅存在于单个迭代中,我会(相当强烈地)认为Set objDoc = Nothing
在循环体内属于。
答案 1 :(得分:3)
简答:在循环中。
答案很长:从避免问题的角度来看,你应该把它设置为“什么都没有”。当你马上完成它。您将要尝试捕获的问题是意外重用。如果你不小心重复使用变量而不必在以后给出奇怪的结果时调试它,你希望你的代码爆炸。一般来说,你不应该重用变量,因为在重构时变量很容易出错并且变量最终包含错误的值。
很遗憾,如果你在内窥镜之外使用一个变暗的VBA,那么VBA并不在乎。以下是不幸的是法律和更现代的语言不允许你这样做:
Sub CountInsideLoop()
Dim i As Long
For i = 1 To 3
Dim count As Long
count = count + 1
Next i
' count value will be 3
Debug.Print count
End Sub
答案 2 :(得分:0)
循环内部
应从以下等效代码中轻易推断:
dim objWord as object
Set objWord = CreateObject("Word.Application")
for r=2 to 40
'Some code to set filename
With objWord.Documents.Open(filename, ReadOnly:=False, Visible:=False) 'Set and reference your document object
'Code to retrieve relevant info from document
.Close
End With 'this “disposes” the referenced document object, so you also set it to Nothing
Next r
objWord.Quit
当然,对于objWord来说,还有进一步应用相同概念的空间:
With CreateObject("Word.Application") ‘ instantiate and reference your Word object
for r=2 to 40
'Some code to set filename
With .Documents.Open(filename, ReadOnly:=False, Visible:=False) 'Set and reference your document object
'Code to retrieve relevant info from document
.Close
End With 'this “disposes” the referenced document object, so you also set it to Nothing
Next r
.Quit
End With 'this “disposes” the referenced Word object, so you also set it to Nothing