VBA Nested IF statement - vba

I want to show a message box when a specific cell has a particular value in it. I have done this with the following code;
If Range("P8") = "Y" Then
MsgBox "Message here"
End If
This is within the Worksheet_Change sub so shows the message box everytime another cell value changes. I have tried to get around this by adding a boolean variable, set to true when the messagebox has been shown the first time;
If Range("P8") = "Y" Then
If messageshown = False Then
messageshown = True
MsgBox "Message here"
Else
End If
Else
End If
However the message box still shows every time I change a cell in the worksheet. I have a feeling it';s to do with the way I have written the nested if statement but have tried various different ways and orders of where I place else and end if but to no avail.

Use the Target argument instead - this refers to the actual cell being changed, which is what you are interested in. Test the address of the Target to see if it's the cell you need and then act accordingly. This will stop the message showing when another cell is changed.
Private Sub Worksheet_Change(ByVal Target As Range)
With Target
If .Address = "$P$8" And .Value = "Y" Then MsgBox "Message here"
End With
End Sub

Try this code, it first checks which cell is changed, if it is anything but P8, it will not pop the messagebox.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$P$8" Then
If Range("P8") = "Y" Then
MsgBox "This works"
End If
End If
End Sub
As pointed out by Macro Man, there is a more optimal, more efficient option.

Related

VBA code to popup msgbox and return to the previous value

