如何使用控件集合在Access 2003和VBA [英] How to use Controls collection in Access 2003 and VBA

查看:332
本文介绍了如何使用控件集合在Access 2003和VBA的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有时间赫克试图找出这一个。

I'm having a heck of the time trying to figure this one out.

我想传递一个控件集合函数,但我得到一个类型不匹配。这里的函数声明:

I want to pass a Controls collection to a function but I get a type mismatch. Here's the function declaration:

Public Function DoStuffToCollection(topCtlList As Controls, isLocked As Boolean)

这就是我把它叫做:

Call DoStuffToCollection(myPage.Controls, isLocked)

我的页面是从TabControl的页面控制。我已经通过了code加大,看看是否有东西在myPage.Controls有。

myPage is a Page control from the TabControl. I've stepped through the code to see if there was something in myPage.Controls and there is.

为了好玩,我通过了,而不是myPage.Controls没有类型不匹配的Me.Controls(这将是窗体的控件集合)。是否有一个窗体控件集合和一个页面控件集合之间的区别是什么?这是推动我疯了。

For fun, I passed in Me.Controls (which would be the Form's control collection) instead of the myPage.Controls and no type mismatch. Is there a difference between a Form control collection and a Page control collection? This is driving me crazy.

这一点挖,调试器调用myPage.Controls儿童/儿童的类型和Me.Controls为控制/控件的类型。为什么是这样?

A bit more digging, the debugger is calling myPage.Controls Children/Children as the type and the Me.Controls as Controls/Controls as the type. Why is this?

只是增加了一点信息。 doStuffToCollection是一个函数,递归这只是应该锁定绑定字段和标签控件内禁止任何形式的按钮。 previously我只能够在页面级别锁定,但后来我增加了一个页面中有一个按钮。该按钮并没有得到禁用的页面。我知道这 http://allenbrowne.com/ser-56.html 的。我还没有成功地得到它适应了我的需要,虽然。

Just adding a bit of info. doStuffToCollection is a function that recurses that's just supposed to locked bound fields and disable any kind of buttons within a tab control. Previously I just was able to lock it at the page level but then I added a page with a button in it. The button did not get disabled with the page. I'm aware of this http://allenbrowne.com/ser-56.html. I haven't been successful in getting it adapted to my need though.

推荐答案

@Tim Lentine的建议非常好,直接回答你的问题,在我看来。

@Tim Lentine's suggestion is very good and directly answers your question, seems to me.

不过,我可能永远不会写一个子可以工作在形式的整个控件集合。其原因是,这是实际上是相当低效这样做。但它是否是合适的取决于你的频率和时间行走的集合。

But I would probably never write a sub that operates on the entire controls collection of a form. The reason is that it's actually quite inefficient to do so. But whether or not it's appropriate depends on how often and when you're walking that collection.

如果你在表单的onload事件走一次(你不会想去做的,因为的OnOpen控件的数据绑定属性,不保证在该点被完全初始化 - 你仍然可以对格式属性进行操作,虽然 - 但是一切都准备好了的时候在onload事件触发),这没什么大不了的,并通过该集合到外部子程序将是适当的。

If you're walking it once in the form's OnLoad event (you wouldn't want to do it in the OnOpen because the data-bound properties of the controls aren't guaranteed to be fully initialized at that point -- you can still operate on format properties, though -- but everything's ready to go by the time the OnLoad event fires), that's no big deal, and passing that collection to an outside subroutine would be appropriate.

但是,如果你走它的每一条记录(说来隐藏/显示控件,或初始化未绑定查询通过表单接口标准领域),那么你会明显通过使用一个或多个提高表单的性能通过比拥有更小的数字项环的自定义集合在任何正常的窗体的控件集合。然后,你可以重写蒂姆code使用自定义的集合,或者,对于这个问题,人们仍然可以使用对象变量上面,并通过它的自定义集合以及(和仍然能够传递一个窗体的控件集合)

But if you're walking it for every record (say to hide/reveal controls, or to initialize criteria fields in an unbound query-by-form interface), then you will noticeably improve your form's performance by using one or more custom collections having much smaller numbers of items to loop through than are in any normal form's controls collection. Then you could rewrite Tim's code to use a custom collection, or, for that matter, one could still use the Object variable above and pass it a custom collection as well (and still remain able to pass it a form's controls collection).

基本上,你所要做的就是初始化集合形式的onload事件。我通常写一个私人子程序要做到这一点,所以我可以重新初始化应在code复位发生:

Basically, what you do is initialize the collection in the form's OnLoad event. I normally write a private subroutine to do that so I can re-initialize should a code reset happen:

  Private Sub SetupCollections()
    If mcolCriteria.Count = 0 Then
       Call PopulateCollections(Me, mcolCriteria, "Criteria")
    End If
  End Sub

  Public Sub PopulateCollections(frm As Form, pcol As Collection, strTag As String)
    Dim ctl As Control

    For Each ctl In frm.Controls
      If ctl.Tag = strTag Then
         pcol.Add ctl, ctl.Name
      End If
    Next ctl
    Set ctl = Nothing
  End Sub

在这种情况下,我的方法来确定,其控制被添加到集合是设置这些控制的标记属性。你也可以这样做:

In this case, my method for determining which controls get added to the collection is to set the Tag property of those controls. You could also do something like:

  Public Sub PopulateCollections(frm As Form, pcol As Collection, intControlType As AcControlType)
    Dim ctl As Control

    For Each ctl In frm.Controls
      If ctl.ControlType = intControlType
         pcol.Add ctl, ctl.Name
      End If
    Next ctl
    Set ctl = Nothing
  End Sub

要使用此功能,你可以,例如,创建可空控件的集合是这样的:

To use this, you could, for instance, create a collection of Nullable controls like this:

  If mcolControlsNullable.Count = 0 Then
     Call PopulateCollections(Me, mcolControlsNullable, acTextBox)
     Call PopulateCollections(Me, mcolControlsNullable, acComboBox)
     Call PopulateCollections(Me, mcolControlsNullable, acListBox)
   End If

有关布尔控件:

  If mcolControlsBoolean.Count = 0 Then
     Call PopulateCollections(Me, mcolControlsBoolean, acCheckBox)
  End If

对于有默认值的选项组或其他控件:

For option groups or other controls having a default value:

  If mcolControlsWithDefaults.Count = 0 Then
     Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acTextBox)
     Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acComboBox)
     Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acListBox)
     Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acCheckBox)
     Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acOptionGroup)
  End If

  Public Sub PopulateCollectionsWithDefaults(frm As Form, pcol As Collection)
    Dim ctl As Control

    For Each ctl In frm.Controls
      If Len(ctl.DefaultValue) > 0 Then
         pcol.Add ctl, ctl.Name
      End If
    Next ctl
    Set ctl = Nothing
  End Sub

  Private Sub SetControlValuesFromDefaults(pcol As Collection)
    For Each ctl in pcol 
      ctl = ctl.DefaultValue
    Next ctl 
  End Sub

