Avoid multiple error pop up messages in excel - excel

Option Explicit
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
'Does the validation range still have validation?
If Not HasValidation(Range("A1:A1048576")) Then RestoreValidation
If Not HasValidation(Range("C1:C1048576")) Then RestoreValidation
If Not HasValidation(Range("I1:I1048576")) Then RestoreValidation
If Not HasValidation(Range("P1:P1048576")) Then RestoreValidation
End Sub
Private Sub RestoreValidation()
Application.EnableEvents = False
'turn off events so this routine is not continuously fired
Application.Undo
Application.EnableEvents = True
'and turn them on again so we can catch the change next time
MsgBox "Your last operation was canceled." & _
"It would have deleted data validation rules.", vbCritical
End Sub
Private Function HasValidation(r) As Boolean
' Returns True if every cell in Range r uses Data Validation
On Error Resume Next
Debug.Print r.Validation.Type 'don't care about result, just possible error
If Err.Number = 0 Then HasValidation = True Else HasValidation = False
End Function
I applied validation on 4 columns with the above code, Even the validation is passed I am getting 4 error pop up messages how to restrict number of error messages ?
UPDATE:
I selected the value from the drop down which is a valid selection, but I am getting the below error message.
I am using the following code

If you are working with the sheet's Change event, then I would recommend having a look at THIS
Since you are working with just one sheet then you don't need the code in the ThisWorkbook code area. If you put it there then the code will run for every sheet. Put the code in the relevant sheet's code area. So if the validation is in Sheet1 then put the code in the Sheet1 code area. See ScreenShot below.
Ok now to address your query. What you can do is use a Boolean variable and then set it to True after you show the first message so that the message doesn't show again.
Try this (UNTESTED)
Dim boolDontShowAgain As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
Application.EnableEvents = False
If Not HasValidation(Range("A1:A1048576")) Then RestoreValidation
If Not HasValidation(Range("C1:C1048576")) Then RestoreValidation
If Not HasValidation(Range("I1:I1048576")) Then RestoreValidation
If Not HasValidation(Range("P1:P1048576")) Then RestoreValidation
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
Private Sub RestoreValidation()
Application.Undo
If boolDontShowAgain = False Then
MsgBox "Your last operation was canceled." & _
"It would have deleted data validation rules.", vbCritical
boolDontShowAgain = True
End If
End Sub
Private Function HasValidation(r) As Boolean
On Error Resume Next
Debug.Print r.Validation.Type
If Err.Number = 0 Then HasValidation = True
End Function

Related

Excel VBA Function throws an error when changes the cell

I have been using this code which copies the range and paste the range as picture but when i change the concerns cell it throws an error that is Error 1004, Microsoft Excel cannot paste the data.
Any help will be appreciated.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("C5:P5")) Is Nothing Then
Application.CutCopyMode = TRUE
ActiveSheet.Pictures.Delete
Worksheets("Pivot").Range("FC3:FP35").Copy
With Worksheets("Map")
.Activate
.Range("C8").Select
.Pictures.Paste
End With
Application.CutCopyMode = FALSE
End If
End Sub
You need to turn off events Application.EnableEvents = False before changing cells and turn them on after. Make sure they get turned on in any case of an error in this event or you will not be able to fire any other events in your Excel instance. So error handling in this event is a must have. • You might benefit from reading
How to avoid using Select in Excel VBA.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("C5:P5")) Is Nothing Then
On Error Goto ERR_ENABLE_EVENTS
Application.EnableEvents = False
Me.Pictures.Delete
Worksheets("Pivot").Range("FC3:FP35").Copy Destination:=Worksheets("Map").Range("C8").Paste
End If
ERR_ENABLE_EVENTS:
Application.CutCopyMode = False
Application.EnableEvents = True
If Err.Number <> 0 Then
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End If
End Sub

VBA: Workbookfunction if Dropdown Changes Call Sub with different sheets

