用于在隐藏/取消隐藏之间切换的Excel VBA工作表事件
我正在进行一个项目,以尽量减少在任何给定时间excel工作簿中可见的工作表数量。我正在尝试创建一个父图纸(用作切换按钮)以显示/隐藏子图纸。例如,我的工作簿中有6张工作表:输入、输入1和输入2、输出、输出1和输出2。激活时,输入和输出将切换隐藏和取消隐藏其他工作表。我创建了两个工作表级别的子函数来尝试这样做。第一个非常有效,但另一个只有在第一个被激活并再次隐藏后才有效。任何关于更好的方法的建议都会很好。我不知道为什么excel没有这个功能。我尝试使用数组,但似乎不起作用。我认为您需要逐个取消隐藏每个选项卡用于在隐藏/取消隐藏之间切换的Excel VBA工作表事件,vba,excel,Vba,Excel,我正在进行一个项目,以尽量减少在任何给定时间excel工作簿中可见的工作表数量。我正在尝试创建一个父图纸(用作切换按钮)以显示/隐藏子图纸。例如,我的工作簿中有6张工作表:输入、输入1和输入2、输出、输出1和输出2。激活时,输入和输出将切换隐藏和取消隐藏其他工作表。我创建了两个工作表级别的子函数来尝试这样做。第一个非常有效,但另一个只有在第一个被激活并再次隐藏后才有效。任何关于更好的方法的建议都会很好。我不知道为什么excel没有这个功能。我尝试使用数组,但似乎不起作用。我认为您需要逐个取消隐藏
'1. Inputs:
Private Sub Worksheet_Activate()
On Error Resume Next
Sheets("Input 1").Visible = True = Not Sheets("Input 1").Visible = True
Sheets("Input 2").Visible = True = Not Sheets("Input 2").Visible = True
Sheets("Input 1").Activate 'needed to deactivate inputs sheet
End Sub
'2. Outputs
Private Sub Worksheet_Activate()
On Error Resume Next
Sheets("Output 1").Visible = True = Not Sheets("Output 1").Visible = True
Sheets("Output 2").Visible = True = Not Sheets("Output 2").Visible = True
Sheets("Output 1").Activate 'needed to deactivate Outputs sheet
End Sub
根据用户3598756的说法,这个问题可能需要一些澄清,但是听起来你好像在模仿类似的行为:
Action Visible Worksheet
------ -----------------
Open Workbook [Input], [Output]
Activate [Input] [Input], [Output], [Input1], [Input2] ' (shows InputX)
Activate [Input1] [Input], [Output], [Input1], [Input2] ' (no change)
Activate [Output] [Input], [Output], [Output1], [Output2] ' (hides InputX, shows OutputX)
这使得[Input]
和[Output]
成为您唯一的网关工作表,因此下面的[Input]
(与[Output]
相反)将实现这一点
Private Sub Worksheet_Activate()
Sheets("Input 1").Visible = True
Sheets("Input 2").Visible = True
Sheets("Output 1").Visible = False
Sheets("Output 2").Visible = False
End Sub
注释
.Visible
属性本身是一个布尔值
,因此有条件的.Visible=True
等同于仅使用.Visible
.Visible
语句可能无法解析您希望它们的方式。每行上只有一个=
是赋值运算符,其他将是相等检查。在没有括号的情况下,它将是您的第一个=
,而另一个=
将是从右到左逐步进行的相等性检查。这是运算符在工作时的优先级Sheets("Input 1").Visible = True = Not Sheets("Input 1").Visible = True
Sheets("Input 1").Visible = True = Not <True> = True
Sheets("Input 1").Visible = True = Not <True>
Sheets("Input 1").Visible = True = <False>
Sheets("Input 1").Visible = <False>
这些东西可能很难用布尔语言来理解,因为即使你的逻辑是错误的,结果也有一半是正确的。我已经成功地做到了这一点。问题与在激活和隐藏“输入1”工作表时尝试使用“输出”专用子工作表_Activate()函数有关。我添加了另一个名为“Main”的选项卡来替换此选项卡,因此在激活功能后,“Main”将始终是活动选项卡。这就解决了这个问题,尽管在浏览每个“文件夹”中的内容时,如果焦点不在工作簿中跳跃会更好。这里是更新的代码
'Inputs "Parent folder" sheet
Private Sub Worksheet_Activate()
On Error Resume Next
Sheets("Input 1").Visible = True = Not Sheets("Input 1").Visible = True
Sheets("Input 2").Visible = True = Not Sheets("Input 2").Visible = True
**Sheets("Main").Activate** 'needed to deactivate Inputs sheet
End Sub
'Outputs "Parent folder" sheet
Private Sub Worksheet_Activate()
On Error Resume Next
Sheets("Output 1").Visible = True = Not Sheets("Output 1").Visible = True
Sheets("Output 2").Visible = True = Not Sheets("Output 2").Visible = True
**Sheets("Main").Activate** 'needed to deactivate Outputs sheet
End Sub
我认为这是一个很好的方法来简化工作手册与五月标签。它可以大胆地改进,所以期待听到任何建议
这是我的工作文件的链接
这里有一个链接,指向可以从onedrive下载的文件: 我在“控件”工作表上使用ListObject(即Excel表格)来存储“父”工作表与其各个“子”工作表之间的关系,而不是硬编码选择每个工作表时应该发生的事情。代码只是检查这个ListObject以查看哪些子对象属于哪个父对象,然后采取相应的操作。这样做的额外好处是,对于一点也不了解VBA的人来说,添加或修改需要的父/子工作表关系非常容易 我还实现了一种“开发人员”模式,在这种模式下不会发生工作表隐藏。没有什么比尝试在一个将您视为“用户”的应用程序上进行开发更令人沮丧的了:-)您可以使用键盘快捷键Ctrl+Shift+D(D代表开发者)在“用户”和“开发者”模式之间切换 下面是我刚刚整理的示例文件中的内容。我已将如下所示的ListObject添加到名为“Controls”的新工作表中,并将ListObject命名为“VisibleSheets”: 我还添加了一个名为DeveloperMode的命名范围,其值为TRUE: 下面是在标准代码模块中的“用户”模式和“开发人员”模式之间切换应用程序的代码:
Public Sub ToggleDeveloperMode()
Dim ws As Worksheet
If ActiveWorkbook.Names("DeveloperMode").Value = "=TRUE" Then
ActiveWorkbook.Names("DeveloperMode").Value = "=FALSE"
Else
ActiveWorkbook.Names("DeveloperMode").Value = "=TRUE"
For Each ws In ActiveWorkbook.Worksheets
ws.Visible = xlSheetVisible
Next ws
End If
End Sub
Sub DisplaySheets()
Dim ws As Worksheet
Dim lo As ListObject
Dim lc As ListColumn
Dim vMatch As Variant
Set lo = Range("VisibleSheets").ListObject
If Not [DeveloperMode] Then
For Each lc In lo.ListColumns
If lc.Name = ActiveSheet.Name Then
For Each ws In ActiveWorkbook.Worksheets
Set vMatch = Nothing 'Reset from last pass
vMatch = Application.Match(ws.Name, lo.HeaderRowRange, 0)
If IsError(vMatch) Then 'It's not one of our main sheets
Set vMatch = Nothing 'Reset from last pass
vMatch = Application.Match(ws.Name, lc.Range, 0)
If IsError(vMatch) Then
ws.Visible = xlSheetVeryHidden
Else
ws.Visible = xlSheetVisible
End If
End If
Next ws
End If
Next lc
End If
End Sub
下面是实际执行所有隐藏和取消隐藏的代码,它也包含在标准代码模块中:
Public Sub ToggleDeveloperMode()
Dim ws As Worksheet
If ActiveWorkbook.Names("DeveloperMode").Value = "=TRUE" Then
ActiveWorkbook.Names("DeveloperMode").Value = "=FALSE"
Else
ActiveWorkbook.Names("DeveloperMode").Value = "=TRUE"
For Each ws In ActiveWorkbook.Worksheets
ws.Visible = xlSheetVisible
Next ws
End If
End Sub
Sub DisplaySheets()
Dim ws As Worksheet
Dim lo As ListObject
Dim lc As ListColumn
Dim vMatch As Variant
Set lo = Range("VisibleSheets").ListObject
If Not [DeveloperMode] Then
For Each lc In lo.ListColumns
If lc.Name = ActiveSheet.Name Then
For Each ws In ActiveWorkbook.Worksheets
Set vMatch = Nothing 'Reset from last pass
vMatch = Application.Match(ws.Name, lo.HeaderRowRange, 0)
If IsError(vMatch) Then 'It's not one of our main sheets
Set vMatch = Nothing 'Reset from last pass
vMatch = Application.Match(ws.Name, lc.Range, 0)
If IsError(vMatch) Then
ws.Visible = xlSheetVeryHidden
Else
ws.Visible = xlSheetVisible
End If
End If
Next ws
End If
Next lc
End If
End Sub
下面是ThisWorkbook模块中的一段代码,它将键盘快捷键Ctrl+Shift+D指定给ToggleDeveloperMode例程,以便您可以轻松地在模式之间切换。(不要告诉用户此键盘快捷键是什么):
最后,这里是触发DisplaySheets例程的代码,该例程也位于ThisWorkbook模块中:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
DisplaySheets
End Sub
这是一种享受。以下是我依次选择3个父图纸时看到的内容:
…下面是当我使用Ctrl+Shift+D快捷键将应用程序置于“开发人员”模式时发生的情况,所有工作表都未隐藏,包括带有控件的工作表。
我建议将父选项卡的颜色设置为与此处相同的颜色,以便用户更容易理解,无论其他选项卡有选择地出现/消失,它们都不会改变
如果用户(或您)可能希望重命名工作表,请使用代码名而不是工作表名。如果您不确定我在说什么,请告诉我。显然您正在使用
工作表\u Activate()
事件来显示或隐藏工作表。但此外,您正在使用此事件激活另一张图纸。通过这样做,您(递归地)激活了该工作表的事件工作表\u Activate()
。如果该工作表上再次出现工作表\u Activate()
的代码,则该工作表也会被激活(依此类推)。因此,您可能需要在之前添加Application.EnableEvents=False