If Else VBA Issue - vba

My problem is that my code does not pick up the "Medium" variable
If Range("B24").Value = "Medium" Then
Sheets("Sheet2").Visible = True
Can you please advise what's wrong with it ("Standard" should uncover rows, "Medium" should keep them hidden but unhide the Sheet2, High again keeps the rows hidden but unhides Sheet2, if (B24) is empty it should keep rows and Sheet2 hidden:
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("B24").Value = "Standard" Then
Sheets("Sheet2").Visible = False
End If
If Range("B24").Value = "Medium" Then
Sheets("Sheet2").Visible = True
End If
If Range("B24").Value = "High" Then
Sheets("Sheet2").Visible = True
End If
Else
Sheets("Sheet2").Visible = False
End If
If Range("B24").Value = "Standard" Then
Rows("29:47").EntireRow.Hidden = False
Else
Rows("29:47").EntireRow.Hidden = True
End If
End Sub

You are obviously missing an If, and your code should not be working. This is how it looks like, when it is formatted:
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("B24").Value = "Standard" Then
Sheets("Sheet2").Visible = False
End If
If Range("B24").Value = "Medium" Then
Sheets("Sheet2").Visible = True
End If
If Range("B24").Value = "High" Then
Sheets("Sheet2").Visible = True
End If
'Is this Else an IF?
Else
Sheets("Sheet2").Visible = False
End If
If Range("B24").Value = "Standard" Then
Rows("29:47").EntireRow.Hidden = False
Else
Rows("29:47").EntireRow.Hidden = True
End If
End Sub
If you omit the If-Else, the code would look a bit better with a Select-Case statement:
Private Sub Worksheet_Change(ByVal Target As Range)
Select Case Range("B24")
Case "Standard"
Sheets("Sheet2").Visible = False
Rows("29:47").EntireRow.Hidden = False
Case "Medium"
Sheets("Sheet2").Visible = True
Rows("29:47").EntireRow.Hidden = True
Case "High"
Sheets("Sheet2").Visible = True
Rows("29:47").EntireRow.Hidden = True
Case Else
Sheets("Sheet2").Visible = False
Rows("29:47").EntireRow.Hidden = True
End Select
End Sub
You can probably go one step further, by writing Rows("29:47").EntireRow.Hidden = True before the select case and remove this line from cases, thus following the Do-Not-Repeat-Yourself principle. But in this case it is probably not needed.
If you want to add a second range, something like this is possible:
Select Case True
Case Range("B24") = "Standard"
Case Range("B26") = "Medium"
End Select
However, it would evaluate just once, thus if both are true, B26 is not going to happen.

Related

Group Box content - hide based on cell value

I have the following code:
Private Sub Worksheet_Calculate()
Application.EnableEvents = False
Select Case Range("B14")
Case "Medium Risk"
Rows("6:12").EntireRow.Hidden = True
Case Else
Rows("6:12").EntireRow.Hidden = False
End Select
Application.EnableEvents = True
End Sub
What I need is: to hide Group Box "content" based on the value in B14.
Group Box 15 surrounds a CheckBox8_Click.
Any ideas?
Thanks
I decided that I will simply settle with hiding a row [based on cell criteria] where the object is:
Private Sub Worksheet_Calculate()
Application.EnableEvents = False
Select Case Range("B14")
Case "Medium Risk"
Rows("6:12").EntireRow.Hidden = True
Rows("24").EntireRow.Hidden = True
Case Else
Rows("6:12").EntireRow.Hidden = False
Rows("24").EntireRow.Hidden = False
End Select
Application.EnableEvents = True
End Sub

Compiler error on if statement

