Forum Discussion
Using a drop down to hide/unhide columns in a table (VBA Code)
- Apr 22, 2024
Michael1835 To show/hide columns based on a selected employee, first open Name Manager and define a named range for the list of employees (referring to the applicable column headers). For example, define a new name called Employee_List that refers to: =Sheet1!$I$6:$DD$6. Next, create a Data Validation List in cell G6, with Source: =Employee_List. Then, open the Visual Basic Editor and use the following code in the Worksheet_Change event of the applicable worksheet module (Sheet1, in this example):
Private Sub Worksheet_Change(ByVal Target As Range) Dim rgEmployee As Range Set rgEmployee = Me.Range("G2") If Not Intersect(Target, rgEmployee) Is Nothing Then Dim rgList As Range, str As String, n As Variant Set rgList = Range("Employee_List") str = rgEmployee.Value n = Application.Match(str, rgList, 0) If IsError(n) Then rgList.EntireColumn.Hidden = False Else rgList.EntireColumn.Hidden = True rgList.Cells(, n).EntireColumn.Hidden = False End If End If End SubTo filter rows based on the "Check Training Status" selection in cell D2, I highly recommend looking into the Range.AutoFilter method, which will vary slightly depending on if your data is setup as a worksheet range or an Excel table (ListObject). As an example, the following code demonstrates how this could be achieved with an Excel table (ListObject), where the "Training Records out of Date" and "Retraining Required" columns are part of the table:
Sub CheckTrainingStatus() Dim tbl As ListObject, x As Long, y As Long Set tbl = Sheet1.ListObjects("Table1") x = tbl.ListColumns("Training Records out of Date").Index y = tbl.ListColumns("Retraining Required").Index With tbl.Range Select Case Sheet1.Range("D2").Value Case "Refresh" .AutoFilter Field:=x .AutoFilter Field:=y, Criteria1:="<>0" Case "Obsolete" .AutoFilter Field:=x, Criteria1:="<>0" .AutoFilter Field:=y Case Else 'All or blank .AutoFilter Field:=x .AutoFilter Field:=y End Select End With End SubTo apply the filter to the selected employee only, modify the worksheet formulas used in columns DE and DF to reference the matching column only. For example, if the original formula in cell DE7 was:
=SUM(I7:DD7)...you could change it to:
=IF(ISBLANK($G$2), SUM(I7:DD7), INDEX(I7:DD7, MATCH($G$2, Employee_List, 0)))Then, modify the Worksheet_Change event to call CheckTrainingStatus as needed. For example:
Private Sub Worksheet_Change(ByVal Target As Range) Dim rgEmployee As Range Set rgEmployee = Me.Range("G2") If Not Intersect(Target, rgEmployee) Is Nothing Then Dim rgList As Range, str As String, n As Variant Set rgList = Range("Employee_List") str = rgEmployee.Value n = Application.Match(str, rgList, 0) If IsError(n) Then rgList.EntireColumn.Hidden = False Else rgList.EntireColumn.Hidden = True rgList.Cells(, n).EntireColumn.Hidden = False End If Call CheckTrainingStatus ElseIf Not Intersect(Target, Me.Range("D2")) Is Nothing Then Call CheckTrainingStatus End If End SubNote: this is an example only, intended to help point you in the right direction. If your data is not formatted as an Excel table (ListObject), additional steps may be required to identify the AutoFilter Range and/or the Field Numbers of the columns to be filtered.
Your first screenshot shows the cause of your problem (no columns were hidden). Remember that in my first post I wrote "Put the following code into the Worksheet_Change event handler for the worksheet that contains…". The two dropdowns at the top of your (code) window show that you placed the code in the (General) (Declarations) section.
So make a temporary copy somewhere of all the code you have put in. Then:
- Delete everything from the (General) (Declarations) section.*
- Open the left dropdown (which shows you the objects that this code module can deal with) and select Worksheet. (The VB Editor then by default selects SelectionChange in the right dropdown and creates an empty event handler for that event. That event handler does not hurt anything, and you can optionally delete it later.)
- Open the right dropdown (which shows you the events to which the object at left can respond) and select Change. (The VB Editor then creates an empty event handler for the Worksheet_Change event.)
- Paste your copy of the code there.
This is approximately what you should see after step 3 (without the green comments, of course).
(Whether you see all procedures/code sections in the window, like this, or just one procedure/code section depends on which of the two buttons at the lower left of the code window is selected. If you see all at once, the content of the two dropdowns at the top of the window varies depending upon where the cursor is located.)
* In the future, you may need to put declarations of module-scope constants and/or variables and/or external routines here in the Declarations section (as it is usually called). But something that I strongly recommend you include here now is an "Option Explicit" statement, shown in my screenshot above. This tells the VBA interpreter (~compiler) that any variable name that it does not recognize should be flagged as a compile error; that will both identify variables which you have not declared (usually specifying a data type), and variables that you declared but for which you simply mistyped the name when trying to use them.
You can get the VB Editor to automatically include an Option Explicit statement in any new code module. From the Tools | Options… menu, you get the Options dialog:
Homework assignments: Read the first two-thirds of this tutorial for an overview of events in VBA. (I dislike that this author calls event handlers "macros". They are two different types of procedures.) Some YouTube videos on VBA events may be a good source of info, but I have not viewed any. And bookmark this site as an Excel reference.
SnowMan55 Thank you for your help, it's been solved now but when I put your code in the correct place (apologies still new to this) I managed to get the rows filter code working great and the first code you posted also worked as it should, I didn't manage to update the code to accept the extra columns but I'm sure that would of worked if I managed to type it correctly also. ![]()