VBA event change to hide specific rows (dynamic amount) determined by cell value

wbstadeli

Board Regular
Joined
Mar 11, 2016
Messages
156
Office Version
  1. 365
Platform
  1. Windows
Hi,

Im trying to come up with code that the following sample simulates:

Within an excel table, one of the columns (B) can have different values. There is "Item" and then the rows beneath that row pertain to that specific item, until the next "Item" then it repeats this pattern (the amount of rows beneath an item is variable, not a set amount). For example one item may have 3 rows of "Time". What remains as a constant is whenever there is "Item", that item has its own set of rows pertaining to it, underneath, until the next "Item".

What I want to do in VBA is, create a worksheet change event that when I select "Hide Rows" (from a dropdown list) in cell left of "Item", it hides all rows between that ITEM (row that the "Hide Rows" event trigger is on) and the next ITEM. Then I would also like the reverse option, "Show Rows" to unhide the pertaining rows to the specific item (determined by the event trigger cell to the left of the "Item" trying to unhide row underneath.

Thank you for any help!

ABC
1Dropdown list selection hereItem
2CostsThis row pertains to Item B1
3TimeThis row pertains to Item B1
4DividerThis row pertains to Item B1
5BreakoutsThis row pertains to Item B1
6Item DividerThis row pertains to Item B1
7Dropdown list selection hereItem
8CostsThis row pertains to Item B7
9TimeThis row pertains to Item B7
10etc...This row pertains to Item B7
 
How about this,
VBA Code:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim ws As Worksheet: Set ws = Me
    If Target.Column <> 1 Or Target.Cells.Count > 1 Then Exit Sub
    If LCase(Trim(Target.Offset(0, 1).Value)) <> "item" Then Exit Sub

    Dim action As String: action = LCase(Trim(Target.Value))
    Dim startRow As Long: startRow = Target.Row + 1
    Dim endRow As Long: endRow = startRow
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    Application.EnableEvents = False
    Do While endRow <= ws.Rows.Count
        If LCase(Trim(ws.Cells(endRow, 2).Value)) = "item" Or ws.Cells(endRow, 2).Value = "" Then Exit Do
        endRow = endRow + 1
    Loop

    If endRow > startRow Then
        ws.Rows(startRow & ":" & endRow - 1).EntireRow.Hidden = (action = "hide rows")
    End If
    Application.EnableEvents = True
End Sub
Assuming this is how your data is,
1744142936678.png
 
Upvote 0
Solution
Or without loop.
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim s$, lr&, x&, myRow&
    If Target.Column <> 1 Then Exit Sub
    If UCase$(Target(, 2)) <> "ITEM" Then Exit Sub
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    lr = [max(if(b1:b50000<>"",row(1:50000)))]
    myRow = Target.Row + 1
    s = "b1:b" & lr
    x = Evaluate(Replace("min(if((#=""Item"")*(row(#)>" & myRow & "),row(#)))", "#", s))
    If x = 0 Then x = lr + 1
    Rows(Target.Row + 1 & ":" & x - 1).Hidden = UCase$(Target.Value) = "HIDE ROWS"
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub
 
Upvote 0
Or,
VBA Code:
Private Sub Worksheet_Change(ByVal t As Range)
    If t.Column <> 1 Or UCase$(t(1, 2)) <> "ITEM" Then Exit Sub
    Dim a$, b&, c&, d&, w, f
    Set w = Me: a = UCase$(t.Value): b = t.Row + 1
    Application.EnableEvents = False: Application.ScreenUpdating = False
    Set f = w.Columns(2).Find("Item", w.Cells(b - 1, 2), , 1, 1, 1)
    c = w.UsedRange.Rows(w.UsedRange.Rows.Count).Row + 1
    d = IIf(f Is Nothing Or f.Row <= t.Row, c, f.Row)
    w.Rows(b & ":" & d - 1).Hidden = (a = "HIDE ROWS")
    Application.EnableEvents = True: Application.ScreenUpdating = True
End Sub
 
Upvote 0
How about this,
VBA Code:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim ws As Worksheet: Set ws = Me
    If Target.Column <> 1 Or Target.Cells.Count > 1 Then Exit Sub
    If LCase(Trim(Target.Offset(0, 1).Value)) <> "item" Then Exit Sub

    Dim action As String: action = LCase(Trim(Target.Value))
    Dim startRow As Long: startRow = Target.Row + 1
    Dim endRow As Long: endRow = startRow
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    Application.EnableEvents = False
    Do While endRow <= ws.Rows.Count
        If LCase(Trim(ws.Cells(endRow, 2).Value)) = "item" Or ws.Cells(endRow, 2).Value = "" Then Exit Do
        endRow = endRow + 1
    Loop

    If endRow > startRow Then
        ws.Rows(startRow & ":" & endRow - 1).EntireRow.Hidden = (action = "hide rows")
    End If
    Application.EnableEvents = True
End Sub
Assuming this is how your data is,
View attachment 124206
Thank you! This code is a great starting point for me, sure appreciate your help!
 
Upvote 0
Or without loop.
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim s$, lr&, x&, myRow&
    If Target.Column <> 1 Then Exit Sub
    If UCase$(Target(, 2)) <> "ITEM" Then Exit Sub
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    lr = [max(if(b1:b50000<>"",row(1:50000)))]
    myRow = Target.Row + 1
    s = "b1:b" & lr
    x = Evaluate(Replace("min(if((#=""Item"")*(row(#)>" & myRow & "),row(#)))", "#", s))
    If x = 0 Then x = lr + 1
    Rows(Target.Row + 1 & ":" & x - 1).Hidden = UCase$(Target.Value) = "HIDE ROWS"
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub
Im using Sam_D_Ben's first reply as a starting base, but thank you for your time on this!
 
Upvote 0

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top