【问题标题】:Hiding Rows with Excel 2013使用 Excel 2013 隐藏行
【发布时间】:2016-07-27 22:58:35
【问题描述】:

所以我尝试使用基于几个不同条件的 VBA 在 Excel 2013 中隐藏行:

  • 如果部分标题为“未使用”,则隐藏部分。每个部分都是一个命名范围,以简化此操作。
  • 如果行是“Cblank”命名范围的一部分,则隐藏它。
  • 现在是最难的部分——对于 Range("CNonTest") 中的每个单元格,如果 C.Value = "" 和 C.Columns(41).Value = "" 然后隐藏它们。

Range("CNonTest") 在 Col C 中,应检查的额外列是 Col AQ。

为了增加难度,我需要在每次 8 个不同验证框中的任何一个更改时运行此宏。

以下是我目前拥有的代码:

    Sub CompHide()

    With Sheets("Comparison").Cells
       .EntireRow.Hidden = False

    If Range("C9").Value = "Unused" Then
        Range("CMarket1").EntireRow.Hidden = True
    End If

    If Range("C115").Value = "Unused" Then
        Range("CMarket2").EntireRow.Hidden = True
    End If

    If Range("C221").Value = "Unused" Then
        Range("CMarket3").EntireRow.Hidden = True
    End If

    If Range("C329").Value = "Unused" Then
        Range("CMarket4").EntireRow.Hidden = True
    End If

    If Range("C437").Value = "Unused" Then
        Range("CMarket5").EntireRow.Hidden = True
    End If

    If Range("C545").Value = "Unused" Then
        Range("CMarket6").EntireRow.Hidden = True
    End If

    If Range("C653").Value = "Unused" Then
        Range("CMarket7").EntireRow.Hidden = True
    End If

    If Range("C761").Value = "Unused" Then
        Range("CMarket8").EntireRow.Hidden = True
    End If

    If Range("C869").Value = "Unused" Then
        Range("CMarket9").EntireRow.Hidden = True
    End If

    If Range("C977").Value = "Unused" Then
        Range("CMarket10").EntireRow.Hidden = True
    End If

    For Each C In Range("CNonTest")
        If C.Value = "" And C.Columns(41).Value = "" Then
            C.EntireRow.Hidden = True
        End If
    Next



    Range("CBlank").EntireRow.Hidden = True

    End With
End Sub

然后在工作表上我有这个代码:

    Private Sub Worksheet_Change(ByVal Target As Range)

If Intersect(Target, Me.Range("A4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("D4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("G4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("K4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("AO4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("AR4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("AU4")) Is Nothing _
    Or _
    Intersect(Target, Me.Range("AY4")) Is Nothing _
    Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True


End Sub

对于工作表代码,我也尝试过,但无济于事

Private Sub Worksheet_Change(ByVal Target As Range)

If Intersect(Target, Me.Range("A4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True



If Intersect(Target, Me.Range("D4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True



If Intersect(Target, Me.Range("G4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True



If Intersect(Target, Me.Range("K4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True



If Intersect(Target, Me.Range("AO4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True



If Intersect(Target, Me.Range("AR4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True



If Intersect(Target, Me.Range("AU4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True


If Intersect(Target, Me.Range("AY4")) Is Nothing Then Exit Sub

    Application.EnableEvents = False 'to prevent endless loop
    Application.ScreenUpdating = False

    Call CompHide

    Application.ScreenUpdating = True
    Application.EnableEvents = True


End Sub

这段代码似乎都运行良好,当我使用 F8 逐步完成 CompHide 时,它​​运行良好。所以我认为问题出在工作表本身的代码上。您会在该代码中看到一条注释,其中提到以防止无限循环,该注释来自一些不知道它的用途的手下代码,但根据我会留下的注释得出结论。

当我更改验证框时,它不再隐藏所有正确的东西,只隐藏其中的一些。幸运的是,我还没有看到它隐藏了一些它不应该隐藏的东西。我说不再是因为起初这段代码只查看了第一个验证框,但现在它查看了全部 8 个。

【问题讨论】:

    标签: vba excel excel-2013


    【解决方案1】:

    对事件处理程序的一些调整:

    Private Sub Worksheet_Change(ByVal Target As Range)
    
        Dim rng As Range
    
        On Error GoTo haveError
    
        Set rng = Application.Intersect(Target, Me.Range("A4,D4,G4,K4,AO4,AR4,AU4,AY4"))
    
        If Not rng Is Nothing Then
            Application.EnableEvents = False 'to prevent endless loop
            Application.ScreenUpdating = False
            CompHide
            Application.EnableEvents = True
        End If
        Exit Sub
    
    haveError:
        'always re-enable events
        '  (screenupdating setting is not persistent)...
        Application.EnableEvents = True
    
    End Sub
    

    其他部分:

    Sub CompHide()
    
        Dim sht As Worksheet, C As Range
    
        Set sht = Sheets("Comparison")
        sht.Rows.Hidden = False
    
        SetRowVis "C9", "CMarket1"
        SetRowVis "C115", "CMarket2"
        '...and the rest
    
        For Each C In sht.Range("CNonTest")
            If C.Value = "" And C.EntireRow.Columns(43).Value = "" Then
                C.EntireRow.Hidden = True
            End If
        Next
    
        sht.Range("CBlank").EntireRow.Hidden = True
    End Sub
    
    'utility sub...
    Sub SetRowVis(addr As String, rngName As String)
        With Sheets("Comparison")
            If .Range(addr).Value = "Unused" Then
                .Range(rngName).EntireRow.Hidden = True
            End If
        End With
    End Sub
    

    【讨论】:

    • 使用.EntireRow.Columns(43) 引用第 43 列而不考虑起始范围是非常聪明的。
    • 感谢您的帮助,我将在周五回到办公室时进行测试。但是阅读它很有意义
    • 也同意@Thomas 的观点,.entirerow.columns(43) 是个好主意。
    • 等不及了,所以我在工作中远程访问了我的计算机。这些轻微的代码修改是完美的解决方案。我确实有两个后续问题需要澄清。 1)您在其中一个 cmets 中声明 "always re-enable (screenupdating setting is not persistent)" 但是 Application.ScreenUpdating = True 的代码不存在所以我很好奇您的意思是什么。我在我的上面添加了那行代码。 2)只是想知道防止endloops的代码就是你是否碰巧知道。
    • 1) 那条评论措辞不当:一开始是“总是重新启用事件”,但最后我标记了关于屏幕更新的位。我将对其进行编辑以使其更清晰。 2) 通常在从事件处理程序中对工作表进行更改时,可能会重新触发事件,这在某些情况下可能会让您陷入无限循环。此处并非如此,因为仅隐藏或显示行不会触发更改事件,因此关闭事件并没有真正退休。
    【解决方案2】:

    第一,您的CompHide Sub 有引用问题。
    您需要完全引用对工作表的所有 Range 对象调用。

    With Sheets("Comparison")
        .Cells.EntireRow.Hidden = False
        'Notice the dot in front of the Range object
        If .Range("C9").Value = "Unused" Then .Range("CMarket1").EntireRow.Hidden = True
        'Also notice that I used a one liner IF which I think is applicable for you
        'Rest of your code go here
        '.
        '.
        '.
    
    End With
    

    第二,看看蒂姆的帖子。他打败了我。 :)

    【讨论】:

    • 感谢你的想法,即使他打败了你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多