Go to a referenced cell when clicking "ok" in the message box - excel

So my code starts on a different sheet with a button click. The code below stops the user from continuing with an error message if the user does not put in a value in cell "B38" on the "Pricing checklist" sheet. Is there a way to bring the user to the cell so they can input a value?
If ThisWorkbook.Sheets("Pricing checklist").Range("B38").Value = "" Then
MsgBox "Please enter the Sales Rep. " _
& vbCrLf & vbCrLf & "Press OK to exit and try again.", vbCritical
Exit Sub
End If

Select a Cell Using Application.Goto
Application.Goto method
Sub CheckPrice()
Dim PriceCell As Range
Set PriceCell = ThisWorkbook.Worksheets("Pricing checklist").Range("B38")
If Len(CStr(PriceCell.Value)) = 0 Then
MsgBox "Please enter the Sales Rep. " _
& vbCrLf & vbCrLf & "Press OK to exit and try again.", vbCritical
Application.Goto PriceCell, True ' to not scroll, remove 'True'
Exit Sub
End If
End Sub

Related

Only Certain UserForm Fields Mandatory While Others are "And Or" Excel VBA

I hope you are all keeping safe!
Within my UserForm, there are multiple ComboBoxs and TextBoxs.
When the Command Button is clicked Ideally what I would like to achieve is that: ComboBox2 & Textbox6 are a mandatory requirement, while having Either textbox2 and or (one or the other) Textbox3 also a mandatory requirement, before the form copies into the workbook.
The following code makes the ComboBox2 field mandatory but I just don’t know how to make either textbox2 and OR Textbox3 a requirement. I've just started to learn a little about Excel VBA, so any help is greatly appreciated! :)
If ComboBox2.Value = "" And ComboBox3.Value = "" And TextBox6.Value = "" Or TextBox16.Value = "" Or TextBox17.Value = "" Then
MsgBox "You must select a: Category/Type, a Description, and a Start Date" & vbCrLf & "And enter either an: Expenses or Income Amount." & vbCrLf & "Please check your entries and try again.", vbCritical
Exit Sub
End If
When validating inputs on UserForms there are a few ways I do it.
Here is an example from an input form that requires all but 1 field to be completed:
The userform:
And the validation in the code behind:
Dim Code As String
Dim Description As String
Dim Qty As String
Dim Min As String
Dim ProductType As String
Dim Supplier As String
Dim StockMinimums As String
With Me
Code = .txtCodeLG.Text
Description = .txtDescriptionLG.Text
Qty = .txtQtyLG.Value
Min = .txtMinLG.Value
If .chkEMG80.Value = True Then
ProductType = .chkEMG80.Caption
ElseIf .chkUCP100.Value = True Then
ProductType = .chkUCP100.Caption
ElseIf .chkEMGLicences.Value = True Then
ProductType = .chkEMGLicences.Caption
ElseIf .chkUCPLicences.Value = True Then
ProductType = .chkUCPLicences.Caption
End If
Dim opt As Control
For Each opt In Me.Controls
If TypeName(opt) = "OptionButton" Then
If opt.Value = True Then
Supplier = opt.Caption
Else
'Do nothing
End If
End If
Next opt
End With
If Me.chkMinimumsSheet.Value = True Then
StockMinimums = "Yes"
ElseIf Me.chkMinimumsSheet.Value = False Then
StockMinimums = "No"
End If
'--------------------------------------Error checking-------------------------------------
Dim ErrorString As String
If Code = "" Then
ErrorString = ErrorString + "Please enter a value into the 'Code' box." & vbNewLine
End If
If Description = "" Then
ErrorString = ErrorString + "Please enter a value into the 'Description' box." & vbNewLine
End If
'If Qty = "" Then
' ErrorString = ErrorString + "Please enter a value into the 'Quantity' box." & vbNewLine
'End If
If Min = "" Then
ErrorString = ErrorString + "Please enter a value into the 'Minimum' box." & vbNewLine
End If
If ProductType = "" Then
ErrorString = ErrorString + "Please choose a 'Product Type'." & vbNewLine
End If
If Supplier = "" Then
ErrorString = ErrorString + "Please select a 'Supplier'." & vbNewLine
End If
If Not ErrorString = "" Then
MsgBox ErrorString + vbNewLine & "Danger to manifold.", vbCritical, "Values Missing"
Exit Sub
End If
And if the user clicks submit without filling out the required fields it displays a descriptive message advising what is missing (heres the msgbox when nothing is filled in):
you can use an "or" or "and" statement like you would in non vba excel, its just a little different formatting. But you are exactly on the right path!
Basically if both are blank, then a message would pop up requiring a value in one of the boxes. If one or both are filled in, then good. I.E.
if textbox2.value = "" and textbox3.value = "" then
msgbox "You must enter a value in textbox 2 and/or 3", vbCritical
exit sub
end if
for an "or" statement, just replace "and" with "or"
Edit to add:
for going thru multiple iterations thru your userform for data validation and checking if boxes are filled in, etc. I would start top to bottom, and do a check for each one.
if textbox1.value = "" then
msgbox "Please fill in " & textbox1.name (or .tag or some other way to identify the item), vbcritical, "Error"
exit sub
elseif combobox2.value = "" then
msgbox "Please fill in " & combobox2.name, vbcritical, "Error"
exit sub
elseif textbox6.value = "" then
msgbox "Please fill in " & textbox6.name, vbcritical, "Error"
exit sub
elseif textbox2.value = "" or textbox3.value="" then
msgbox "Please fill in either textbox 2 or 3", vbcritical, "Error"
exit sub
end if
If they are simple, and have a way to loop as described by another gentleman, you can use a generic formula such as
for i=1 to 5
if me.controls("Textbox" & i).value = "" then
msgbox "Please fill in " & me.controls("textbox" & i).name, vbcritical, "Error"
exit sub
exit for
end if
next i
I would perhaps use a combination if you have a lot of boxes. Say there are 10 mandatory boxes, I can use the loop thru all 10 mandatory, and then just use individual if then statements using the "or" statement to check those that are one or the other

