代码之家  ›  专栏  ›  技术社区  ›  mattbierwirth

隐藏或取消隐藏所有Excel工作表而不循环

  •  2
  • mattbierwirth  · 技术社区  · 7 年前

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

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

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

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

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

    如上所述,我需要以某种方式快速隐藏工作簿中的所有(只有一个)工作表,并取消隐藏工作簿中的所有工作表 无循环

    5 回复  |  直到 7 年前
        1
  •  3
  •   paul bica    7 年前

    如前所述,您只能 隐藏 没有循环的多张图纸,如以下语句所示:

    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
    
        2
  •  2
  •   Excelosaurus    7 年前

    假设您的工作簿没有受到保护,这里有一个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
    

    您可以这样调用sub:

    HideAllSheetsBut Sheet1
    

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

    要隐藏除一个工作表之外的所有工作表,请执行以下操作:

    HideAllSheetsBut Nothing
    

    显示所有图纸。

    编辑 正如paul bica在回答中提到的,自定义视图是快速翻转多个工作表可见性的好方法。在我的回答中,它将用于显示所有工作表,而不必在它们上循环。

        3
  •  0
  •   dwirony Greg Viers    7 年前

    也许可以试试这个:

    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
  •  0
  •   Maldred    7 年前

    按照建议,您可以关闭屏幕更新。添加下面的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
    

    Caleeco公司

        5
  •  0
  •   jsotola    7 年前

    试试这个。。。从录制的宏

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