【问题标题】:Workbook Open event and detecting this event in the Worksheet code工作簿打开事件并在工作表代码中检测到此事件
【发布时间】:2016-02-02 05:58:47
【问题描述】:

我正在尝试减少 .xlsm 工作簿中的一些重复编码。为此,我在“Workbook Open”区域中创建了许多子程序,现在从工作表 1 中的子程序调用这些子程序。(最初在这两个程序中都有重复的代码段)。这一切都很好!

我的问题是这个...

Sheet 1 中的代码是否可以知道它正在被 Workbook Open 事件激活?

例如,我有一个由 Workbook_open 事件填充的组合框,然后触发工作表 1 组合框“更改”事件。但是,我只希望用户在打开工作簿后触发此更改事件。

我尝试在 Workbook Open 中设置一个全局变量,但这仅在此事件中具有作用域。

这里最好的解决方法是什么?

我可以使用工作簿模块吗?
我是否应该将变量写入工作表中的单元格并在事件结束时将其清除?
其他解决方案?

部分工作簿打开代码..

Private Ws_Open As Boolean
Private Sub Workbook_Open()
'
' set up drop down filter list
'
Range("A1").Select
With ThisWorkbook.Worksheets(1).Cmb_filter
    .Clear
    .AddItem "None"
    .AddItem "60% or less"
    .AddItem "70% or less"
    .AddItem "80% or less"
    .AddItem "90% or less"
    .ListIndex = 0
End With

Sheet 1 代码的一部分...

Private Sub Cmb_filter_Change()
 Dim intvalue As Integer
 Cmb_filter.BackColor = vbWhite
 Application.Run "'" & ThisWorkbook.Name & "'!Thisworkbook.clear_it"
..etc

【问题讨论】:

  • 把全局变量放在一个普通的代码模块中,而不是工作簿模块中。另外,尝试传递变量,而不是使用全局变量。
  • 谢谢@vacip。这是导致问题的变量的传递。我过去处理过很多用户表单,并且知道如何在此处传递变量,但不清楚如何在工作簿打开事件和连接的工作表之间实现这一点。有没有关于这个的文章?

标签: vba excel


【解决方案1】:

如何使用公共/全局变量来防止事件触发

将它与您的其余代码放在一个常规模块中:

Private Ws_Open As Boolean

Private Sub Cmb_filter_Change_Proc()
If Ws_Open Then Exit Sub
    Dim intvalue As Integer
    Cmb_filter.BackColor = vbWhite
    Application.Run "'" & ThisWorkbook.Name & "'!Thisworkbook.clear_it"
    '..etc
End Sub

Public Sub Wb_Open_Proc()
'
' set up drop down filter list
'
Ws_Open = True
Range("A1").Select
With ThisWorkbook.Worksheets(1).Cmb_filter
    .Clear
    .AddItem "None"
    .AddItem "60% or less"
    .AddItem "70% or less"
    .AddItem "80% or less"
    .AddItem "90% or less"
    .ListIndex = 0
End With

'rest of your code

Ws_Open = False
End Sub

这些在 ThisWorbookSheet 模块中

Private Sub Workbook_Open()
    Call Wb_Open_Proc
End Sub

Private Sub Cmb_filter_Change()
    Call Cmb_filter_Change_Proc
End Sub


不适用于此特定情况的提议(工作表中的控制),但适用于工作表、工作簿等大多数其他事件......


比检测事件的触发方式更简单,您可以在代码中使用Application.EnableEvents = False 操作期间禁用事件

所以您的代码将如下所示:

Private Ws_Open As Boolean
Private Sub Workbook_Open()
'
' set up drop down filter list
'
Application.EnableEvents = False
Range("A1").Select
With ThisWorkbook.Worksheets(1).Cmb_filter
    .Clear
    .AddItem "None"
    .AddItem "60% or less"
    .AddItem "70% or less"
    .AddItem "80% or less"
    .AddItem "90% or less"
    .ListIndex = 0
End With
Application.EnableEvents = True

【讨论】:

  • Application.EnableEvents 不会影响工作表上控件的Change 事件。您必须使用自己的变量。
  • @Rory : EnableEvents 不适用于控件? (我承认,我从不使用它们,因为我觉得它们很脏,我更喜欢一个好的用户窗体!)还有其他已知的限制吗?
  • @R3uK。我可以确认EnableEvents=False 没有效果(在这种特殊情况下)。我的意思是说我在最初的帖子中已经尝试过了。那么我该如何使用变量来管理呢??
  • @R3uK 它确实有效,但仅适用于容器公开的事件(GotFocus / LostFocus)。
  • @MiguelH : 我编辑了,如果够清楚请告诉我 ;)
【解决方案2】:

好的。找到了。似乎我确实需要一个模块。我无法使上述解决方案起作用。 Workbook 中的 Public 声明工作正常,但 Worksheet 无法访问变量?

最后我用

创建了 Module1
Public Ws_Open As Boolean

这使得所有工作簿对象都可以访问该变量。

以前我尝试过 Module 解决方案,但使用了 Private 变量声明!呸!

【讨论】:

  • @R3uK。只需更详细地阅读您的模块解决方案(答案 2)。这看起来很整洁!将代码放在模块中而不是在工作簿打开事件或工作表中(除了变量的可用性)有什么优势吗?当用户打开大量工作簿时,我偶尔会遇到无法正确触发 Workbook Open 事件的问题。我目前通过用户单击以手动触发工作簿打开事件的“刷新”按钮来解决此问题。
  • 就个人而言,我只是更喜欢这样进行,我发现在使用事件(和用户窗体)时更容易找到你在做什么,但我不确定是否存在真正的优势,这将使它几乎是强制性的。因此,如果您愿意,可以将所有内容保存在对象模块中! ;)
【解决方案3】:

您需要一个公共变量。例如: 本工作簿模块:

Public Ws_Open As Boolean
Private Sub Workbook_Open()
'
' set up drop down filter list
'
Range("A1").Select
ws_open = True
With ThisWorkbook.Worksheets(1).Cmb_filter
.List =  Array("None", "60% or less", "70% or less", "80% or less", "90% or less")
    .ListIndex = 0
End With
ws_Open = False
End Sub

然后在工作表中:

Private Sub Cmb_filter_Change()
 Dim intvalue As Integer
 If ThisWorkbook.ws_Open then exit sub
 Cmb_filter.BackColor = vbWhite
 Application.Run "'" & ThisWorkbook.Name & "'!Thisworkbook.clear_it"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多