我正在更新一个在许多电子表格中使用的宏,但速度相当慢。在寻求加快速度的同时,我注意到它有一次经历了这个循环:
For each wsLoop in ThisWorkbook.Worksheets
wsLoop.Activate
With ActiveSheet.Status_Text
If bStatus = True Then
.ForeColor = &HC000&
.Caption = "ONLINE"
Else
.ForeColor = &HFF&
.Caption = "OFFLINE"
End If
End With
Next wsLoop
其中 wsLoop 是一个工作表,bStatus 是一个 bool 值,Status_Text 是每个工作表上的 ActiveX 标签表单控件的名称。
我知道使用 .Activate 是不好的做法并且会减慢速度,所以我删除了 wsLoop.Activate
并将下一行更改为 With wsLoop.Status_Text
,但现在我明白了“找不到方法或数据成员”错误消息。
这样做的正确方法是什么?
最佳答案
有趣的问题,似乎涉及 Excel VBA 的一些记录不完整的功能。似乎表达 ActiveSheet.Status_Text
作为控件的名称 运行,点作为命名空间限定符,但在wsLoop.Status_Text
中VBA 将点解释为方法/属性访问运算符,并正确给出错误消息,指出不存在此类方法或属性。为了重现该问题,我创建了一个名为 Status_Text
的标签在每张纸上然后运行
Sub test1()
Dim ws As Worksheet
For Each ws In Worksheets
Debug.Print ws.Status_Text.Caption 'fails
Next ws
End Sub
它因您显示的错误而崩溃。一种解决方法(虽然只是为什么它起作用是个谜)是将循环索引从 Worksheet
更改为到 Variant
:
Sub test2()
Dim ws As Variant
For Each ws In Worksheets
Debug.Print ws.Status_Text.Caption 'succeeds
Next ws
End Sub
最后一个例子的奇怪之处在于,如果您添加行 Debug.Print TypeName(ws)
在 for-each 循环中它打印 Worksheet
所以ws.Status_Text
如果 ws
有效是一个包含工作表但不是 if ws
的变体实际上是一个工作表。当您在调试器中单步执行此子程序并查看本地窗口时,神秘感在某种意义上加深了,但在另一种意义上却减轻了。 ws
的类型在循环中描述为 Variant/Object/Sheet1
(在第一次通过循环时)。特定工作表似乎是变量当前子类型的一部分。
另一种解决方法是使用 For-Next
循环而不是 For-Each
:
Sub test3()
Dim i As Long
For i = 1 To Worksheets.Count
Debug.Print Worksheets(i).Status_Text.Caption 'succeeds
Next i
End Sub
您可以使用这两种方法中的任何一种来获取对标签的引用,而无需激活工作表。
关于excel - 使用 ActiveX 表单控件避免 .Activate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34190238/