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

时间:2016-08-20 07:51:08

标签: excel vba excel-vba

我正在开发一个项目,以便在任何时候最小化excel工作簿中可见的工作表数量。我正在尝试创建一个父表单(用作切换按钮)来显示/隐藏子表单。例如,我在工作簿中有6张:输入,输入1和输入2,输出,输出1和输出。输出2.输入和输出将在激活时切换隐藏和取消隐藏其他工作表。我创建了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

3 个答案:

答案 0 :(得分:0)

根据用户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

备注

  1. 除非您有特定原因,否则请避免使用On Error Resume Next。如果出现问题,你的代码就会陷入停顿通常是一件好事,而不是保留自己的小秘密,而不是让你更聪明。

  2. .Visible属性本身是Boolean,因此条件.Visible = True相当于仅使用.Visible

  3. 您的.Visible语句可能无法解决您的意图。每行=中只有一个是分配运算符,其他行将是相等检查。在没有括号的情况下,它将是您的第一个=,而另一个=将是从右到左的逐步相等检查。这是运算符优先级正在运行。

  4. 关于最后一点,说表输入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>
    

    我认为的目的是:

    Sheets("Input 1").Visible = Not Sheets("Input 1").Visible ' i.e. toggle my visibility
    

    这些事情很难被布尔人接受,因为即使你的逻辑是错误的,结果也可能是正确的一半&#39;当时。

答案 1 :(得分:0)

我已成功完成这项工作。问题与尝试使用&#34;输出&#34;有关。私有子工作表_Activate()函数当&#34;输入1&#34;工作表已激活并隐藏。我添加了另一个名为&#34; Main&#34;取而代之的是,#34; Main&#34;激活该功能后,它将始终为活动选项卡。这解决了这个问题,尽管如果在导航每个&#34;文件夹中的内容时焦点没有跳到工作簿上会更好。这是更新的代码......

'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

我认为这是使用may标签简化工作簿的好方法。它可能会得到改善,所以期待听到任何建议。

这是我工作文件的链接

https://1drv.ms/x/s!AvtNNMCst1bIgxjCBCemZlCerHMo

答案 2 :(得分:0)

以下是您可以从onedrive下载文件的链接:

https://1drv.ms/x/s!Ah_zTnaUo4DzjhWzQ3OTq9tq1APC

我没有硬编码选择每张纸时应该发生什么,而是在'Controls'工作表上使用了ListObject(即Excel表)来存储'父'表和他们各种'子'之间的关系。代码只是检查此ListObject以查看哪些子项属于哪个父项,然后相应地执行操作。这还有一个额外的好处,就是让那些不了解VBA的人很容易添加或修改那些有需要的父/子表关系。

我还实现了一种“开发人员”模式,其中不会发生工作表隐藏。没有什么比尝试在一个仅仅像'用户'看待你的应用程序上进行开发更令人沮丧:-)你可以使用键盘快捷键Ctrl + Shift + D(开发人员D)在'用户'和'开发人员'模式之间切换它)。

以下是我刚放在一起的示例文件中的外观。我已将下面显示的ListObject添加到名为“Controls”的新工作表中,并为ListObject指定了“VisibleSheets”的名称: Controls

我还添加了一个名为DeveloperMode的命名区域,其值为TRUE: Name Manager

以下是在“用户”模式和“开发人员”模式之间切换应用程序的代码,该模式位于标准代码模块中:

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例程,以便您可以轻松地在模式之间切换。 (不要告诉用户这个键盘快捷键是什么):

Private Sub Workbook_Open()
Application.OnKey "^+D", "ToggleDeveloperMode"
End Sub

最后,这里的代码触发了DisplaySheets例程,也在ThisWorkbook模块中:

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    DisplaySheets
End Sub

它是一种享受。这是我在依次选择3个父表中的每一个时看到的内容: Inputs

Outputs

Throughputs

...这就是当我使用Ctrl + Shift + D快捷键将应用程序置于“开发人员”模式时会发生的情况,所有工作表都被取消隐藏,包括带有控件的工作表。 Controls

我建议为父标签提供与此处相同的颜色,以便用户更容易理解,无论选择性显示/消失的其他标签如何,它们都不会发生变化。

如果用户(或您)有可能想要重命名工作表,请使用代号而不是工作表名。如果你不确定我在说什么,请告诉我。