【问题标题】:Hide or Unhide all Excel Sheets Without Looping隐藏或取消隐藏所有 Excel 工作表而不循环
【发布时间】:2017-10-25 21:49:46
【问题描述】:

我有一个包含 179 个工作表的工作簿。我想隐藏所有工作表(根据 Excel 规则保留一个不隐藏),或者取消隐藏所有工作表。

目前我的代码看起来像这样(根据我们是否隐藏/取消隐藏工作表进行适当的修改):

For Each Sht in Wb.Worksheets
    Sht.Visible = xlSheetVisible
Next Sht

有 179 个工作表,这需要 4-5 秒才能运行,我希望它运行得更快。

我知道如果我进入工作簿,手动选择所有工作表(除了一个),然后右键单击并选择"Hide",所有工作表都会立即隐藏。我无法在 VBA 代码中重现这一点。

如上所述,我需要以某种方式快速隐藏工作簿中的所有(除了一个)工作表,并取消隐藏工作簿中的所有工作表不循环。非常感谢任何帮助!

【问题讨论】:

  • 除非您想手动将所有 178 个工作表名称放入数组中:ThisWorkbook.Worksheets(Array("Sheet1","Sheet2",etc)).Visible = xlSheetHidden。您可能希望在将其设置为隐藏之前禁用屏幕更新、暂停计算、禁用事件。
  • 非常感谢所有回答的人,特别是 Excelosaurus 和 paul bica!两个天才的启示是,您可以通过将许多工作表添加到数组中来立即隐藏它们,并使用自定义视图来设置工作表的可见性。非常感谢您的辛勤工作和帮助!你们摇滚!
  • 我还想提一下,我昨晚想出了一个替代解决方案来解决我的问题(就像以前一样),它不包括隐藏或取消隐藏工作簿中的所有工作表。我意识到,如果我可以从只有 179 个工作表中的 1 个可见的工作簿开始该过程,那么我可以按名称取消隐藏我希望显示的工作表,然后按名称隐藏原始工作表(如果不是)目前适用于用户的目标。这样就没有循环了。不过,我仍然非常感谢所有答案!

标签: vba excel hide worksheet


【解决方案1】:

如前所述,您只能在没有循环的情况下隐藏多个工作表,如以下语句:

Worksheets(Array(1,2,3,4,5,6,7,8,9,10,11,...,200)).Visible = True

但取消隐藏多个工作表需要循环

但是,有一种更快的方法可以解决这个问题,使用自定义视图(在视图选项卡中)


下面的代码生成 2 个视图 1.“ShowAllWs”和 2.“HideAllWs”

性能方面:

For 201 Worksheets

Loop HideAll - Time: 0.039 sec (initial setup - sets array, except one Ws in one operation)
Loop ShowAll - Time: 0.648 sec (initial setup - unhides all using a loop)

View ShowAll - Time: 0.023 sec (consecutive runs - no loop)
View HideAll - Time: 0.023 sec (consecutive runs - no loop)

Option Explicit

Public Sub SetWsVisibility(Optional ByVal vis As Boolean = False, _
                           Optional ByVal visibleWs As Long = 0)

    Static vSet As Boolean, hSet As Boolean, wsCount As Long, lastV As Long, i As Long

    With ThisWorkbook

        wsCount = .Worksheets.Count - 1

        'if visibleWs is 0 last ws is visible, or use any other valid sheet index
        visibleWs = IIf(visibleWs < 1 Or visibleWs > wsCount, wsCount + 1, visibleWs)

        If wsCount <> .Worksheets.Count - 1 Or visibleWs <> lastV Then
            vSet = False
            hSet = False
        Else
            If vSet And vis Then .CustomViews("ShowAllWs").Show:        Exit Sub
            If hSet And Not vis Then .CustomViews("HideAllWs").Show:    Exit Sub
        End If

        Application.ScreenUpdating = False
        If vis Then
            For i = 1 To wsCount + 1
                With .Worksheets(i)
                    If Not .Visible Then .Visible = vis
                End With
            Next
            .Worksheets(1).Activate
            .CustomViews.Add ViewName:="ShowAllWs"  'Save View (one-time operation)
            vSet = True
        Else
            If visibleWs <> lastV Then
                For i = 1 To wsCount + 1
                    With .Worksheets(i)
                        If Not .Visible Then .Visible = 1
                    End With
                Next
            End If

            Dim arr() As Variant, j As Long
            ReDim arr(1 To wsCount)
            j = 1
            For i = 1 To wsCount + 1
                If i <> visibleWs Then arr(j) = i Else j = j - 1
                j = j + 1
            Next
            .Worksheets(arr).Visible = vis
            .CustomViews.Add ViewName:="HideAllWs"  'Save View (one-time operation)
            hSet = True
            lastV = visibleWs
        End If
        Application.ScreenUpdating = True
    End With
