为什么我无法从该集合的成员获取属性?

发布于 2024-08-30 12:09:23 字数 1036 浏览 1 评论 0原文

我已将一些表单控件添加到集合中,并且当我通过索引引用成员时可以检索它们的属性。

但是,当我尝试通过引用集合成员来使用任何属性时,我看到“无法设置 ControlSource 属性”。 “找不到成员。”本地窗口中出现错误。

下面是代码的简化版本:

'Add controls to collection'
For x = 0 To UBound(tabs)
    activeTabs.Add Item:=Form.MultiPage.Pages(Val(tabs(x, 1))), _
        key:=Form.MultiPage.Pages(Val(tabs(x, 1))).Caption
Next x

'Check name using collection index'
For x = 0 To UBound(tabs)
    Debug.Print "Tab name from index: " & activeTabs(x + 1).Caption
Next x

'Check name using collection members'
For Each formTab In activeTabs
    Debug.Print "Tab name from collection: " & formTab.Caption
Next formTab

立即窗口中的结果是:

Tab name from index: Caption1
Tab name from index: Caption2
Tab name from collection: 
Tab name from collection: 

为什么一种方法有效而另一种方法失败?

这是在标准代码模块中,但我有类似的代码在表单模块中工作得很好。这会不会有什么关系呢?

编辑添加

formTab 被声明为控件,但我发现如果它被声明为对象,则代码可以工作。

这可能会解决我的问题,但为了进一步加深我的知识,我将不胜感激对此行为的任何解释,特别是关于在不同类型的模块中运行代码的差异。

I've added some form controls to a collection and can retrieve their properties when I refer to the members by index.

However, when I try to use any properties by referencing members of the collection I see a 'Could not set the ControlSource property. Member not found.' error in the Locals window.

Here is a simplified version of the code:

'Add controls to collection'
For x = 0 To UBound(tabs)
    activeTabs.Add Item:=Form.MultiPage.Pages(Val(tabs(x, 1))), _
        key:=Form.MultiPage.Pages(Val(tabs(x, 1))).Caption
Next x

'Check name using collection index'
For x = 0 To UBound(tabs)
    Debug.Print "Tab name from index: " & activeTabs(x + 1).Caption
Next x

'Check name using collection members'
For Each formTab In activeTabs
    Debug.Print "Tab name from collection: " & formTab.Caption
Next formTab

The results in the Immediate window are:

Tab name from index: Caption1
Tab name from index: Caption2
Tab name from collection: 
Tab name from collection: 

Why does one method work and the other fail?

This is in a standard code module, but I have similar code working just fine from within form modules. Could this have anything to do with it?

Edited to add

formTab was declared as a Control, but I find that if it is declared as an Object then the code works.

This will probably solve my problem, but in the interests of furthering my knowledge I would be grateful for any explanation of this behaviour, particularly with regard to the difference in running the code in the different types of module.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

同展鸳鸯锦 2024-09-06 12:09:23

这是一个非常好的问题。您在帖子末尾的编辑揭示了很多有关 VBA 工作原理以及这里发生的事情的信息。我不是 100% 知道发生了什么,但我会解释我认为发生的事情。

VBA(以及 VB6,就此而言;相同的代码库)中的 Collection 不是强类型的。这意味着集合中的所有内容在技术上都是“对象”。在 .NET 世界(从 .NET 2.0 开始),可以有强类型集合,因此您可以说“该集合中的所有内容都是 Control 对象”。在 VBA 中,Collection 无法实现这一点。

在第一次迭代中,您引用 activeTabs 集合中索引的项目,activeTabs(x + 1) 引用一个 object 。当您告诉 VBA 查找该对象的 .Caption 时,它不知道底层类型是什么(我认为),因此它必须简单地查看底层对象类型是否包含名为 Caption 的属性或方法。正如您所看到的,Tab 控件实际上包含一个名为 Caption 的属性。

在第二次交互中,您正在执行 For Each 循环,我认为问题在于 Control 类型可能没有名为 Caption< 的属性/code>,尽管不同类型的控件可能会这样做。例如,文本框控件可能没有 Caption 属性,而标签控件则具有 Caption 属性。

您有几个选项可以修复第二个循环。 1)您可以将 formTab 声明为 Tab 控件(我不确定它到底叫什么)。 Tab 控件应具有 Caption 属性。 2) 如果 activeTabs 中的每个控件都不是专门的 Tab 控件(在这种情况下,您可能应该将其称为 activeControls 而不是 activeTabs),您可以在循环中检查 formTab 是否实际上是一个 Tab 控件。如果是,请将其转换为 Tab 控件,然后调用 .Caption。在将其转换为 Tab 控件之前,VBA 不会知道它具有 Caption 属性,因为常规 Control 对象没有 Caption 属性。

最后,您可以像在第一个循环中那样使用对象并让运行时确定要做什么,但这可能会带来非常糟糕的性能。一般来说,最好使用强类型语言来处理特定类型。它还有助于在代码中显示您具体知道正在使用的内容,而不是让运行时来决定可以使用哪些属性和方法。

This is a really great question. Your edit at the end of the post reveals a lot about how VBA works and what's going on here. I'm not 100% this what's going on, but I'll explain what I think is happening.

A Collection in VBA (and VB6, for that matter; same code base) is not strongly typed. This means that everything in a collection is technically an "object." In the .NET world (as of .NET 2.0), it's possible to have strongly typed collections so that you could say "everything in this collection is a Control object." In VBA, this isn't possible with a Collection.

In your first iteration, where you are referring to the item indexed in the activeTabs collection, activeTabs(x + 1) is referring to an object. When you tell VBA to look up .Caption of that object, it doesn't know what the underlying type is (I think), so it has to simply look to see if the underlying object type contains a property or method called Caption. As you can see, Tab controls do in fact contain a property called Caption.

In your second interation, where you are doing a For Each loop, I think the problem is that the Control type probably doesn't have a property called Caption, though different types of controls probably do. For example, a text box control probably doesn't have a Caption property whereas as label control does have a Caption property.

You have a few options to fix your second loop. 1) You could declare formTab as a Tab control (I'm not sure exactly what it's called). The Tab control should have a Caption property. 2) If every control in activeTabs is not specifically a Tab control (in which case, you should probably call it activeControls instead of activeTabs), you could check within your loop to see if the formTab is actually a Tab control. If it is, cast it as a Tab control and then call .Caption. Until you cast it as a Tab control, VBA won't know that it has a Caption property since a regular Control object doesn't have a caption property.

In the end, you can get away with using objects as in your first loop and letting the runtime figure out what to do, but that can give really bad performance. In general, it's better to work with your specific types in a strongly-typed language. It also helps to show in your code that you know specifically what you're working with rather than leaving it to the runtime to decide what properties and methods you can work with.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文