和为其他集合:

  Public Sub SetControlValues(pcol As Collection, varValue As Variant)
    For Each ctl in pcol
      ctl = varValue
    Next ctl
  End Sub

通过这种更复杂的集藏品,你需要这样的事情最初填充它们其中:

With this more complex set of collections, you would need something like this to initially populate them them:

  Private Sub SetupCollections()
    If mcolControlsNullable.Count = 0 Then
       Call PopulateCollections(Me, mcolControlsNullable, acTextBox)
       Call PopulateCollections(Me, mcolControlsNullable, acComboBox)
       Call PopulateCollections(Me, mcolControlsNullable, acListBox)
     End If
    If mcolControlsBoolean.Count = 0 Then
       Call PopulateCollections(Me, mcolControlsBoolean, acCheckBox)
    End If
    If mcolControlsWithDefaults.Count = 0 Then
       Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acTextBox)
       Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acComboBox)
       Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acListBox)
       Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acCheckBox)
       Call PopulateCollectionsWithDefaults(Me, mcolControlsWithDefaults, acOptionGroup)
    End If
  End Sub

...那么你会希望有一个子来初始化控制值:

...then you'd want a sub to initialize the control values:

  Private Sub InitializeControls()
    Call SetControlValues(mcolControlsNullable, Null)
    Call SetControlValues(mcolControlsBoolean, False)
    Call SetControlValuesFromDefaults(mcolControlsWithDefaults)
  End Sub

...这样你就可以再设置一切在你的表单的onload事件:

...so that you could then set everything up in your form's OnLoad event:

  Call SetupCollections()
  Call InitializeControls()

现在,当然,也有少令人费解的方式来做到这一点。你可能想有你的初始化程序走的控件集合只有一次:

Now, of course, there are less convoluted ways to do this. You might want to have your initialization routine walk the controls collection just once:

  Private Sub SetupCollections()
    Dim ctl As Control

    For Each ctl in Me.Controls
      If Len(ctl.DefaultValue) > 0 then
         mcolControlsWithDefaults.Add ctl, ctl.Name
      Else
         Select Case ctl.ControlType
           Case acTextBox, acComboBox, acListBox
             mcolControlsNullable.Add ctl, ctl.Name
           Case acCheckBox
             mcolControlsBoolean.Add ctl, ctl.Name
         End Select
      End If
    Next ctl
    Set ctl = Nothing
  End Sub

一个方法来消除初始化程序将是使用自定义属性来返回集合,使用根据需要,将被重新初始化内部静态变量。然而,这将意味着通过控件集合多个阶层,所以它的效率不高:

A way to eliminate the initialization routine would be to use custom properties to return the collections, using internal static variables that would be re-initialized as needed. However, this would mean multiple walks through the controls collection, so it's not as efficient:

  Private Property Get colControlsNullable() As Collection
    Static colNullable As Collection

    If colNullable.Count = 0 Then
       Call PopulateCollections(Me, mcolControlsNullable, acTextBox)
       Call PopulateCollections(Me, mcolControlsNullable, acComboBox)
       Call PopulateCollections(Me, mcolControlsNullable, acListBox)       
    End If
    Set colControlsNullable = colNullable
  End Property

不幸的是,使用静态变量,同时很好地避免了模块级的变量,意味着你的inialization程序变得效率较低,因为没有办法对外部初始化程序利用这些静态变量来填充一切都与一个步行通过控制集合。

Unfortunately, using the static variable, while nicely avoiding module-level variables, means that your inialization routine gets less efficient, since there's no way for an outside initialization routine to utilize these static variables to populate everything with one walk through the controls collection.

所以,我不为这些集合使用自定义属性,尽管我希望我能。在另一方面,如果我只有一个自定义的控件集合,我会做到这一点。

So, I don't use custom properties for these collections, even though I wish I could. On the other hand, if I have only one custom controls collection, I would do that.

不管怎样,我洋洋洒洒远长,用了太多的卷积,大概所有的空气code充满了错误...

Anyway, I've rambled on far to long and with way too much convolution, and probably all that air code is filled with errors...

这篇关于如何使用控件集合在Access 2003和VBA的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