How can I use two conditions for my `IF` block? - vba

I have a problem to create double conditions with If, so this is what I have for hiding a line:
If Target.Address = "$D$35" Then
If (Target.Value = "No") Then
ActiveSheet.Range("37:40").Rows.Hidden = False
End If
If (Target.Value = "Yes") Then
ActiveSheet.Range("37:40").Rows.Hidden = True
End If
End If
Now, I want to add another condition for this formula, let's say that that cell $D$35 need to be "No" and Cell $D$36 need to be "done" in order for the Hide function to work.
How do I insert this to my existing formula ?

1. You can use And for multiple conditions (cf #jonrsharpe comment). Actually take a look at other logical operators like Or etc ... Logical and Bitwise Operators
2. Why don't you use If\ElseIf\Else ? It's quite obvious that if Target.Value = "No" is true you do not have to test if Target.Value = "Yes" ...
So just do something like that:
If cond1 And cond2 Then
' Some code
ElseIf cond3 And cond4 Then '<--editted
' Some code
Else
' Some code
End If
Example: Let's say you want to do a condition on the values of cell D35 ($D$35) and D36 you can just do:
If Range("D35")= "No" And Range("D36")= "No" Then
ActiveSheet.Range("37:40").Rows.Hidden = False
ElseIf Range("D35")= "Yes" And Range("D36")= "done" Then
ActiveSheet.Range("37:40").Rows.Hidden = True
End If
Instead of
If Target.Address = "$D$35" Then
If (Target.Value = "No") Then
ActiveSheet.Range("37:40").Rows.Hidden = False
End If
If (Target.Value = "Yes") Then
ActiveSheet.Range("37:40").Rows.Hidden = True
End If
End If
Note 1: this assumes you are working on the right sheet
Note 2: this isn't especially the best way to do ...

First, it's not a formula, it's a subroutine. Second, you don't have to have multiple IF blocks. Just one should suffice.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("D35:D36")) Is Nothing Then
ActiveSheet.Range("37:40").Rows.Hidden = (Range("D35").Value = "No" And Range("D36").Value = "Done")
End If
End Sub
A little explanation is in order:
If Not Intersect(Target, Range("D35:D36")) Is Nothing returns TRUE if the change is detected in either D35 or D36. If you want the condition to check in non-contiguous ranges, use Union on the ranges you want to check.
(Range("D35").Value = "No" And Range("D36").Value = "Done") evaluates to TRUE if both conditions are met, FALSE if else. We then use this as the boolean trigger for the Hidden property of the given range.
Hope this helps.

Related

using VBA to hide various rows based on changing cell value

I presently have the following coding:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim arCases As Variant
Dim res As Variant
arCases = Array("Term", "Indeterminate", "Transfer", "Student", "Term extension", "As required", "Assignment", "Indéterminé", "Mutation", "Selon le besoin", "Terme", "prolongation du terme", "affectation", "Étudiant(e)")
If Target.Address <> "$C$37" Then Exit Sub
res = Application.Match(Target, arCases, 0)
If IsError(res) Then
Rows("104:112").Hidden = False
Else
Rows("104:112").Hidden = True
End If
End Sub
The issue that I am having is that I need to add to this such as if value in Cell C37 is "X" then rows 42:49 are hidden and if value on Cell H4 is "Y" then rows 101:114 are hidden...etc.....
can you advise on how do so?
You need to change that condition to only execute the code if it matches the cell address, rather than not execute the code unless the address is matched. This will allow you to add further conditions matched on cell address.
I'd recommend changing a hard-coded cell address like "$C$37" to a named range and that named range should ideally be unique throughout the workbook.
arCases = Array("Term", "Indeterminate", "Transfer", "Student", "Term extension", "As required", "Assignment", "Indéterminé", "Mutation", "Selon le besoin", "Terme", "prolongation du terme", "affectation", "Étudiant(e)")
If Target.Address = "$C$37" Then
res = Application.Match(Target, arCases, 0)
If IsError(res) Then
Rows("104:112").Hidden = False
Else
Rows("104:112").Hidden = True
End If
ElseIf Target.Address = "$H$4" Then
' Do something else
End If
End Sub

Can I use IsEmpty to refer to a different sheet and hide a column?

Is it possible to use IsEmpty to refer to a cell on a different sheet from where the macro is being fired from? Also, is it possible to hide the queried column if the result of that query is True?
Here's what I've built so far:
My first version looked like this:
If IsEmpty(L1) Then
Columns("L").EntireColumn.Hidden = True
Else
Columns("L").EntireColumn.Hidden = False
End If
Straightforward enough. But, that only works if it's fired from the worksheet where I want the query/hide to occur. When I launch the macro from the different sheet, it hides the column in that sheet (of course, duh).
So, after several iterations and errors, I got to this:
If IsEmpty(Sheets("Results").Cells(10, 1).Value) Then
Worksheets("Results").Columns(10).EntireColumn.Hidden = True
Else
Worksheets("Results").Columns(10).EntireColumn.Hidden = False
End If
Which at least doesn't throw any errors from the VBA. It also does a grand total of squat. :$ I'm starting to wonder if it's even possible to use IsEmpty on a different sheet? Or the EntireColumn.Hidden command? Also, given that I need to run this check on 9 columns, maybe there's a better way than 9 If/Then statements?
To get away from a loop through 9 columns' row 1, use SpecialCells(xlCellTypeBlanks).
dim blnks as range
with workSheets("Results")
with .range(.cells(1, "B"), .cells(1, "K"))
.entirecolumn.hidden = false
set blnks = .specialcells(xlCellTypeBlanks)
if not blnks is nothing then blnks.entirecolumn.hidden = true
end with
end with
Essentially this unhides all 9 columns then hides the columns with blank cells in the first row. Note that a zero-length string (e.g. "") returned by a formula is not the same thing as a truly blank cell.
I think you're very close, just you have the cells inputs the wrong way around:
If IsEmpty(Sheets("Results").Cells(1, 10).Value) Then
Worksheets("Results").Columns(10).EntireColumn.Hidden = True
Else
Worksheets("Results").Columns(10).EntireColumn.Hidden = False
End If
Additionally as mentioned in the comments you can create a loop to check many columns:
Dim i As Integer
Dim maxi As Integer
i = 1
maxi = 20
While i < maxi
If IsEmpty(ThisWorkbook.Worksheets("Results").Cells(1, i)) Then
Worksheets("Results").Columns(i).EntireColumn.Hidden = True
Else
Worksheets("Results").Columns(i).EntireColumn.Hidden = False
End If
i = i + 1
Wend

Limit to ElseIf Conditions?

So I have some VBA code designed to go through a few things based on a value in a cell. The value in the cell is read and the code runs accordingly. This works without issue with.
If Target.Value = "something" Then
End If
ElseIf Target.Value = "something2" Then
End If
ElseIf Target.Value = "something3" Then
End If
ElseIf Target.Value = "something4" Then
End If
That works perfectly, however if I add an additional ElseIf condition I get the compiler error of "Else without If". Changing ElseIf to Else on the fifth condition doesn't fix the issue. My question is that is there a limit to the amount of ElseIf conditions I can run? I literally only need this fifth one to be entirely done with what I am trying to do. I am positive the code within the condition has no errors.
The End If goes at the end only:
If Target.Value = "something" Then
'Do something
ElseIf Target.Value = "something2" Then
'Do something
ElseIf Target.Value = "something3" Then
'Do something
ElseIf Target.Value = "something4" Then
'Do something
End If
Definitely you should "upgrade" your multiple ElseIf and go with Select Case.
This will let you implement more scenarios in the future easier.
Select Case Target.Value
Case "something"
' code 1 here
Case "something2"
' code 2 here
Case "something3"
' code 3 here
Case "something4"
' code 4 here
Case "something5", "something6" ' <-- replaces using another If with And
' code 5 here
' Case ....
End Select

VBA Excel Double If

I have various dropdown menus in the document and need to create a double conditional statement.
So I am trying to do the following:
If Cell B14 = Option 1 Then unhide Cells B16:B17
If Cells B17 = Yes Then hide Cells B19:B53
If Cells B17 = No Then show Cells B19:B34
So if someone picks Option 1 from the dropdown menu then there is another drop down menu that appear and if they select Yes from the second on it hide the required cells and if they pick No it unhides the required cells.
Options 2 & 3 in the first dropdown menu do not need to show the second drop down box.
I have it all working apart from the double if.
Current code is:
If Target.Address = "$B$14" Then
If Range("B14") = "Option 1: Travel Home" Then
ActiveSheet.Rows("16:35").EntireRow.Hidden = False
ActiveSheet.Rows("36:55").EntireRow.Hidden = True
ElseIf Range("B14") = "Option 2: Travel to next city" Then
ActiveSheet.Rows("15").EntireRow.Hidden = False
ActiveSheet.Rows("16:17").EntireRow.Hidden = True
ActiveSheet.Rows("19:35").EntireRow.Hidden = True
ActiveSheet.Rows("36").EntireRow.Hidden = False
ActiveSheet.Rows("37:55").EntireRow.Hidden = True
ElseIf Range("B14") = "Option 3: Make own arrangements" Then
ActiveSheet.Rows("15:36").EntireRow.Hidden = True
ActiveSheet.Rows("39:55").EntireRow.Hidden = False
End If
End If
Option 2 and 3 are working OK just option 1 isn't working to unhide/hide whats necessary and also then need to do the second dropdown option which the alters what is shown.
I tested the below code and it appears to be behaving as you desire. I did make some seemingly significant changes to the structure, but I did so in hopes of making it both easier to read and maintain going forward. I think my edits are self-explanatory.
I also took the liberty to assume this is a Worksheet_Change event even though you did not explicity state as such.
Private Sub Worksheet_Change(ByVal Target As Range)
Select Case Target.Address
Case Is = "$B$14"
Select Case Right(Left(Target.Value, 8), 1)
Case Is = 1 'Option 1
Me.Rows("16:17").EntireRow.Hidden = False
Case Is = 2 'Option 2
Me.Rows("15").EntireRow.Hidden = False
Me.Rows("16:17").EntireRow.Hidden = True
Me.Rows("19:35").EntireRow.Hidden = True
Me.Rows("36").EntireRow.Hidden = False
Me.Rows("37:55").EntireRow.Hidden = True
Case Is = 3 'Option 3
Me.Rows("15:36").EntireRow.Hidden = True
Me.Rows("39:55").EntireRow.Hidden = False
Case Else
Me.Rows("15:55").EntireRow.Hidden = True
End Select
Case Is = "$B$17"
Me.Range("B19:B35").EntireRow.Hidden = Not (Target.Value = "No")
End Select
End Sub
Here's the code to make sure all rows are hidden when the workbook is opened.
Private Sub Workbook_Open()
With Me.Worksheets("SheetName") ' change as needed
.Rows("1:3").EntireRow.Hidden = True
.Rows("15:55").EntireRow.Hidden = True
End With
End Sub

How to check if a date cell in Excel is empty?

If feels like this should be really easy but I dont get it to work without retrieving the value of the cell again.
To start with, I have 2 date cells:
Dim agreedDate As Date
Dim completedDate As Date
THIS WORKS .. (but looks messy)
agreedDate = Worksheets("Data").Cells(Counter, 7).Value
completedDate = Worksheets("Data").Cells(Counter, 9).Value
If (IsEmpty(Worksheets("Data").Cells(Counter, 7).Value) = True) Or (IsEmpty(Worksheets("Data").Cells(Counter, 9).Value) = True) Then
[.. do stuff]
End If
THIS DOES NOT WORK - WHY NOT?!
agreedDate = Worksheets("Data").Cells(Counter, 7).Value
completedDate = Worksheets("Data").Cells(Counter, 9).Value
If (IsEmpty(agreedDate) = True) Or IsEmpty(completedDate) = True) Then
[.. do stuff]
End If
Is there a way to write the if statement in a clean and easy way?
Since only variables of type Variant can be Empty, you need a different test for Date types.
Check for zero:
If agreedDate = 0 Or completedDate = 0 Then
But a safer path would be to change the variables to type Variant and then do this test:
If IsDate(agreedDate) = False Or IsDate(completedDate) = False Then
The IsEmpty function determines indicated whether a variable has been initialized. If a cell is truly blank then it is considered uninitialized from the IsEmpty standpoint. However, declaring a variable in VBA gives it a default value. In this case the date type variables are essentially 0 or 30-Dec-1899 00:00:00 as demonstrated by the following short snippet.
Sub date_var_test()
Dim dt As Date
Debug.Print Format(dt, "dd-mmm-yyyy hh:mm:ss")
End Sub
If you want to 'tidy up' your code, you might also wish to allow the true boolean return of the IsEmpty function to resolve the boolean condition rather than comparing it to True.
If IsEmpty(Worksheets("Data").Cells(Counter, 7)) Or IsEmpty(Worksheets("Data").Cells(Counter, 9)) Then
[.. do stuff]
End If
Given that False is (for all intents and purposes) zero then this will work for your date type variables.
If Not (agreedDate or completedDate) Then
[.. do stuff]
End If
As Excel Hero pointed out, a date variable cannot be empty. In fact, a date variable is a number, so you should be able to do something like this. Also, notice that the code below uses "Value2".
Sub test()
Dim d As Date
d = Range("A1").Value2
If d = 0 Then
MsgBox "ok"
Else
MsgBox "not ok"
End If
End Sub