【问题标题】:Code placement in Excel VBAExcel VBA 中的代码放置
【发布时间】:2013-07-22 15:39:51
【问题描述】:

我已将以下代码添加到我的 Excel 2003 模板 (Book.xlt) 中的 3 张工作表中。 每张表中的代码都是相同的;这让我想知道:我可以将代码放在一个地方,以便每张纸都可以使用它。 我尝试将其放入 ThisWorkBook 和用户模块中 - 均未奏效。

守则

'=====================================================================
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
'- Used with conditional format so selected row is shaded yellow:
'        =AND(CELL("row")=ROW(),UPPER(cel_HighlightRow)="Y")
    Application.ScreenUpdating = True
End Sub
'=====================================================================
Private Sub cmdGrabTable_Click()
'- Select table with 1 click.
   Range("tbl_1Main").Select
End Sub  'cmdGrabTable SortData
'=====================================================================

你好,亲爱的

评论于 2013 年 7 月 25 日 02:50 添加(澳大利亚堪培拉) 你好

  1. 注意事项: 3 个工作表中的每一个都有一个 cmdGrabTable 按钮和一个 tbl_1Main(即在 Sheet2 中它是 tbl_1Main,而不是 tbl_2Main)。 条件格式适用于 3 个表中的每一个。

  2. Application.ScreenUpdating = True: 每当我在 tbl_1Main 中选择一个单元格时,所选单元格的行都会突出显示。 如果没有“Application.ScreenUpdating = True”代码,它将无法工作。

  3. 在 2 个程序中,我有 2 行代码。 如果代码很长,我会使用 Retailcoder 的建议,即每个模块从另一个模块调用通用代码。 但除此之外,这些建议似乎有点复杂。正如 David Zemens 所指出的“……听起来 OP 想要避免的是为按钮使用三个不同的 Click 处理程序,为 Worksheet 对象使用 3 个不同的 _Change 处理程序。”

我希望 Click 处理程序可以访问通用代码。不幸的是,正如retailcoder 指出的那样:“……如果Sheet1 上有一个按钮,它的Click 处理程序就属于Sheet1 的代码……。”

非常感谢您努力尝试解决我的问题。 问候,休恩

【问题讨论】:

  • 三张纸上都有cmdGrabTable 按钮吗?
  • SelectionChange 事件会在每次用户点击未选中的单元格时被调用,所以这经常;小心你放在那里的东西。 Application.ScreenUpdating 不需要经常设置(默认情况下它是 true )因为你只想在做事时将它设置为 false否则会使 Excel 闪烁;完成艰苦的工作后,您会将其设置回 false ,..不是每次用户选择一个新单元格时。这就是为什么我的回答只针对Click 处理程序。
  • 我将 Worksheet_SelectionChange 过程移到一个模块中并公开。正如大卫泽门斯预测的那样,它没有用。这似乎是合乎逻辑的,因为它是一个工作表事件。休恩
  • 要在代码模块中使用工作表事件,您需要使用WithEvents 声明一个Worksheet 变量。如果需要,您可以将该工作表变量指定为指向任何工作表。我的建议是使用您已有的工作表并在一个地方编写代码,以允许您传递您可能需要的任何参数的方式。我没有看到更简单的方法。

标签: excel vba


【解决方案1】:

这适用于我使用 Workbook 事件。这是一个非常简单的例子,但希望你能明白:

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)

With Sh
    If .Name = "Sheet1" Or .Name = "Sheet2" Then
        MsgBox ("You made a change on " & .Name)
    Else
        MsgBox ("You didn't make a change on either Sheet1 or Sheet2, but on " & .Name)
    End If
End With

End Sub

此外,您可以连接您的按钮,以便它们都通过使用类来执行相同的代码。

1) 添加对 Microsoft Forms 2.0 对象库的引用(工具 -> 引用)

2) 为您的项目添加一个类。

3) 在类模块中添加如下代码:

Option Explicit
Private WithEvents mbutton As MSForms.CommandButton
Public Property Set Control(obtNew As MSForms.CommandButton)
    Set mbutton = obtNew
