Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于在隐藏/取消隐藏之间切换的Excel VBA工作表事件_Vba_Excel - Fatal编程技术网

用于在隐藏/取消隐藏之间切换的Excel VBA工作表事件

用于在隐藏/取消隐藏之间切换的Excel VBA工作表事件,vba,excel,Vba,Excel,我正在进行一个项目,以尽量减少在任何给定时间excel工作簿中可见的工作表数量。我正在尝试创建一个父图纸(用作切换按钮)以显示/隐藏子图纸。例如,我的工作簿中有6张工作表:输入、输入1和输入2、输出、输出1和输出2。激活时,输入和输出将切换隐藏和取消隐藏其他工作表。我创建了两个工作表级别的子函数来尝试这样做。第一个非常有效,但另一个只有在第一个被激活并再次隐藏后才有效。任何关于更好的方法的建议都会很好。我不知道为什么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
    语句可能无法解析您希望它们的方式。每行上只有一个
    =
    是赋值运算符,其他将是相等检查。在没有括号的情况下,它将是您的第一个
    =
    ,而另一个
    =
    将是从右到左逐步进行的相等性检查。这是运算符在工作时的优先级

  • 关于最后一点,假设图纸输入1可见,则第一行将解析为:

    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