I need a VBA code that pops up error/warning message when the cell value is exceeds more than 100.
For example, if value entered in B2, F2 cells updates automatically. Higher the B2 value will lead F2 value cross 100 and sheet becomes error.
So, I need to give message here to uses, when F2 goes beyond 100 and B2 should return to last value.
My current code is very basic. Please help me to get thru this.
If Sheets("200L_50°C").Range("L2").Value < 100 Then
MsgBox "No further pressure drop at higher operating temperatures", vbOKOnly, "High temperature"
Update, this is the code I put in my worksheet. I get error on the first line:
Public G1Value As Integer
Private Sub Worksheet_Change(ByVal Target As Range)
If Target = Range("G1") Then
If Range("L2") > 100 Then
MsgBox "Error. Invalid value for G1"
Range("G1") = G1Value
Else: End If
Else: End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target = Range("G1") Then
G1Value = Range("G1")
Else: End If
End Sub
Hold up, I think I have a better understanding of your question now. When a user puts something in B2, if that change causes cell F2 to go higher than 100, then you want to output an error message and return cell B2 to the value that it was. Here's how you can do that easily:
Go to the view code of the worksheet you are on by right-clicking the worksheet tab name:
Then add in this code (if a duplicate method exists, then comment out the old code or replace it if it's unimportant).
Public B2Value As Integer
Private Sub Worksheet_Change(ByVal Target As Range)
If Target = Range("B2") Then
If Range("L2") > 100 Then
MsgBox "Error. Invalid value for B2"
Range("B2") = B2Value
Else: End If
Else: End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target = Range("B2") Then
B2Value = Range("B2")
Else: End If
End Sub
I'm not sure if I get your question, but it seems you could use data validation in cell B2 to prevent users from inputting values higher than 100. Click on cell B2, go to the "Data" tab, and click on "Data Validation". Modify the conditions like the image below, and on the "Error Alert" tab, put in the message you want them to see when they try to enter a value higher than 100.

MsgBox when specific cells contain specific text

I would like to have a pop up message appear every time a cell contains specific text. Everytime the word "Red Level" is in any of this cells (I22,I23,I34,I35,I36), I would like a MsgBox to appear.
I am using a data validation list in all those cells mentioned above, to make sure the word "Red Level" is always the same.
I wrote some code and it worked but only when I had 1 cell in my range. When I tried to add the other cell numbers to my code, it will still only work for the first cell and not for the rest.
Below is the code that worked for one cell:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Worksheets("A12").Range("I22").Value = "Red Level" Then
MsgBox ("Please call maintenance immediately to refill reservoir")
End If
End Sub
I thought I could just add the rest of the cells to the range on my code, but that did not work.
This is what I did but did not work (The MsgBox will only appear when the word "Red Level is on I22 and not in the other cells):
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Sheets("A12").Range("I22,I23,I34,I35,I36").Value = "Red Level" Then
MsgBox ("Please call maintenance immediately to refill reservoir")
End If
End Sub
You could use the worksheet's MATCH but it will not work on discontiguous cells so two checks must be made.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
if not iserror(application.match("red level", Range("I22:I23"), 0)) or _
not iserror(application.match("red level", Range("I34:I36"), 0)) then
'Red Level is is at least one of the discontiguous cells
MsgBox ("Please call maintenance immediately to refill reservoir")
end if
End Sub
It's unclear what actually drives 'Red Level' to appear in range("I22:I23, I34:I36"). This may be better as a Worksheet_Change. As is, the user cannot navigate through the worksheet if one or more of the cells remains 'Red Level'.
On a related note: is this within the A12 worksheet's code sheet? If so (as a private sub within the worksheet's code sheet), defining the parent worksheet with Worksheets("A12") is unnecessary. My code has removed the parent worksheet reference.
For this, you can do it two ways (at least). If you want to stay with If, you need lots of Or:
If Sheets("A12").Range("I22").Value = "Red Level" or Sheets("A12").Range("I23").Value = "Red Level" or ... Then
But as you can see, it'll be a really long line, which isn't the most straightforward to read. Here's an alternative:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
Dim addr() As Variant
Dim hasPrompted As Boolean
hasPrompted = False
addr = Array("$I$22", "$I$23", "$I$34", "$I$35", "$I$36")
Dim i As Long
For i = LBound(addr) To UBound(addr)
If Range(addr(i)).Value = "Red Level" And Not hasPrompted Then
MsgBox ("Please call maintenance immediately to refill reservoir")
hasPrompted = True
End If
Next i
Application.EnableEvents = True
End Sub
Note the second one will only fire one time, even if all cells have "Red Level", or just one cell has it. If you want to alert the user which cells have it, you can add that in, just let me know.
why not using find on the wanted cells range?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Worksheets("A12").Range("I22,I23,I34:I36").Find(what:="Red Level", LookIn:=xlValues, lookat:=xlWhole) Is Nothing Then MsgBox "Please call maintenance immediately to refill reservoir"
End Sub
and, as #Jeeped already said, if the worksheet you're monitoring event of is named after "A12" then you can omit the Worksheets("A12"). part
The DATA tab has a wizard for data validation,
The first tab allows you to define a condition.
The third tab of this wizard is for a message popup.
You don't need to write code for this, S it is already built in to excel.
http://www.excel-easy.com/basics/data-validation.html

Data Validation and Worksheet Change Event

I use a VBA macro to query a database and build a list of available projects when a workbook is opened using the workbook activate event. I have project numbers and project names that are combined into two separate data validation lists and applied to two cells. The worksheet change event tests for changes in these cells, splits their data validation lists into arrays, and chooses the corresponding project information from the other array. For instance, if I pick a project number, the worksheet change event finds the project number's position in the project number array, and then picks the project's name from the name array based on position.
This works perfectly whenever a value is selected from the drop down, but I run into problems when values outside the list are entered. For instance, if I enter a blank cell I may get the data validation error or I may get a type mismatch when I use match to find the entered value in the array. I have an error handler to handle the type mismatch, but I would like the data validation error to trigger every time instead. Another problem is that Events will sometimes be disabled. This is much more serious because users will not have a way to turn these back on.
On top of this, I cannot figure out where or how this is happening. I can't replicate how the Events are disabled using breaks because duplicating the steps that lead to the events being disabled with breaks in place only leads to my error handler. However, when breaks aren't applied, the error handler will sometimes fail to trigger and the events will be disabled. Since I'm disabling events just before I parse arrays, I'm thinking the worksheet change fails at the Loc=Application.Match(Target.Text, NumArr, 0) - 1 line, but I can't figure out why no error would be triggered. At the very least, I should get a message with the error number and description, and events should be re-enabled.
Can anyone advise on the interaction between worksheet change and data validation? What is the call order here? Any other advice? Anything I'm missing?
ETA: I've Googled this, but I haven't found anything that helps. Everything that comes up is about working the data validation into worksheet change, nothing about the interaction or call order.
ETA #2: After trying the experiment in the answer below (Thanks Gary's Student), this gets a little more odd. If I choose "Retry" and choose the old, default value, I get the old value three times. If I hit delete, I get a space in the message box, but only one message box. Then the cell is left blank. I can put DV into a loop by clicking "Retry" and accepting the space. The DV error will come up until I click cancel. Then I will get a series of empty text message boxes, one for each time I retried the empty cell. If I start off with a listed value, clear the cell with backspace, click "Retry," and try to select another value, the worksheet change event fails at Intersect 3 times. I think the answer below sheds more light on what is going on, but it does bring up more questions also.
Here is the code I have:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim NumArr() As String
Dim ProjArr() As String
Dim Loc As Integer
On Error GoTo ErrHandler:
If Target.Address = "$E$4" Then
'Disable events to prevent worksheet change trigger on cell upates
Application.EnableEvents = False
'Parse validation lists to arrays
NumArr = Split(Target.Validation.Formula1, ",")
ProjArr = Split(Target.Offset(1, 0).Validation.Formula1, ",")
'Change error handler
On Error GoTo SpaceHandler:
'Determine project number location in array
Loc = Application.Match(Target.Text, NumArr, 0) - 1
'Change error handler
On Error GoTo ErrHandler:
'Change cell value to corresponding project name based on array location
Target.Offset(1, 0) = ProjArr(Loc)
'Unlock cells to prepare for editing, reset any previously imported codes
Range("C8:G32").Locked = False
'Run revenue code import
RevenueCodeCollector.ImportRevenueCodes
'Re-enable events
Application.EnableEvents = True
End If
If Target.Address = "$E$5" Then
Application.EnableEvents = False
NumArr = Split(Target.Validation.Formula1, ",")
ProjArr = Split(Target.Offset(-1, 0).Validation.Formula1, ",")
Loc = Application.Match(Target.Text, NumArr, 0) - 1
Target.Offset(-1, 0) = ProjArr(Loc)
Range("C8:G32").Locked = False
RevenueCodeCollector.ImportRevenueCodes
Application.EnableEvents = True
End If
Exit Sub
ErrHandler:
MsgBox Err.Number & " " & Err.Description
Application.EnableEvents = True
Exit Sub
SpaceHandler:
MsgBox "Pick a project from the dropdown.", vbOKOnly, "Error"
Application.EnableEvents = True
End Sub
You have a very open-ended question...........not having the time to do a full whitepaper, here is a simple experiment. I use the Event code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim A1 As Range, rINT As Range
Set A1 = Range("A1")
Set rINT = Intersect(A1, Target)
If rINT Is Nothing Then Exit Sub
MsgBox A1.Value
End Sub
and in A1, I setup DV as follows:
If I use the drop-down, I get the value entered and I also get the MsgBox. However, if I click on the cell and type some junk what happens is:
the DV alert occurs and I touch the CANCEL Button
I get 2 MsgBox occurrences, each with the original contents rather than the attempted junk !!
I have absolutely no idea why the event is raised since the cell is not actually changed, let alone why the Event is raised twice !! It is almost as if
the event is raised on junk entry, but the DV alarm has precedence, the DV reverse the entry and another event is raised, and finally both events get processed.
Hopefully a person smarter than me will chime in.
With ref to the query, Workaround for the DV and change event is managed.
Public strRange As String
Public bCheck As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
If bCheck Then Exit Sub
MsgBox "Correct Entry!"
strRange = Target.Address
bCheck = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address <> strRange Then bCheck = False
End Sub
http://forum.chandoo.org/threads/multiple-worksheet-change-event-with-data-validation.32750

excel vba - msgbox abort/retry/ignore

I am validating input in an Excel worksheet. When the user enters invalid data a MsgBox is shown, giving the option to Abort/Retry/Ignore.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If IsNumeric(Range("i17")) Then
If [I17] < 0 Then
result = MsgBox("Critical Error Encountered", vbAbortRetryIgnore + vbCritical, "Error Encountered")
If result = 3 Then
ActiveCell.Value = Empty
End If
End If
End If
End sub
Since I have written this code in SelectionChange when I click enter then only it show the message box and since I'm writing Active.Cell = Empty it is deleting the next cell, but I mean it to clear the cell which contains invalid data.
If you use the SelectionChange event, the Target range is the cell just selected and not the cell which has just been changed. If you use the Change event of the worksheet, then Target refers to the cell that has been changed. So, assuming that cell I17 is some kind of subtotal/validation cell and not the cell into which the user enters data, try this:
Private Sub Worksheet_Change(ByVal Target As Range)
If IsNumeric(Range("i17")) Then
If [I17] < 0 Then
result = MsgBox("Critical Error Encountered", vbAbortRetryIgnore + vbCritical, "Error Encountered")
If result = 3 Then
Target.Value = Empty
Target.Select
End If
End If
End If
End Sub
This code will clear the cell just changed and change the selection back to that cell if the user selects the Abort button in the message.

Excel - Run-time error '1004': Unable to set the hidden property of the range class

I am new to scripting and I am trying to improve a existing Macro. I recorded a macro to remove duplicate and added it in a Main function which calls some other functions, but I am getting this error when I add the macro I recorded:
Run-time error '1004': Unable to set the hidden property of the range class
The code looks like
Private Sub Worksheet_Change(ByVal Target As Range)
Dim changed As Range
Set changed = Intersect(Target, Range("J15"))
If Not changed Is Nothing Then
Range("A48:A136").EntireRow.Hidden = True
Select Case Target.Value
Case "Agriculture"
Range("A48:A96").EntireRow.Hidden = False
Case "Commercial"
Range("A97:A136").EntireRow.Hidden = False
Case "MDP"
Range("A48:A61").EntireRow.Hidden = False
End Select
Range("J15").Select
End If
End Sub
Some possible answers:
You have a comment in one of the selected cells
You have some drawn objects which don't resize with text
Your worksheet is protected
When you set a breakpoint on the first line of the event handler, and then press F8 to step through the macro, I'm assuming it crashes on the line:
Range("A48:A136").EntireRow.Hidden = True
When people say "You have a comment in one of the selected cells", keep in mind that THE COMMENT CAN BE IN A DIFFERENT COLUMN.
If a comment box is over the column you're trying to hide (like if you're hiding every column to the right and you have comments in a completely different column), this is the error you'll get.
If you try to manually hide the column, you'll get a different confusing error which is something along the lines of "hiding this column will push an object off of the sheet."
The comment box a few columns over is the object.
^ This would have saved me about 40 minutes of debugging.
try this :)
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveWorkbook.Unprotect "password_here"
Dim changed As Range
Set changed = Intersect(Target, Range("J15"))
If Not changed Is Nothing Then
Range("A48:A136").EntireRow.Hidden = True
Select Case Target.Value
Case "Agriculture"
Range("A48:A96").EntireRow.Hidden = False
Case "Commercial"
Range("A97:A136").EntireRow.Hidden = False
Case "MDP"
Range("A48:A61").EntireRow.Hidden = False
End Select
Range("J15").Select
End If
ActiveWorkbook.Protect "password_here"
End Sub
This should work for you :)