I have a worksheet function that automatically calls CopyValues once dropdown in E4 changes on Sheet Debt Detail. This macro only runs if the sheet name is "Debt Detail" otherwise it is going to Exit Sub. This macro worked well until now. I added another sheet called "Borrower Statement", which is supposed to call BorrowerStatementCall if E4 changes in Sheet Borrower Statement.
I need to modify the existing Workbook function to accomplish this.
Below is the existing code. Any help and suggestions on how to accomplish this would be appreciated:
Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range)
Application.ScreenUpdating = False
If sh.Name <> "Debt Detail" Then Exit Sub
If Target.Address = Range("$E$4").Address Then
Call CopyValues
Range("A1").ClearOutline
Range("d2").Select
End If
Application.ScreenUpdating = True
End Sub
Some suggestions on your code:
Indent your code
Use at least some error handling if you're turning off screenupdating and other stuff
No need for the Call statement
Code:
Private Sub Workbook_SheetChange(ByVal sh As Object, ByVal Target As Range)
On Error GoTo CleanFail
' Exit if modified cell is not E4
If Target.Address <> "$E$4" Then Exit Sub
' Turn off stuff to speed up process (only if modified cell is E4)
Application.ScreenUpdating = False
' Check the sheet name and call procedure accordingly
Select Case sh.Name
Case "Debt Detail"
' Do stuff if it's the target sheet
CopyValues ' Calls the sub CopyValues
sh.Range("A1").ClearOutline
sh.Range("D2").Select
Case "Borrower Statement"
' Do stuff if it's the target sheet
BorrowerStatementCall ' calls the sub BorrowerStatementCall
End Select
CleanExit:
' Turn on stuff again
Application.ScreenUpdating = True
Exit Sub
CleanFail:
MsgBox "An error occurred:" & Err.Description
GoTo CleanExit
End Sub
Let me know if it works

Using Data Validation and limiting cell characters to 10, but copy and pasting will override the Data Validation and the Error Box won't appear

I have code below, but it won't override and create an error message when copy and pasting onto a Data Validation cell
Private Sub Worksheet_Test(ByVal Target As Range)
'Does the validation range still have validation?
If HasValidation(Range("A2:A3")) Then
Exit Sub
Else
Application.Undo
MsgBox "Error: You cannot paste data into these cells." & _
"Please use the drop-down to enter data instead.", vbCritical
End If
End Sub
Private Function HasValidation(r) As Boolean
'Returns True if every cell in Range r uses Data Validation
On Error Resume Next
x = r.Validation.Type
If Err.Number = 0 Then HasValidation = True Else HasValidation = False
End Function

How to use ByVal Target As Range So it applies to multiple cell and is not dependent on previous