Display where an error is in a message box

I use this code to prevent entries of text that are not valid email addresses. The user has a UserForm with 22 textboxes for a user to input the addresses into a range of cells. How can I get the message box to show where the error was? Or, should I put this "check" in a different place, like in the "CommandButton1_Click()" sub?
This code is in the "Private Sub Worksheet_Change(ByVal Target As Range)" sheet.
If Target.Cells.CountLarge = 1 Then
If Target.Column = 13 And Target.Value <> "" And Evaluate("COUNTIF(" & Target.Address & ",""*#*.*"")") <> 1 Then
Target.ClearContents
Target.Activate
MsgBox "Please enter a valid email address."
End If
End If
If Target.Cells.CountLarge = 1 Then
If Target.Column = 13 And Target.Value <> "" And Evaluate("COUNTIF(" & Target.Address & ",""*#*.*"")") <> 1 Then
MsgBox "Email address ''" & Target.Value & "'' in " & Target.Address & " is not a valid email address." & _
vbNewLine & "Please enter a valid email address."
Target.ClearContents
Target.Activate
End If
End If

VBA Excel Change Value in Field

I have an excel table with a column named "Completed?" that users select Yes or No from the drop down. If they Select Yes a Message Box using vbOKCancel pops up. If they confirm Yes that part is working so far, but if anything else happens (they hit Cancel, or X out, etc) I want this field to be changed to "No" - this is what I'm struggling with.
It seems like it should be simple - any ideas?
If Target.Column = 3 And Target.Value = "Yes" Then
Dim answer As Integer
answer = MsgBox("Are you sure you want to mark this as Completed? This will move the record to the Completed Tab and cannot be undone.", vbOKCancel + vbCritical, "CRITICAL WARNING")
If answer = vbOK Then MsgBox ("OK")
'need help with this next row
Else: Target.Value = "No"
End If
End Sub
Fundimentaily, you issue is missuse of the If Then Else End IF structure. (you are mixing Multi Line and Single Line syntax)
See here for more details
There are some other issues too, see inline comments
Private Sub Worksheet_Change(ByVal Target As Range)
Dim answer As VbMsgBoxResult ' use correct data type
Dim rng As Range, cl As Range
On Error GoTo EH ' ensure events get turned back on
Application.EnableEvents = False ' prevent event cascade
Set rng = Application.Intersect(Target, Me.Columns(3)) ' get all cells in column 3 that changed
For Each cl In rng ' process each changed cell
If LCase(cl.Value) = "yes" Or LCase(cl.Value) = "y" Then ' case insensitive
answer = MsgBox("Are you sure you want to mark row " & cl.Row & " as Completed?" & vbNewLine & vbNewLine & "This will move the record to the Completed Tab and cannot be undone.", vbOKCancel + vbCritical, "CRITICAL WARNING")
If answer = vbOK Then
cl.Value = "Yes" ' Standardise case
' MsgBox "OK" ' this is a bit annoying
Else
cl.Value = "No"
End If
End If
Next
EH:
Application.EnableEvents = True
End Sub
try this:
If Target.Column = 3 And Target.Value = "Yes" Then
Dim answer As Integer
answer = MsgBox("Are you sure you want to mark this as Completed? " & _
"This will move the record to the Completed Tab and cannot be undone.", vbOKCancel + vbCritical, "CRITICAL WARNING")
If answer = vbOK Then
MsgBox ("OK")
Else
Target.Value = "No"
End If
End If