I am new to coding/scripting. Its a school project, I would have to change the below code to add Application.EnableEvents to the existing code to suppress the Change event in other macros.
I tried to change the code, but I get a compile error else without if. I validated the syntax, it looks OK. What am I doing wrong here? Is my understanding with "IF" statements not correct?
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("E43")) Is Nothing Then
With Range("E44")
If Target.Value = "Specific number of Days" Then
.Locked = False
.Activate
Else
'This handles **ANY** other value in the dropdown
.Locked = True
'.Clear
End If
End With
ElseIf Not Intersect(Target, Range("E30")) Is Nothing Then
If Target.Value = "YES" Then Call Class8 Else Call Class8User
ElseIf Not Intersect(Target, Range("E31")) Is Nothing Then
If Target.Value = "YES" Then Call Class7 Else Call Class7User
End If
Application.EnableEvents = True
End Sub
I am trying to change the code as below.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("E43")) Is Nothing Then
With Range("E44")
If Target.Value = "Specific number of Days" Then
.Locked = False
.Activate
Else
'This handles **ANY** other value in the dropdown
.Locked = True
'.Clear
End If
End With
ElseIf Not Intersect(Target, Range("E30")) Is Nothing Then
If Target.Value = "YES" Then
Application.EnableEvents = False
Call Notify
Application.EnableEvents = True
Else
Application.EnableEvents = False
Call NotifyUser
Application.EnableEvents = True
ElseIf Not Intersect(Target, Range("E31")) Is Nothing Then
If Target.Value = "YES" Then
Application.EnableEvents = False
Call Delta
Application.EnableEvents = True
Else
Application.EnableEvents = False
Call DeltaUser
Application.EnableEvents = True
End If
End If
Application.EnableEvents = True
End Sub
Always indent all your code - then you can easily see where you are missing the end if
Private Sub x(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("E43")) Is Nothing Then
With Range("E44")
If Target.Value = "Specific number of Days" Then
.Locked = False
.Activate
Else
'This handles **ANY** other value in the dropdown
.Locked = True
'.Clear
End If
End With
ElseIf Not Intersect(Target, Range("E30")) Is Nothing Then
If Target.Value = "YES" Then
Application.EnableEvents = False
Call notify
Application.EnableEvents = True
Else
Application.EnableEvents = False
Call notifyuser
Application.EnableEvents = True
End If ' <-- This was missing
ElseIf Not Intersect(Target, Range("E31")) Is Nothing Then
If Target.Value = "YES" Then
Application.EnableEvents = False
Call delta
Application.EnableEvents = True
Else
Application.EnableEvents = False
Call deltaUser
Application.EnableEvents = True
End If ' <-- This was missing
End If
Application.EnableEvents = True
End Sub

Looking for ways to simplify my code