The objective of this code is so every time cell E6:E36 changes from "Yes" or to "Enter Non Final Action Taken Date" I want it to run my macro.
It works only when E6 is marked to match the next value. How do I make it so it is not dependent on the previous cells value?
I'm new with VBA so I'm a bit lost. Any help would be greatly appreciated. See current code below:
Private Sub Worksheet_Change(ByVal Target As range)
Application.EnableEvents = False 'pervent triggering another change event
On Error GoTo ERR_HANDLING
If Not Intersect(Target, range("E6:E36")) Is Nothing Then
Select Case range("E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,E16,E17,E18,E19,E20,E21,E22,E23,E24,E25,E26,E27,E28,E29,E30,E31,E32,E33,E34,E35,E36")
Case "Yes": EnterDate_of_last_Submission
End Select
End If
If Not Intersect(Target, range("E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,E16,E17,E18,E19,E20,E21,E22,E23,E24,E25,E26,E27,E28,E29,E30,E31,E32,E33,E34,E35,E36")) Is Nothing Then
Select Case range("E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,E16,E17,E18,E19,E20,E21,E22,E23,E24,E25,E26,E27,E28,E29,E30,E31,E32,E33,E34,E35,E36")
Case "Enter Non Final Action Taken Date": EnterNonFinal_Date
End Select
End If
On Error GoTo 0
ERR_HANDLING:
Application.EnableEvents = True
If Err.Number <> 0 Then
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContex
End If
End Sub
You need to loop here and compare cell-by-cell, something like the following:
Private Sub Worksheet_Change(ByVal Target As range)
Dim rngToCheck as Range
Set rngToCheck = Intersect(Target, Me.Range("E6:E36"))
If rngToCheck Is Nothing Then Exit Sub
On Error GoTo SafeExit
Application.EnableEvents = False
Dim rng as Range
For Each rng in rngToCheck
Select Case rng.Value
Case "Yes"
EnterDate_of_last_Submission
Case "Enter Non Final Action Taken Date"
EnterNonFinal_Date
End Select
Next
SafeExit:
Application.EnableEvents = True
End Sub
Most likely EnterDate_of_last_Submission and EnterNonFinal_Date should be rewritten to take a Range parameter, namely the cell the date is entered in (which it looks like would correspond to rng.Offset(,1) with your current setup.

Why does my sub not work when it runs fine in immediate window excel vba

I've been trying to get the typical hide sheets/unhide sheets code to work for encouraging Macro enabling. Since I lock down saving, I needed to do it slightly differently than putting it in the Workbook_BeforeClose Sub as usually is done.
But...my hide sub
Sub HideSheets()
'Error Handling when workbook is unprotected.
On Error GoTo EH
'Unprotect the workbook to allow conditional formatting changes.
ThisWorkbook.Sheets("Field Service Report").Unprotect Password:="x"
ThisWorkbook.Sheets("Prompt").Unprotect Password:="x"
'Main Sub Code
Application.EnableCancelKey = xlDisabled
Sheets("Prompt").Visible = xlSheetVisible
Sheets("Field Service Report").Visible = xlSheetVeryHidden
Application.EnableCancelKey = xlInterrupt
'Reprotect worksheet before ending sub.
ThisWorkbook.Sheets("Field Service Report").Protect Password:="x", UserInterfaceOnly:=True
ThisWorkbook.Sheets("Prompt").Protect Password:="x"
Exit Sub
EH:
Call EH
Resume Next
End Sub
and my unhide sub
Sub UnhideSheets()
'Error Handling
On Error GoTo EH
'Unprotect the workbook to allow conditional formatting changes.
ThisWorkbook.Sheets("Field Service Report").Unprotect Password:="x"
ThisWorkbook.Sheets("Prompt").Unprotect Password:="x"
'Main Sub Code
Application.EnableCancelKey = xlDisabled
Sheets("Field Service Report").Visible = xlSheetVisible
Sheets("Prompt").Visible = xlSheetVeryHidden
Application.EnableCancelKey = xlInterrupt
'Reprotect worksheet before ending sub.
ThisWorkbook.Sheets("Field Service Report").Protect Password:="x", UserInterfaceOnly:=True
ThisWorkbook.Sheets("Prompt").Protect Password:="x"
Exit Sub
EH:
Call EH
Resume Next
End Sub
....works fine when called form the immediate window. Sheets hide and unhide appropriately.
But, when I step through the sub it doesn't actually do anything. The idea is to set the sheets to the "prompt" sheet before saving, save, then revert to usable after saving. But I can't even see if that code is working correctly (it appears to) because stepping through the actual hide/unhide subs doesn't do anything.
Edit: No errors, just doesn't change any settings to hide or unhide sheets.
Thoughts?
Edit: So given the comments below, my subs work when run from the immediate window and when stepped through via debugger. They hide and unhide the worksheets appropriately. So, the only thing that can be wrong is the code that calls these subs. So, here are two more subs. One is the button code for a save button, and the other is the Workbook_BeforeSave Sub.
Sub Save_Form()
'Error Handling ...
On Error GoTo EH
'Unprotect the workbook ...
ThisWorkbook.Sheets("Field Service Report").Unprotect Password:="x"
'Variable to disable any other save but this button.
Module1.SaveChk = 1
'Code to automatically save a copy ...
Module1.UserPath = Environ("USERPROFILE")
Module1.Path = UserPath & "\Desktop\"
If Module1.EditChk = "Y" Then
Module1.SaveName = "FSR Master"
Else
Module1.SaveName = Range("AF6").Value
End If
ThisWorkbook.SaveAs _
Filename:=Path & SaveName & ".xlsm", _
FileFormat:=52
If Module1.SaveError <> 1 Then
'User Display of Save Success
MsgBox "Filename = " & SaveName & vbNewLine _
& "File is saved to your desktop."
Else
Module1.SaveError = 0
End If
'Reset SaveChk variable
Module1.SaveChk = 0
'Reprotect Worksheet
ThisWorkbook.Sheets("Field Service Report").Protect Password:="x", UserInterfaceOnly:=True
Exit Sub
EH:
Call ErHa
Resume Next
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
'Error Handling ...
On Error GoTo EH
'Save Initiation Check
If Module1.SaveChk <> 1 Then
Cancel = True
MsgBox "Please Use Form Save Button", vbOKCancel + vbExclamation, "SAVE CANCELLED"
Exit Sub
End If
If Module1.EditChk <> "Y" Then 'Skips the whole block if EditChk = Y
'Create the final range of cells for checking
Set Module1.Required = Application.Union(Module1.Fixed, Module1.Drive, Module1.Stage)
'Check if all required cells are filled in
If WorksheetFunction.CountA(Module1.Required) < Module1.Required.Count Then
Cancel = True
MsgBox "Please Completed Shaded Cells!", vbOK + vbExclamation, "SAVE CANCELLED"
Module1.SaveError = 1
Else
'Set the report date before saving
Application.EnableEvents = False
Range("AE59") = Format(Now(), "mm-dd-yyyy hh:mm:ss AM/PM")
Application.EnableEvents = True
End If
End If
'Renable Macro Splash Screen Before Save
Call HideSheets
Exit Sub
EH:
Call ErHa
Resume Next
End Sub

Resources