Multi-optional macros using removeable checkboxes

Thanks to these instructions
How do I assign a Macro to a checkbox dynamically using VBA
https://social.msdn.microsoft.com/Forums/office/en-US/877f15da-bbe4-4026-8ef2-8df77e1022f7/how-do-i-assign-a-macro-to-a-checkbox-dynamically-using-vba?forum=exceldev
I came up with an idea to:
Put checkboxes where I want on the sheet, e.g. in columns to the right from table with data for processing
Connect their (un)checking with logical variables which are used whether to start or not to start some procedures.
Wait for user to make his choices and check certain checkbox (e.g. the last in the list) to start selected procedures
Remove all (!) checkboxes and start the procedures selected shortly before.
This way the macros containing optional procedures are portable, as they don't DEPEND on the opened files but only WORK on them.
The files themselves remain unchanged by these free from control buttons coded in the macro (i.e. the sheet with checkboxes returns to it's previous state).
The following macro makes its own checkboxes (in column H), waits for user to choose options, memorizes choices, deletes all checkboxes, runs other procedures... and ends up without leaving a trace of itself in a workbook.
Dim FirstOptionLogical, SecondOptionLogical, ThirdOptionLogical As Boolean
' Making new checkboxes
Sub CheckBOxAdding()
Dim i As Long, id As Long
Dim cel As Range
Dim cbx As CheckBox
On Error GoTo CheckBoxAddingERROR
'FirstOptionLogical = False
'SecondOptionLogical = False
'ThirdOptionLogical = False
' Deleting all checkboxes, if any found
' Preventing error stops if there is no checkbox
On Error Resume Next
' Repeating with all checkboxes on active sheet
For Each chkbx In ActiveSheet.CheckBoxes
' Removing a checkbox
chkbx.Delete
' Next checkbox
Next
Range("G3").Select
ActiveSheet.Range(Columns("G:G"), Selection.End(xlToRight)).Select
Selection.Delete Shift:=xlToLeft
On Error GoTo 0
Set cel = ActiveSheet.Cells(3, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' height will autosize larger to the font
End With
cbx.Name = "Option_1"
cbx.Caption = "First Attribute changes, name it"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
''''''''''
Set cel = ActiveSheet.Cells(5, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' height will autosize larger to the font
End With
cbx.Name = "Option_2"
cbx.Caption = "Second Attribute changes, name it"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
Set cel = ActiveSheet.Cells(7, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' height will autosize larger to the font
End With
cbx.Name = "Option_3"
cbx.Caption = "Third Attribute changes, name it"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
Set cel = ActiveSheet.Cells(9, 8)
With cel
Set cbx = ActiveSheet.CheckBoxes.Add(.Left, .Top, 90, 3)
' .Font.Size = 36
' height will autosize larger to the font
End With
cbx.Name = "Option_4"
cbx.Caption = "START THE MACRO"
cbx.Display3DShading = True
' with a linked can trap sheet change event or link to other formulas
cbx.LinkedCell = cel.Offset(0, -1).Address
cbx.OnAction = "'" & ThisWorkbook.Name & "'!CheckBoxHandling"
Exit Sub
CheckBoxAddingERROR:
MsgBox "Something went wrong... ;-) in the sub CheckBOxAdding", vbCritical + vbOKOnly
End
End Sub
Sub CheckBoxHandling()
Dim sCaller, UsersChoice As String
Dim id As Long
Dim cbx As CheckBox
Dim shp As Shape
UsersChoice = ""
On Error GoTo CheckBoxHandlingERROR
sCaller = Application.Caller
Set shp = ActiveSheet.Shapes(sCaller)
Set cbx = ActiveSheet.CheckBoxes(sCaller)
id = Val(Mid$(sCaller, Len("Option_") + 1, 5))
' maybe something based on Select Case?
Select Case id
Case 1:
'MsgBox "You clicked the checkbox with option" & vbCrLf & "'Larger description of First Attribute changes, name it'"
FirstOptionLogical = Not FirstOptionLogical
'FirstOptionLogical = IIf(cbx.Value = xlOn, True, False)
'MsgBox "FirstOptionLogical = " & FirstOptionLogical & vbCrLf & "SecondOptionLogical = " & SecondOptionLogical & vbCrLf & "ThirdOptionLogical= " & ThirdOptionLogical
Case 2:
'MsgBox "You clicked the checkbox with option" & vbCrLf & "'Larger description of Second Attribute changes, name it'"
SecondOptionLogical = Not SecondOptionLogical
'SecondOptionLogical = IIf(cbx.Value = xlOn, True, False)
'MsgBox "FirstOptionLogical = " & FirstOptionLogical & vbCrLf & "SecondOptionLogical = " & SecondOptionLogical & vbCrLf & "ThirdOptionLogical= " & ThirdOptionLogical
Case 3:
'MsgBox "You clicked the checkbox with option" & vbCrLf & "'Larger description of Third Attribute changes, name it'"
ThirdOptionLogical = Not ThirdOptionLogical
'ThirdOptionLogical = IIf(cbx.Value = xlOn, True, False)
'MsgBox "FirstOptionLogical = " & FirstOptionLogical & vbCrLf & "SecondOptionLogical = " & SecondOptionLogical & vbCrLf & "ThirdOptionLogical= " & ThirdOptionLogical
Case 4:
If FirstOptionLogical Then
UsersChoice = UsersChoice & "- Larger description of First Attribute changes, name it " & vbCrLf
End If
If SecondOptionLogical Then
UsersChoice = UsersChoice & "- Larger description of Second Attribute changes, name it " & vbCrLf
End If
If ThirdOptionLogical Then
UsersChoice = UsersChoice & "- Larger description of Third Attribute changes, name it " & vbCrLf
End If
Ans0 = MsgBox("The following options were chosen:" & vbCrLf & UsersChoice & vbCrLf & vbCrLf & _
"You chose a checkbox with an option" & vbCrLf & "'START THE MACRO'" & vbCrLf & vbCrLf & " S H O U L D W E S T A R T T H E M A C R O ? ", vbYesNo + vbDefaultButton2 + vbQuestion)
If Ans0 = vbYes Then
'MACRO WITH PARAMETERS WE CHOSE BY CLICKING GETS STARTED...
' Delete all remaining checkboxes, if any (removing traces of the macro)
' In case of error, resume
On Error Resume Next
For Each chkbx In ActiveSheet.CheckBoxes
chkbx.Delete
Next
' Deleting all columns from G to the right
Range("G3").Select
ActiveWorkbook.Sheets(1).Range(Columns("G:G"), Selection.End(xlToRight)).Select
Selection.Delete Shift:=xlToLeft
' Resetting on Error event to default
On Error GoTo 0
' If chosen, start sub 'Larger description of First Attribute changes, name it'
If FirstOptionLogical Then Call RunFirstOptionSub ' Name of the Sub
' If chosen, start sub 'Larger description of Second Attribute changes, name it'
If SecondOptionLogical Then Call RunSecondOptionSub ' Name of the Sub
' If chosen, start sub 'Larger description of Third Second Attribute changes, name it'
If ThirdOptionLogical Then Call RunThirdOptionSub ' Name of the Sub
Else
If Ans0 = vbNo Then
End If
End If
Exit Sub
End Select
cbx.TopLeftCell.Offset(, 2).Interior.Color = IIf(cbx.Value = xlOn, vbGreen, vbRed)
'MsgBox cbx.Caption & vbCr & IIf(cbx.Value = xlOn, " is ", " is not ") & "chosen"
Exit Sub
CheckBoxHandlingERROR:
MsgBox "Something went wrong... ;-) in the Sub CheckBoxHandling", vbCritical + vbOKOnly
End Sub
Sub RunFirstOptionSub()
' CODE
End Sub
Sub RunSecondOptionSub()
' CODE
End Sub
Sub RunThirdOptionSub()
' CODE
End Sub
Sub MacroWithOptionsEndsWithoutATrace()
FirstOptionLogical = False
SecondOptionLogical = False
ThirdOptionLogical = False
' OPTIONAL: Delete all remaining checkboxes, if any (most important when testing macro)
On Error Resume Next
For Each chkbx In ActiveSheet.CheckBoxes
chkbx.Delete
Next
' Resetting on Error event to default
On Error GoTo 0
CheckBOxAdding
End Sub
Share and use as you wish, as I used other's knowledge and experience.
I am very sorry, but I haven't found any other solution to present this to you, and I also haven't found anyone else presenting something similar to this.
Updated on Dec 17th 2019:
You could also use these checkboxes even easier way: write a macro that
creates a blank worksheet somewhere After:=Sheets(Sheets.Count) , so that it now becomes the new "last sheet",
put there these checkboxes,
check/uncheck them and start the macro by clicking the lowest one of them,
delete this last worksheet, leaving no traces of macro
That way you won't have to think again about where to put temporary checkboxes...
Updated on Oct 7th 2020:
I finally assumed, it would be better to make this an answered question, since it is.

VBA looking for error values in a specific column

Sub Macro9()
Dim LReturnValue As Boolean
LReturnValue = IsError(Sheets("Lookup Addition").Range("A:A").Value)
If LReturnValue = False Then
i = MsgBox("there were no errors", vbOKOnly)
Else
i = MsgBox("there were errors", vbOKOnly)
End If
End Sub
I am a little confused as to what the IsError(Customfunction()) syntax should be. how do we tell it to check every cell in the the range?
Counting errors in a range doesn't require looping (which can be very slow if the range is large) or even any VBA.
Just add this worksheet function to a cell somewhere. If you don't want the user to see this cell, you can hide the row/column/sheet.
=SUMPRODUCT(ISERROR(A:A)*(1=1))
If you still want a pop-up box for the user, your VBA will now be:
Sub CountErr()
MsgBox "There are " & ActiveSheet.Range("B1").Value & " Errors"
End Sub
Make sense?
You could simply use Evaluate and the worksheet function COUNTIF to count the # of errors:
Sub CheckRangeForErrors()
Dim errCount As Long
Dim rng As Range
Dim cl As Range
Dim col As String
col = Application.InputBox("Enter the column letter you would like to check for errors", "Column Name?")
If Not Len(col) = 1 Then
MsgBox "You have entered an invalid selection", vbCritical
Exit Sub
End If
Set rng = Sheets("Lookup Addition").Range(col & "1", Range(col & "1048576").End(xlUp))
errCount = Application.Evaluate("COUNTIF("& rng.Address &",IsError)")
If errCount = 0 Then
MsgBox "there were no errors", vbOKOnly
Else
MsgBox "there were " & errCount & " errors", vbOKOnly
End If
End Sub

Resources