End Sub

要这样称呼它:

Public Sub UpdateWsVisibility()

    SetWsVisibility 0, 5    'or 0 to hide them (or True / False respectively)

End Sub

【讨论】:

  • 好主意!如果参数为 False,能够指定唯一可见的工作表会很酷。
【解决方案2】:

假设您的工作簿没有受到保护,这里有一个 sub 可以在没有系统循环的情况下做所有可能的事情。支持图表类型的工作表。

我刚刚了解到,通过数组引用工作表只有在它们都可见时才有效,因此在使工作表可见时需要循环。

'Hides all sheets in the workbook containing pExceptThisSheet, except pExceptThisSheet.
'Note: pExceptThisSheet is declared as an Object so as to support both the Worksheet and Chart types.
Public Sub HideAllSheetsBut(ByVal pExceptThisSheet As Object)
    On Error GoTo errHandler

    Dim vntAllSheetsBut() As Variant
    Dim oSht As Object
    Dim lIndex As Long
    Dim bScreenUpdating As Boolean

    bScreenUpdating = Application.ScreenUpdating
    Application.ScreenUpdating = False

    'Show all sheets.
    'Note: for some reason, an array can't be used here; must loop.
    For Each oSht In pExceptThisSheet.Parent.Sheets
        If oSht.Visible <> xlSheetVisible Then
            oSht.Visible = xlSheetVisible
        End If
    Next

    If Not pExceptThisSheet Is Nothing Then
        If pExceptThisSheet.Parent.Sheets.Count > 1 Then        
            'Hide all sheets but the specified one.        
            ReDim vntAllSheetsBut(0 To pExceptThisSheet.Parent.Sheets.Count - 2) As Variant

            lIndex = 0
            For Each oSht In pExceptThisSheet.Parent.Sheets
                If Not oSht Is pExceptThisSheet Then
                    vntAllSheetsBut(lIndex) = oSht.Name
                    lIndex = lIndex + 1
                End If
            Next
            'Note: for some reason, this only works for hiding, and if all sheets in vntAllSheetsBut are visible.
            'A possible explanation would be that, behind the scene, Excel attempts to select the sheets, and fails when it encounters hidden ones.
            pExceptThisSheet.Parent.Sheets(vntAllSheetsBut).Visible = xlSheetHidden
        End If
    End If

Cleanup:
    On Error Resume Next
    Set oSht = Nothing
    Application.ScreenUpdating = bScreenUpdating
    Exit Sub

errHandler:
    MsgBox Err.Description, vbExclamation + vbOKOnly, "Error"
    Resume Cleanup
End Sub

你可以这样调用子:

HideAllSheetsBut Sheet1

HideAllSheetsBut Application.Workbooks("MyWorkbook.xlsx").Worksheets("MyWorksheet")

隐藏除一个工作表以外的所有工作表,如下所示:

HideAllSheetsBut Nothing

显示所有工作表。

编辑 正如保罗比卡的回答中提到的,自定义视图是快速翻转多个工作表的可见性的好方法。在我的回答中,它将用于显示所有工作表,而无需遍历它们。

【讨论】:

    【解决方案3】:

    不妨试试这个:

    Application.ScreenUpdating = False
    
    For Each Sht in Wb.Worksheets
        If Sht.Visible = xlSheetHidden Then
            Sht.Visible = xlSheetVisible
        End If
    Next Sht
    
    Application.ScreenUpdating = True
    

    【讨论】:

      【解决方案4】:

      按照建议,您可以关闭屏幕更新。添加下面的 IF 语句以省略您想要的工作表(在我的称为“Main”,将其更改为您想要的)

      Sub HideSheets()
      
          Dim sht As Worksheet
      
          Application.ScreenUpdating = False
      
          For Each sht In ActiveWorkbook.Worksheets
              If sht.Name <> "Main" Then sht.Visible = False
          Next sht
      
          Application.ScreenUpdating = True
      
      End Sub
      

      卡利科

      【讨论】:

        【解决方案5】:

        试试这个...从录制的宏中

        Option Explicit
        
        Sub HideSheets()
        
            Worksheets.Select
            Sheets("Main").Activate
            ActiveWindow.SelectedSheets.Visible = False
        
        End Sub
        

        【讨论】:

          猜你喜欢
          • 2022-12-18
          • 2014-08-07
          • 1970-01-01
          • 2011-02-25
          • 2017-07-05
          • 2023-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多