I'm having trouble adding another function in that macro I used to activate or deactivate columns in a Excel Workbook we are using at work. I'm getting the Out of stack space error when running it just adding one of the following function.
Mostly, I've used an If( ;1;0) to manage the activation part and an If(;TRUE;FALSE) for the locked/unlocked part. The function I want to had is based on the same idea using a verification code to Clearcontents of a cell and locked it. If the verification code is false, then, I want the cell to be unlocked so the user can write the value. Here is the code line I want to had times 15 as already done for the locked, unlocked function.
If Range("AS16") = "Vrai" Then
Range("AA16").ClearContents
Range("AA16").Locked = True
Else:
Range("AA16").Locked = False
End If
Here is the code I'm using right now.
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveSheet.Unprotect ("Francis")
Dim Cell As Range
Set Cell = ActiveCell
Application.ScreenUpdating = False
For Each cellule In Range("S50:X50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule
For Each cellule In Range("S50:X50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule
For Each cellule In Range("I50:J50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule
For Each cellule In Range("I50:J50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule
If Range("AR16") = "Vrai" Then
Range("K16").Locked = False
Range("O16").Locked = False
Else:
Range("K16").Locked = True
Range("O16").Locked = True
End If
If Range("AR18") = "Vrai" Then
Range("K18").Locked = False
Range("O18").Locked = False
Else:
Range("K18").Locked = True
Range("O18").Locked = True
End If
If Range("AR20") = "Vrai" Then
Range("K20").Locked = False
Range("O20").Locked = False
Else:
Range("K20").Locked = True
Range("O20").Locked = True
End If
If Range("AR22") = "Vrai" Then
Range("K22").Locked = False
Range("O22").Locked = False
Else:
Range("K22").Locked = True
Range("O22").Locked = True
End If
If Range("AR24") = "Vrai" Then
Range("K24").Locked = False
Range("O24").Locked = False
Else:
Range("K24").Locked = True
Range("O24").Locked = True
End If
If Range("AR26") = "Vrai" Then
Range("K26").Locked = False
Range("O26").Locked = False
Else:
Range("K26").Locked = True
Range("O26").Locked = True
End If
If Range("AR28") = "Vrai" Then
Range("K28").Locked = False
Range("O28").Locked = False
Else:
Range("K28").Locked = True
Range("O28").Locked = True
End If
If Range("AR30") = "Vrai" Then
Range("K30").Locked = False
Range("O30").Locked = False
Else:
Range("K30").Locked = True
Range("O30").Locked = True
End If
If Range("AR32") = "Vrai" Then
Range("K32").Locked = False
Range("O32").Locked = False
Else:
Range("K32").Locked = True
Range("O32").Locked = True
End If
If Range("AR34") = "Vrai" Then
Range("K34").Locked = False
Range("O34").Locked = False
Else:
Range("K34").Locked = True
Range("O34").Locked = True
End If
If Range("AR36") = "Vrai" Then
Range("K36").Locked = False
Range("O36").Locked = False
Else:
Range("K36").Locked = True
Range("O36").Locked = True
End If
If Range("AR38") = "Vrai" Then
Range("K38").Locked = False
Range("O38").Locked = False
Else:
Range("K38").Locked = True
Range("O38").Locked = True
End If
If Range("AR40") = "Vrai" Then
Range("K40").Locked = False
Range("O40").Locked = False
Else:
Range("K40").Locked = True
Range("O40").Locked = True
End If
If Range("AR42") = "Vrai" Then
Range("K42").Locked = False
Range("O42").Locked = False
Else:
Range("K42").Locked = True
Range("O42").Locked = True
End If
If Range("AR44") = "Vrai" Then
Range("K44").Locked = False
Range("O44").Locked = False
Else:
Range("K44").Locked = True
Range("O44").Locked = True
End If
Application.ScreenUpdating = True
Application.Goto Cell
'ActiveSheet.Protect Password:="Francis"
End Sub
Thanks a lot for your help.
Have a nice day!
You typically don't want to have performance-expensive code running in that specific handler. Worksheet_Change gets invoked every time a cell changes... and that includes changing a cell's Locked property value.
So that's how you run out of stack space: your handler is modifying cells' Locked state, which triggers the Worksheet_Change event, which modifies cells' Locked state, which triggers the Worksheet_Change event, which modifies cells' Locked state, which triggers the Worksheet_Change event, which... which eventually blows the call stack.
So prevent this accidental recursion, you need to prevent Excel from firing worksheet events when you're handling one:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo CleanFail
Application.EnableEvents = False
'do stuff
CleanExit:
Application.EnableEvents = True
Exit Sub
CleanFail:
'handle errors here...
Resume CleanExit
End Sub
As for simplifying the code, that's more of a mandate for Code Review Stack Exchange, once your code works as intended.
If any C# dev is reading this, this particular situation now has an up-for-grabs issue on Rubberduck's GitHub repository: #3109 Prevent accidental recursion in Worksheet_Change and Workbook_SheetChange handlers; once that inspection is implemented, Rubberduck will be able to warn you when you handle Worksheet_Change without disabling application events.
The Out of stack error is caused by the Change event, as noted by #Mat
Try this version which also turns the events off and on
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cellule As Range, r As Long, isVrai As Boolean
ActiveSheet.Unprotect "Francis"
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
For Each cellule In Union(Range("I50:J50"), Range("S50:X50"))
With cellule
Select Case .Value2
Case "1": .EntireColumn.Hidden = False
Case "0": .EntireColumn.Hidden = True
End Select
End With
Next
For r = 16 To 44 Step 2
isVrai = (Range("AR" & r).Value2 = "Vrai")
Range("K" & r).Locked = Not isVrai
Range("O" & r).Locked = Not isVrai
If isVrai Then Range("AR" & r).ClearContents
Next
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
'ActiveSheet.Protect Password:="Francis"
End Sub
This section can be simplified:
For Each cellule In Range("S50:X50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule
For Each cellule In Range("S50:X50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule
For Each cellule In Range("I50:J50")
If cellule.Value = "1" Then cellule.EntireColumn.Hidden = False
Next cellule
For Each cellule In Range("I50:J50")
If cellule.Value = "0" Then cellule.EntireColumn.Hidden = True
Next cellule
To the following (however, note that this will unhide any non-zero values).
For Each cellule in Range("S50:X50")
cellule.EntireColumn.Hidden = (cellule.Value = "0")
Next
For Each cellule in Range("I50:J50")
cellule.EntireColumn.Hidden = (cellule.Value = "0")
Next
And this section:
If Range("AR16") = "Vrai" Then
Range("K16").Locked = False
Range("O16").Locked = False
Else:
Range("K16").Locked = True
Range("O16").Locked = True
End If
If Range("AR18") = "Vrai" Then
Range("K18").Locked = False
Range("O18").Locked = False
Else:
Range("K18").Locked = True
Range("O18").Locked = True
End If
....
Can be simplified using a loop over Range("AR16:AR44")
For Each cellule in Range("AR16:AR44") Step 2
cellule.Offset(,-33).Locked = (cellule.Value = "Vrai")
cellule.Offset(,-29).Locked = (cellule.Value = "Vrai")
Next

Optimizing VBA including AND statement within IF

I was wondering if there was a way to optimize this set of code
Sub BBG_Transmital()
'Hides Sections Not Used in Expanded Form
Dim CollapseRange1 As Range
Dim CollapseRange2 As Range
'Set Which Range/Cell to Associate with Marked CheckBox
With ActiveDocument.Tables(3)
Set CollapseRange1 = .Rows(10).Range
CollapseRange1.End = .Rows(13).Range.End
End With
With ActiveDocument.Tables(3)
Set CollapseRange2 = .Rows(16).Range
CollapseRange2.End = .Rows(21).Range.End
End With
'If Box is Checked then CollapseRanges
If CheckBox1.Value = True Then
CollapseRange1.Font.Hidden = True
'If Box is Not Checked then UncollapseRange
Else
CollapseRange1.Font.Hidden = False
End If
'If Box is Checked then CollapseRanges
If CheckBox1.Value = True Then
CollapseRange2.Font.Hidden = True
'If Box is Not Checked then UncollapseRange
Else
CollapseRange2.Font.Hidden = False
End If
End Sub
I tried using
If CheckBox1.Value = True Then
CollapseRange1.Font.Hidden = True AND CollapseRange2.Font.Hidden = True
Else
CollapseRange1.Font.Hidden = False And CollapseRange2.Font.Hidden = False
But it didn't work. I was just wondering if I can shorten my IF statement into one rather then two.
Thanks!
Here is your same code... just condensed to remove unnecessary checks
Sub BBG_Transmital()
'Hides Sections Not Used in Expanded Form
Dim CollapseRange1 As Range
Dim CollapseRange2 As Range
'Set Which Range/Cell to Associate with Marked CheckBox
With ActiveDocument.Tables(3)
Set CollapseRange1 = .rows(10).Range
CollapseRange1.End = .rows(13).Range.End
Set CollapseRange2 = .rows(16).Range
CollapseRange2.End = .rows(21).Range.End
End With
'If Box is Checked then CollapseRanges
If CheckBox1.Value = True Then
CollapseRange1.Font.Hidden = True
CollapseRange2.Font.Hidden = True
Else 'If Box is Not Checked then UncollapseRange
CollapseRange1.Font.Hidden = False
CollapseRange2.Font.Hidden = False
End If
End Sub
Further condensing Wayne's answer:
This part:
'If Box is Checked then CollapseRanges
If CheckBox1.Value = True Then
CollapseRange1.Font.Hidden = True
CollapseRange2.Font.Hidden = True
Else 'If Box is Not Checked then UncollapseRange
CollapseRange1.Font.Hidden = False
CollapseRange2.Font.Hidden = False
End If
Can be written as:
CollapseRange1.Font.Hidden = CheckBox1.Value
CollapseRange2.Font.Hidden = CheckBox1.Value
Also note, If {boolean-expression} = True can always be rewritten as If {boolean-expression}, and If {boolean-expression} = False can always be rewritten as If Not {boolean-expression}.

Trying to hide rows in Excel based on certain cell values

I am looking around for a formula to hide certain rows based on certain cell inputs. In cell C5 I have a drop-down selection of "Corporates" and "Projects". In cell C8 I have a drop-down selection of "High", "Medium", and "Low". In cell H6 I have the formula =C5&C8. The macro I have is as follows:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(False, False) = "H6" Then
Select Case Target.Value
Case "CorporatesHigh": Rows("21:33").Hidden = True: Rows("12:20").Hidden = False
Case "CorporatesMedium": Rows("21:33").Hidden = True: Rows("12:20").Hidden = False
Case "CorporatesLow": Rows("25:33").Hidden = True: Rows("12:24").Hidden = False
Case "ProjectsHigh": Rows("25:28").Hidden = False: Rows("29:33").Hidden = True: Rows("12:24").Hidden = True
Case "ProjectsMedium": Rows("25:28").Hidden = False: Rows("29:33").Hidden = True: Rows("12:24").Hidden = True
Case "ProjectsLow": Rows("25:33").Hidden = False: Rows("12:24").Hidden = True
Case "": Rows("12:33").Hidden = False
Case "Corporates": Rows("12:33").Hidden = False
Case "Projects": Rows("12:33").Hidden = False
Case "High": Rows("12:33").Hidden = False
Case "Medium": Rows("12:33").Hidden = False
Case "Low": Rows("12:33").Hidden = False
End Select
End If
End Sub
The macro works when I click into H6 but I need it to work when cells C5 or C8 is changed.
The If-Not-Intersect-Is Nothing pattern is the preferred way to check if the changed cells(s) are inside a given range of cell(s).
To handle all three of your cells, you can use the following. You can easily add or remove cells to the Range if you want.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("H6,C5,C8")) Is Nothing Then
Select Case Range("H6").Value
Case "CorporatesHigh": Rows("21:33").Hidden = True: Rows("12:20").Hidden = False
Case "CorporatesMedium": Rows("21:33").Hidden = True: Rows("12:20").Hidden = False
Case "CorporatesLow": Rows("25:33").Hidden = True: Rows("12:24").Hidden = False
Case "ProjectsHigh": Rows("25:28").Hidden = False: Rows("29:33").Hidden = True: Rows("12:24").Hidden = True
Case "ProjectsMedium": Rows("25:28").Hidden = False: Rows("29:33").Hidden = True: Rows("12:24").Hidden = True
Case "ProjectsLow": Rows("25:33").Hidden = False: Rows("12:24").Hidden = True
Case "": Rows("12:33").Hidden = False
Case "Corporates": Rows("12:33").Hidden = False
Case "Projects": Rows("12:33").Hidden = False
Case "High": Rows("12:33").Hidden = False
Case "Medium": Rows("12:33").Hidden = False
Case "Low": Rows("12:33").Hidden = False
End Select
End If
End Sub