I have read through the multiple Q&As on error handling in VBA but for some reason my code does not work. I am trying to filter for a specific word (variable name "item"), if the filtered range does not have the word, it must skip the code and jump to error handler (and go to the next word). This must be continued until the for is done. My code is below:
Sub Group_Button1_Click()
Worksheets("Grouping_Name").Select
Range("B2").Select
Range(Selection, Selection.End(xlDown)).Select
lastrow_grouping = Selection.Count + 1
Dim filterRange As Range
Dim copyRange As Range
Dim lastrow_To_be_grouped As Long
For grouping_counter = 2 To lastrow_grouping
' on to_be_grouped sheet turn off any autofilters that are already set Sheets("To_be_grouped").AutoFilterMode = False
' find the last row with data in column A of To_be_grouped sheet
lastrow_To_be_grouped = Sheets("To_be_grouped").Range("A" & Sheets("To_be_grouped").Rows.Count).End(xlUp).Row
' the range that we are auto-filtering (all columns)
Set filterRange = Sheets("To_be_grouped").Range("A1:B" & lastrow_To_be_grouped)
' Copy filtered data (exclude header) in To_be_grouped sheet
Set copyRange = Sheets("To_be_grouped").Range("A2:B" & lastrow_To_be_grouped)
' Assign variable "item" which is the word to filter
Item = Sheets("Grouping_Name").Range("A" & grouping_counter).Value
' Filter column with variable item
filterRange.AutoFilter field:=2, Criteria1:="=*" & Item & "*", Operator:=xlAnd
' copy the visible cells to Final_Grouping sheet
' determine first row with no data in Final Grouping sheet and copy to sheet
On Error GoTo errorhandler
' This is where I need help, if there is no line with the filtered word the code must jump to errorhandler
If IsNumeric(copyRange.SpecialCells(xlCellTypeVisible).Count) = True Then
copyRange.SpecialCells(xlCellTypeVisible).Copy Sheets("Final_Grouping").Range("A" & item_counter_total)
' delete the tables
Sheets("To_be_grouped").Range("$A$1:$B$" & lastrow_To_be_grouped).Offset(1, 0).SpecialCells _
(xlCellTypeVisible).EntireRow.Delete
' Count the number of rows added
item_counter = copyRange.SpecialCells(xlCellTypeVisible).Count / 2
' ------------------------------------------
For group_table_counter = item_counter_total To item_counter_total + item_counter - 1 Step 1
Sheets("Final_Grouping").Range("C" & group_table_counter).Value = Item
Next group_table_counter
' ------------------------------------------
item_counter_total = item_counter_total + item_counter
End If
errorhandler:
Next grouping_counter
End Sub
Any assistance will be greatly appreciated. Thank you
I can't tell what your code is doing exactly or what the error that you are trying to capture is, but one of the problems you are having is that you can't put "Next grouping_counter" in the error handler.
I think your misunderstanding is based on the fact that if you put in an "On Error GoTo ErrorHandler" statement, the code in the ErrorHandler will be run in the case of an error.
But when the code is compiled, VBA is trying to determine whether the code makes sense and is giving you an error that there is no For Loop for your next statement, because, while if an error were to occur where you expect it to, you would be within a for loop, the program is not aware of this.
As sous2817 mentioned in a comment, you likely do not need error handling here, but I will present both methods so you can better understand how to do error handling.
In this case, you could use ErrorHandling in a couple of ways, assuming that an error occurs in your code:
1.
For grouping_counter = 2 To lastrow_grouping
'some code here
On Error GoTo ErrorHandler
'code that has error you are trying to handle
'more code to run
NextGroupingCounter: 'label to jump to from error handler
Next grouping_counter
Exit Sub
ErrorHandler:
GoTo NextGroupingCounter
End Sub
Of course, this is if you don't actually want to do anything with the error other than skip the rest of the code. If that is what you want, then just change the On Error Code to GoTo the NextGroupingCOunter label!
2.
For grouping_counter = 2 To lastrow_grouping
'some code here
On Error GoTo NextGroupingCounter
'code that has error you are trying to handle
'more code to run
NextGroupingCounter: 'label to jump to from error handler
Next grouping_counter
Of course, you likely don't even need the error handling
3.
For grouping_counter = 2 To lastrow_grouping
'some code here
If [*insert text to check condition needed for no error*] Then
'code to run if no error
End If
'If the condition needed for no error is false, this will just go to the next one.
Next grouping_counter
Option 3 is preferred if possible. If an error will actually occur in your code, then Option 2 will work fine. If you want to capture the error and then jump back into your loop, Option 3 works.
Additionally, notice that I put "Exit Sub" above the ErrorHandler. The ErrorHandler label is just a label, so if the program runs until the end, it will run the code in the ErrorHandler section. The Exit Sub ends the procedure to avoid this.
Also note that for other circumstances, you could use "On Error Resume Next" to just continue in the case of an error or even put "Resume Next" in your error handler to return to the line after the one of error. This is a bit beyond the scope of the question, but may add some useful info.
Related
I have looked up the question and have seen several solutions addressing things like Select or having protected worksheets, none of which apply to me here.
For various reasons, I can't post the entire code, but I will give a description of what it does and post the exact sub that is giving me issues.
I have a Macro that generates a number of worksheets based on the Month and Year input by the user (so "1" - "31" or "1" - "30" etc). To generate these worksheets, the macro makes copies of a worksheet fittingly named "EXAMPLE". One thing that is copied is a picture (just a rectangle with the word 'Export' on it) that has a macro attached to it.
I recently made what I thought was a cosmetic change by moving the location of this picture, since then, when I run the macro I get an error:
"Run-time error '1004':
Microsoft Excel cannot paste the data."
And options for 'End' 'Debug' and 'Help'
If I select 'Debug' it points me to a second macro which is called during the process of the generation macro'
Sub CopyAllShapes()
Dim ws As Worksheet
' Sets the non-generated worksheets as an array
nSheets = Array("EXAMPLE", "Weekly Totals", "Menu")
' Copies the Picture from the EXAMPLE sheet to all worksheets not in the array and then assigns a
' seperate Macro called "Export" to the picture on each of these sheets.
For Each ws In ActiveWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, nSheets,0)) Then
Sheets("EXAMPLE").Shapes("Picture 1").Copy
ws.Range("J62").PasteSpecial
ws.Shapes("Picture 1").OnAction = "Export"
End If
Next ws
Application.CutCopyMode = xlCopy
End Sub
The Debug option highlights the line
ws.Range("J62").PasteSpecial
What really confuses me is that if I select 'End' instead of 'Debug', the macro stops, but all the the sheets have had the picture pasted as well as the Export Macro assigned and everything works as expected. If I were the only person using this, it would be a minor annoyance, but this document is used by many people that can't reliable be told to "just ignore" the error. Since the macro is functioning as expected, how can i troubleshoot what is causing the problem and make the error go away?
As I said, I can't post the entire macro, but I can post some bits and pieces if anyone needs more info.
Not a pure fix, but this code will retry the Copy/Paste if it fails (up to 3 times), instead of just dropping it:
Const MaxRetries AS Long = 3
Sub CopyAllShapes()
Dim ws As Worksheet
Dim TimesRetried As Long
' Sets the non-generated worksheets as an array
nSheets = Array("EXAMPLE", "Weekly Totals", "Menu")
' Copies the Picture from the EXAMPLE sheet to all worksheets not in the array and then assigns a
' seperate Macro called "Export" to the picture on each of these sheets.
For Each ws In ActiveWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, nSheets,0)) Then
TimesRetried = 0
CopyExampleShape:
On Error Resume Next
Sheets("EXAMPLE").Shapes("Picture 1").Copy
ws.Range("J62").PasteSpecial
'If the Copy/Paste fails, retry
If Err Then
On Error GoTo -1 'Clear the Error
'Don't get stuck in an infinite loop
If TimesRetried < MaxRetries Then
'Retry the Copy/paste
TimesRetried = TimesRetried + 1
DoEvents
GoTo CopyExampleShape
End If
End If
On Error GoTo 0
ws.Shapes("Picture 1").OnAction = "Export"
End If
Next ws
Application.CutCopyMode = xlCopy
End Sub
I have come across a similar issue before, and it was been down to another program (in one case Skype) reacting to data being added to the Clipboard by "inspecting" it. That then briefly locked the clipboard, so the Paste/PasteSpecial operation failed. This then caused the Clipboard to be wiped clean... All without Excel doing anything wrong.
"It is possible to commit no mistakes and still lose. That is not a weakness; that is life." ~ Jean-Luc Picard
On moving to Office 365 and Win10 (can't say which of those was the culprit) I found a bunch of existing macros which would give that same error when trying to paste a copied image onto a worksheet.
When entering debug, the "paste" line would be highlighted, but if I hit "Continue" it would (after one or two attempts) run with no errors.
I ended up doing this:
'paste problem fix
Sub PastePicRetry(rng As Range)
Dim i As Long
Do While i < 20
On Error Resume Next
rng.PasteSpecial
If Err.Number <> 0 Then
Debug.Print "Paste failed", i
DoEvents
i = i + 1
Else
Exit Do
End If
On Error GoTo 0
i = i + 1
Loop
End Sub
...which looks like overkill but was the only reliable fix for the problem.
EDIT: cleaned up and refactored into a standalone sub.
Just wanted to let everyone know I have found a (sort of) solution. Based on the answers/comments from Tim Williams and PeterT I modified the code to look like this:
Sub CopyAllShapes()
Dim ws As Worksheet
' Sets the non-generated worksheets as an array
nSheets = Array("EXAMPLE", "Weekly Totals", "Menu")
' Copies the Picture from the EXAMPLE sheet to all worksheets not in the array and then assigns a
' seperate Macro called "Export" to the picture on each of these sheets.
For Each ws In ActiveWorkbook.Worksheets
If Not IsNumeric(Application.Match(ws.Name, nSheets,0)) Then
Sheets("EXAMPLE").Shapes("Picture 1").Copy
On Error Resume Next
ws.Range("J62").PasteSpecial
On Error Goto 0
ws.Shapes("Picture 1").OnAction = "Export"
End If
Next ws
Application.CutCopyMode = xlCopy
End Sub
This has successfully ignored the error and everything is working properly now! Thanks everyone for your help, hopefully this aids someone else in the future!
The following statements (in a loop) end in an error when row 1 is empty.
I would have expected the error to be silently ignored and the next sheet to be processed.
How come the code stops when the on error is active ? I would expect it to ignore the error and continue processing after the skip label.
Sub listSheets()
Dim sh As Worksheet, ar
Dim a
Set a = Application
For Each sh In ThisWorkbook.Sheets
Sheet1.Cells(3 + sh.Index, 1) = sh.Name
On Error GoTo skip
ar = sh.Range("1:1").SpecialCells(xlCellTypeConstants) 'code stops here if row 1 empty
ar = a.Transpose(a.Transpose(ar))
Sheet1.Cells(3 + sh.Index, 2) = Join(ar, "//")
ar = Null
skip:
Next sh
End Sub
Note: Error trapping is set to "Break on unhandled errors"
I believe the reason lays in the fact you allready encountered an error. You however never cleared your error from the handler. A second error won't skip over that line again.
So to replicate this I had three worksheets, a blank row in the second and third. Your On Error Goto went through the second sheet but would return Error 1004 on the third.
You might want to include an Err.Clear
On Error Resume Next
ar = sh.Range("1:1").SpecialCells(xlCellTypeConstants) 'error 1004 on certain sheets
skip:
Err.Clear
Next sh
EDIT: Just found an alternative solution here
And even then, maybe even drop the error handling completely and use something like:
If WorksheetFunction.CountA(sh.Rows(1)) > 0 Then
ar = sh.Range("1:1").SpecialCells(xlCellTypeConstants)
End If
A Resume statement is needed after an error occurs in which an error handler is enabled by the On Error statement. As per VBA reference...
If an error occurs while an error handler is active (between the occurrence of the error and a Resume, Exit Sub, Exit Function, or Exit Property statement), the current procedure's error handler can't handle the error.
For additional information have a look at the following link...
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/on-error-statement
I have a form that I have created in Excel as an input area for Production Information. Once the data has been filled into the Form I have a save button with a macro behind it. This to copy and paste the data from the form into a line in the Info Log area below the form.
I have tried to use a "helper" column to place True if the information being saved has already been saved once. I am not sure I have all of that correct either.
Sub Record_Save()
'With Sheets("Roll Line Form")
'Application.ScreenUpdating = False
'Range("B43:B" & Cells(Rows.Count, 1).End(xlUp).Row) =
"=CountIf(D2:D4,D2,)>1"
'Range("B:B").AutoFilter 1, "True"
'If .Range("B:B").Value = "True" Then
'MsgBox "This has already been entered"
'Exit Sub
'End If
'End With
With Sheets("Roll Line Form")
If .Range("D2").Value = Empty Then
MsgBox "Please Enter a Date"
Exit Sub
End If
RecordRow = .Range("C999999").End(xlUp).Row + 1 'Find First Available Row
For RecordCol = 3 To 46
.Cells(RecordRow, RecordCol).Value = .Range(.Cells(41,
RecordCol).Value).Value
Next RecordCol
End With
End Sub
I want to have the Macro understand that the data is already saved and not to save the data in the Log area. I have commented out the code I tried to use but when it was still running I would get the error code of Run-time error '1004': Application-defined or object error
This is on the line that starts Range ("B43:B"...
Below code is part of a larger code where some data is filtered by using AutoFilter. And in most instances there is data in the filtered cells. However, in some instances there is no data, and when trying to use copy, I get the error "No Cells". Which makes sense.
Therefore I'm trying to use below code to exit the sub, if the filtered cells has no data in them. But the "No Cells" error keeps popping up in the first line of the code.
I've tested the range and it's populated correctly.
I've tried .Cells.Count and just .Count. Nothing works.
Can someone help me?
If .Range("C5:C" & lastrow).SpecialCells(xlCellTypeVisible).Cells.Count = 0 Then
.AutoFilterMode = False
Exit Sub
End If
Whenever you are working with SpecialCells, sandwich them betweeen OERN and OEGTO as shown below
Is this what you are trying? (Untested)
On Error Resume Next
Set rng = .Range("C5:C" & lastrow).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then
.AutoFilterMode = False
Exit Sub
End If
Until now, if there is an error in one of the macro codes, it announces an error
I want instead to let him know he has to go to the manager
That's the code I have now
Private Sub Workbook_'What should be written here?()
On Error GoTo error1
error1:
MsgBox "Error, contact administrator"
End Sub
How can I display the message in all errors in the file
If this is not clear enough, please write to me
I recommend not using the On Error GoTo error1 method of error trapping. You can trap expected errors directly rather a generic 'catch all' approach.
Using On Error GoTo error1 is error trapping your entire code. You won't even know what line threw the error which is problematic if your code is long.
Here is how you to correctly wrap your entire code in a generic 'catch all' error trap. You need to use Exit Sub after your code. This ensures your error line only gets reached on the instance of an error.
Sub Generic ()
On Error GoTo error1
'Code goes here
Exit Sub
''''''''''''''''''''''''''''''''''''''
error1:
MsgBox "Error, Contact Administrator"
End Sub
A better approach is to anticipate potential errors and code out the errors or handle them in a more direct approach. Since we do not know what error you are trying to trap for, I will just give one example. The below code aims to copy the last used cell in Column A and copy it to cell B2
Sub CopyRange()
Dim LRow as Long 'Last Row
LRow = Range("A" & Rows.Count).End(xlUp).Row
Range("A" & LRow).Copy Destination:= Range("B2") '<---- anticipated error line
End Sub
This code will through an error if LRow = 0 since there is no range A0 to be copied. You could wrap your entire code in the generic error trap, or you could handle the error directly. Check the value of LRow and display your message there. Now you will know what the error is!
Sub CopyRange()
Dim LRow as Long 'Last Row
LRow = Range("A" & Rows.Count).End(xlUp).Row
'Error Trap Here!
If LRow = 0 Then
MsgBox "LRow Calculation Issue. Notify Admin!"
Exit Sub '<---- code will stop here before the error has a chance to be raised
End If
Range("A" & LRow).Copy Destination:= Range("B2") '<---- anticipated error line
End Sub