【问题标题】:When should I move VBA code from a form module to a separate module?何时应将 VBA 代码从表单模块移动到单独的模块?
【发布时间】:2012-05-06 23:24:18
【问题描述】:

我有很多例子,我从一个基本的子表单开始,然后我有 3 个其他子表单建立在它之上,每个子表单都在基本子表单上添加了一些不同的元素。这意味着我对每个子表单都有一个代码页,其中有很多重复。是否可以将通用元素放入单独的模块中,并在其代码页上仅保留与每个子表单相关的附加代码?这有任何性能问题吗?

【问题讨论】:

  • 当你说“类”是指类模块还是表单代码模块?
  • @HK1:我根本没有提到“班级”。我尝试为其中一个子表单设置一个新模块并将所有重复的代码移入其中,但它不起作用,其他子表单上的更改没有正确触发事件代码。
  • 标题中确实出现了“class”这个词。
  • 了解您所说的重复代码类型可能会有所帮助。
  • 抱歉,当我重读我的问题时没有看标题。表单代码页列表出现在标题“MS Office Access Class Objects”下,因此提及。在大多数情况下,代码控件启用了属性,以便根据控件中的选择启用相关选项。有些根据特定变量设置组合框的选项。我设置了一个包含通用元素的表单作为一种模板,然后用它来作为我其他表单的基础,每个表单都添加了另外一些控件以及它们相关的编码。

标签: ms-access ms-access-2007 vba


【解决方案1】:

关于您问题的最后一部分,“这有什么性能问题吗?

我知道有两种后果:

  1. 表单加载时间
  2. 内存使用

作为一个假设示例,假设您有一个带有选项卡控件的表单。该选项卡控件包含 10 个页面,每个页面包含一个子表单。如果这些子表单包含相同 VBA 代码的副本,则必须为每个子表单再次加载该公共代码。这需要时间并增加内存使用。

如果您将公共代码移动到标准模块并从子表单中引用它,则只需加载一次...减少表单加载时间和内存消耗。

因此,最终结果是您正在考虑的方法可以使您的应用程序更具响应性......这可能会带来更快乐的用户。

但是,即使这种方法没有产生明显的性能改进,我仍然会这样做,因为这意味着您只需要维护一份通用代码的副本。

【讨论】:

  • 如今的计算机似乎确实足够快,以至于您提到的性能问题对用户来说很少是显而易见的。为您的最后一行 +1。当涉及到代码/应用程序的未来可管理性时,代码集中化非常重要。
  • @HK1 我看过Chelle的申请。主要形式类似于我的“假设”情况,并且在表单加载时存在显着滞后。但是,我并没有真正不同意您的观点……对于不太复杂的形式,这不是什么大问题。无论如何,听起来你和我完全同意 RE 代码集中化。 :-)
  • 我仍在学习提高代码可管理性的新方法。这似乎是一个永无止境的学习和完善过程。
  • 实际事件仍然可以正常触发,对吧?您是否尝试将 MsgBox 或 Debug.Print 放入相关事件中以查看它们是否触发?
  • 我对子表单进行了一些更改,对附加元素使用嵌套子表单而不是完整的新子表单,这样就消除了重复的代码。而不是像我之前那样使用主窗体的加载事件加载所有子窗体,而是使用选项卡控件的更改事件加载它们,因此现在性能得到了很大提高,一开始只加载了一个子窗体。
【解决方案2】:

简短的回答,是的,这样做,将每个表单之间重复的代码拆分出来。

更长的答案,但在我看来,将重复的代码提取到单独的模块或类中是更好的方法。

类使您的代码更易于管理和维护。如果您在多个地方都有相似的代码,则维护会更加困难,因为您必须在每个位置进行更改。将它放在一个地方可以更容易管理和维护。

优势列表来自Chicago Access Users Group (CAUG) talk - "Class Modules in Access"

Advantages of using classes/objects:
 - let's you create more complex objects than tables or queries provide
   alone
 - using classes within classes let's you restrict function visibility
 - class methods & attributes are more descriptive than module's
   function list alone
 - let's you use Intellisense for more efficient coding
 - no "ambiguous name" errors with multiple copies of the same class
   module
 - can copy class modules without worry of creating ambiguous function
   names
 - static variables are implicit in class objects, and so are easier to
   manage
 - isolating access layers within wrapper classes promote
   portability/maintainability
 - better support for separation of UI/business logic/data access =
   n-tier development
 - promotes modular thinking in analysis, design
 - easier to adapt many publicly-available object models to Access apps
 - prepares you for transition to .NET and other fully object-oriented
   architectures

【讨论】:

  • +1 我从来没有花时间去比较它们,我两者都用过,但总是喜欢标准模块而不是类,但这些点很有趣。
【解决方案3】:

如果我理解这个问题,是的,您可以通过将一定数量的代码移动到标准代码模块中来集中这些代码。您可能有很多方法可以做到这一点,但更好的方法之一是将表单对象传递给您的函数。这是一个例子:

Private Sub Form_BeforeUpdate(Cancel As Integer)
    If ValidateContact = False Then Cancel = True
End Sub

'This code goes in a standard code module not associated with any form
Public Function ValidateContact(ByRef frm as Form) as Boolean
    Dim bValid as Boolean
    bValid = True
    If Nz(frm!FirstName, "") = "" Then
        MsgBox "First Name cannot be blank."
        bValid = False
    ElseIf Nz(frm!LastName, "") = "" Then
        MsgBox "Last Name cannot be blank."
        bValid = False
    End If
    ValidateContact = bValid
End Function

另外,如果我理解正确,您的问题根本不是关于使用类模块/类对象,至少不是明确的。 (事实上​​,基本上你在 Access 中编写的每一段代码都在使用类对象,通常是隐式的。)另一个 SO 用户已经发布了一个很好的答案,关于在 Access 中使用类对象的好处,所以我不会解释更多关于这一点。事实上,标准代码模块基本上是一个单例类,不需要像类对象那样实例化。首选单例/标准代码模块是有原因的,至少在某些情况下,如果没有其他原因,更容易调用函数。但是,如果您发现自己编写的函数具有大约四个或更多参数,您可能会受益于将其更改为允许您在调用相关方法之前设置属性的类对象。

【讨论】:

    猜你喜欢
    • 2019-11-29
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    相关资源
    最近更新 更多