End Property

Private Sub mbutton_Click()
MsgBox ("Generic Message goes here!")
End Sub

4) 为你的类添加一个常规模块并添加以下代码:

Option Explicit

Dim mcolEvents As Collection

Sub InitializeEvents()
    Dim obtButton As OLEObject
    Dim clsEvents As Class1

    If mcolEvents Is Nothing Then
        Set mcolEvents = New Collection
    End If

    For Each obtButton In Sheet1.OLEObjects
        If TypeName(obtButton.Object) = "CommandButton" Then
            Set clsEvents = New Class1
            Set clsEvents.Control = obtButton.Object
            mcolEvents.Add clsEvents
        End If
    Next
End Sub

5) 向工作表 1 添加一些 Active X 按钮并运行 InitializeEvents() 代码。

6) 按您添加到工作表中的任何按钮

7) 修改代码以适应您的特定场景

8) ...

9) 利润!

请记住,这是一个简单的示例,但应该能让您走上正确的道路。基本上,您需要将要执行特定代码的按钮添加到 mcolEvents 集合中,一切就绪。

祝你好运,如果您需要任何帮助,请随时回复。

【讨论】:

  • +1 用于使用WithEvents。聪明的。但是,如果曾经需要添加行为不同的按钮,For Each 循环中的事情可能会变得一团糟。如果两个按钮做同样的事情但作用于不同的范围(一个选择范围 A,另一个选择范围 B - 两者都只选择一个范围),“包装类”点击处理程序中的所有内容都必须硬编码在一个不错的 @ 987654326@ 块,这里没有办法通过参数说“为我选择范围 X”......这不是 .NET!但是,是的,如果工作表上的所有按钮都需要执行完全相同的操作,那就完全可以了。干得好!
  • @retailcoder 谢谢!是的,我同意它可能会变得混乱。像我写的那样拿代码可能会变得混乱。但是,除了添加任何“CommandButton”之外,您还可以使用另一个属性(如 .Name)并将控件命名为类似的名称,以便仅应用 .name 以“CustomClick”开头的按钮(完全试图记住我是如何做到了,所以根本没有测试)。老实说,我会按照您概述的方式进行操作……但是抛出另一种方法总是很好。
【解决方案2】:

要在多个工作表中使用一段代码,您可以将它放在一个代码模块 (.bas) 中,并将共享 代码设为Public。如果一个过程是Private,那么只有该模块中的代码才能“看到”它。

Public Sub SomeSharedCode(ByVal TheRange As Range)
    'do something with TheRange
End Sub

不幸的是,您无法告诉按钮由看不到按钮的代码处理 - 换句话说,如果 Sheet1 上有一个按钮,则其 Click 处理程序属于 Sheet1 的代码。您可以做的是让所有这些处理程序调用相同的代码,如下所示:

在 Sheet1 中:

Private Sub Sheet1CmdGrabTable_Click()
    SomeSharedCode Range("tbl_1Main")
End Sub

在 Sheet2 中:

Private Sub Sheet2CmdGrabTable_Click()
    SomeSharedCode Range("tbl_2Main")
End Sub

在 Sheet3 中:

Private Sub Sheet3CmdGrabTable_Click()
    SomeSharedCode Range("tbl_3Main")
End Sub

【讨论】:

  • 很确定这不适用于应用程序Event 程序(即,您不能将按钮Click 事件放在公共代码模块中,也不能将工作表Change公共模块中的事件)。听起来 OP 想要避免的是为按钮设置三个不同的 Click 处理程序,为 Worksheet 对象设置三个不同的 _Change 处理程序。
  • @DavidZemens 编辑澄清。当然,工作表事件必须在该工作表的“代码隐藏”中处理。
  • @retailcoder 对于它的价值,我已经使用类在我的答案中模拟了一个示例。似乎按照OP的要求做。它使用类级别的单击事件集,您可以订阅该单击事件的任何按钮。
猜你喜欢
  • 2023-03-05
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
相关资源
最近更新 更多