VBA code - error after 20 rows

Please provide some detailed examples of it not working as intended.
To do this, let us know:
- Exactly what you are entering and exactly what cell you are entering it in
- What you expect to happen
- What is happening
 
Upvote 0

Excel Facts

VLOOKUP to Left?
Use =VLOOKUP(A2,CHOOSE({1,2},$Z$1:$Z$99,$Y$1:$Y$99),2,False) to lookup Y values to left of Z values.
Please provide some detailed examples of it not working as intended.
To do this, let us know:
- Exactly what you are entering and exactly what cell you are entering it in
- What you expect to happen
- What is happening

Hey, let me just say I really appreciate your help on this.
-I'm entering time in the "hh:mm" format in the cells that I've told the macro to look over the entire column - i.e. column 5)
Example - I'll enter 25:00 in cell E5.
-I'm expecting the code to compare cell E5 in this example to CC5 (another time in the "hh:mm" format. And if E5<cc5 then="" nothing,="" but="" if="" it's="" bigger="" give="" an="" error="" that="" the="" time="" allocated="" is="" after="" staff="" member's="" desired="" work="" time.

-What happens is that no matter what cell I enter something into, even those that I'm not trying to monitor with the val_change or even if it's one that should just compare the 2 cells - it triggers my error which I've set as a message.</cc5>
 
Last edited:
Upvote 0
-I'm expecting the code to compare cell E5 in this example to CC5 (another time in the "hh:mm" format. And if E5<cc5 then="" nothing,="" but="" if="" it's="" bigger="" give="" an="" error="" that="" the="" time="" allocated="" is="" after="" staff="" member's="" desired="" work="" time.
</cc5>
Looks like your sentence got cut off. If you are using < and > signs, be sure to surround them in spaces, or else they are treated as HTML code (see https://www.mrexcel.com/forum/forum.php).
So, can you finish that statement, and let me know what is in cell CC5 in this particular example?
I am trying to recreate the behavior you are experiencing on my side, so I need to make sure that all values are exactly the same as yours, so please provide all that pertinent information.
 
Upvote 0
Better than finishing off the sentence let's look at a particular example that doesn't work and I can then take it from there.
All < > = symbols are surrounded by spaces.


The Code:
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ProcError
Application.ScreenUpdating = False


'FRI End Time - 18 y/o check
If Target.Column = 5 Then
    'If under 18 years of age BJR will be 0 and then
    If Range("BJR" & Target.Row).Value = 0 Then
        'If Friday finish time is > 23:00 then
        If Range("BKA" & Target.Row).Value = 1 Then
            MsgBox "This staff member is under 18 and cannot work past 23:00!", vbExclamation, "ERROR"
        End If
    End If
    'If FRI END - SAT START is less than 11h rest Then ERROR
    If Range("BJT" & Target.Row).Value = 0 Then
        MsgBox "This staff member needs more rest!", vbExclamation, "ERROR"
    End If
End If

'SAT Start Time - 11H check - Against Previous Day
If Target.Column = 12 Then
    'If Less than FRI END - SAT START is less than 11h rest Then ERROR
    If Range("BJT" & Target.Row).Value = 0 Then
        MsgBox "This staff member needs more rest!", vbExclamation, "ERROR"
    End If
End If

ProcError: MsgBox "ERROR!"
Application.ScreenUpdating = True


End Sub



The problem: No matter what cell you change to what it always goes to ProcError, telling me that there's an error in something, somewhere.

How the document is set up so no one has to download anything:
Tab name is "ROTA (ORIG)"
Cell BP10 is formatted as the default date cell - we're going to put that as 17/02/2001
Cell BQ10 is =IF(BP10="","",DATEDIF(BP10,TODAY(),"Y"))
Cell CC10 is formatted ashh:mm - we'll set it to 19:00
Cell CD10 is formatted as hh:mm - we'll set it to 8:00
Cell BJQ10 is =IF('ROTA (ORIG)'!L10="","12:00",IF('ROTA (ORIG)'!L10<'ROTA (ORIG)'!E10,('ROTA (ORIG)'!L10-'ROTA (ORIG)'!E10+('ROTA (ORIG)'!L10<'ROTA (ORIG)'!E10)),('ROTA (ORIG)'!L10-'ROTA (ORIG)'!E10+('ROTA (ORIG)'!L10<'ROTA (ORIG)'!E10)+TIME(12,0,0))))
Cell BJR is =IF(AND(NOT(ISBLANK(BP10)),BP10<=TODAY()-6570),1,IF(ISBLANK(BP10),"",0))
Cell BJT is =IF(BJK10>TIME(10,59,0),1,0)
Cell BKA is =IF(E10>TIME(23,0,0),1,0)
Cell E10 is formatted as hh:mm - Friday end shift timeCell L10 is formatted as hh:mm - Saturday start time

What I'm trying to achieve with VBA:
When we set E10 to 18:00 then nothing happens.
When we set E10 to 19:30 then ERROR MSG about staff member not being able to work past their agreed finish time (CC10)
When we set E10 to 24:30 then ERROR MSG about staff member not being able to work past their agreed finish time (CC10) + error saying they can't work past 23:00 (BKA) because they're not 18 (BJR)
When we E10 as 19:00 and L10 as 5:00 then ERROR MSG that there isn't 23 hours rest (BKA)
And nothing should proc if I change Cell A10 or ZZZ300 - only changes in E1,E2,E3,etc. should trigger this macro.

I appreciate the help so much, this has become such a huge project (for my excel skill level at least) that I'm tearing my hair out even when I'm not at work. So stressful.
 
Last edited:
Upvote 0
The problem: No matter what cell you change to what it always goes to ProcError, telling me that there's an error in something, somewhere.
It looks like you didn't take the advice I said up in post 5 (https://www.mrexcel.com/forum/excel-questions/1059027-vba-code-error-after-20-rows.html#post5086191).

Basically, you have three main blocks of your code:
1. Code if cell in column 5 updated
2. Code if cell in column 18 updated
3. Error handling code

The issue is that how you have written the code, it is ALWAYS going to hit your error handling code because you are not telling it exit the code anywhere before that part. You need to add an Exit Sub line before the error handling part, so that if it gets through the first two blocks without any errors, it exits BEFORE it hits that part. You want it to only run on the error handling code if an error is encountered (the On Error GoTo ProcError line handles that).

So you need to do that I instructed up in post 5, i.e.
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ProcError
Application.ScreenUpdating = False


'FRI End Time - 18 y/o check
If Target.Column = 5 Then
    'If under 18 years of age BJR will be 0 and then
    If Range("BJR" & Target.Row).Value = 0 Then
        'If Friday finish time is > 23:00 then
        If Range("BKA" & Target.Row).Value = 1 Then
            MsgBox "This staff member is under 18 and cannot work past 23:00!", vbExclamation, "ERROR"
        End If
    End If
    'If FRI END - SAT START is less than 11h rest Then ERROR
    If Range("BJT" & Target.Row).Value = 0 Then
        MsgBox "This staff member needs more rest!", vbExclamation, "ERROR"
    End If
End If

'SAT Start Time - 11H check - Against Previous Day
If Target.Column = 12 Then
    'If Less than FRI END - SAT START is less than 11h rest Then ERROR
    If Range("BJT" & Target.Row).Value = 0 Then
        MsgBox "This staff member needs more rest!", vbExclamation, "ERROR"
    End If
End If

Application.ScreenUpdating = True
Exit Sub

 
ProcError: MsgBox "ERROR!"
Application.ScreenUpdating = True

End Sub
 
Last edited:
Upvote 0
Sorry, I should have mentioned - I tried that already. It just made it so nothing happened.
If I enter something in cell A4 nothing would happen (as opposed to the error before).
But also if I enter something in cell E10 nothing would happen (as opposed to before with the error or the messages that should pop up).

My bad, I should have said that.
 
Upvote 0
You have so many formulas pulling from so many other cells, it is not going to be possible for me to recreate this.

However, it is important to understand what is really going on.
Sorry, I should have mentioned - I tried that already. It just made it so nothing happened.
If I enter something in cell A4 nothing would happen (as opposed to the error before)
The way you had it written before, every single change you make on the sheet will cause that error message to come up. But it is not coming up because it found an error, it is coming up because you are hitting that code EVERY time the code runs. Nothing in your code is telling it to stop or skip over the error code. When using OnError code, you MUST do something to make the code stop before hitting it if it does not find any errors.

By putting the additions in that I did, if it finds no errors, we are telling it to exit the code before running the error message, as it should.
If you change the value in A4, nothing SHOULD happen, as your IF blocks are looking for changes happening in columns 5 or 12. A4 is in neither of those columns.

Try adding the following message boxes to your code, like this, and you will see that the code is running. It will tell you when it starts, if it falls in either loop, when it is done, and if an error is found.
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ProcError
Application.ScreenUpdating = False

[COLOR=#ff0000]MsgBox "Worksheet_Change macro running"[/COLOR]

'FRI End Time - 18 y/o check
If Target.Column = 5 Then[COLOR=#ff0000]
    MsgBox "Change occurred in column 5"[/COLOR]
    'If under 18 years of age BJR will be 0 and then
    If Range("BJR" & Target.Row).Value = 0 Then
        'If Friday finish time is > 23:00 then
        If Range("BKA" & Target.Row).Value = 1 Then
            MsgBox "This staff member is under 18 and cannot work past 23:00!", vbExclamation, "ERROR"
        End If
    End If
    'If FRI END - SAT START is less than 11h rest Then ERROR
    If Range("BJT" & Target.Row).Value = 0 Then
        MsgBox "This staff member needs more rest!", vbExclamation, "ERROR"
    End If
End If


'SAT Start Time - 11H check - Against Previous Day
If Target.Column = 12 Then
[COLOR=#ff0000]    MsgBox "Change occurred in column 12"[/COLOR]
    'If Less than FRI END - SAT START is less than 11h rest Then ERROR
    If Range("BJT" & Target.Row).Value = 0 Then
        MsgBox "This staff member needs more rest!", vbExclamation, "ERROR"
    End If
End If

Application.ScreenUpdating = True
[COLOR=#ff0000]MsgBox "Code finished running with no errors!"[/COLOR]
Exit Sub

 
ProcError: MsgBox "ERROR!"
Application.ScreenUpdating = True

End Sub
Unfortunately, I cannot test out the logic within your IF loops without access to your workbook.
I would recommend adding a break point at the beginning of your code to step inside it, and then use the F8 key to step through the code one line at a time to see what it is doing (if you hover over any variables while doing this, it will show you their value). This is a common debugging technique.
See: https://www.thespreadsheetguru.com/blog/2014/4/8/debugging-vba-code-adding-breakpoints
 
Upvote 0
This sounds precisely like what I need to go through all the code I've got!
I will adapt it to every section and get back to you with results.

In the mean time, is there any way we can also put in exits on those sub-parts?
Something along the line of "IF cell 5 then run code, else if cell 12 run code, else exit macro"
I'm thinking of a way to make it run only on the specified cells rather than on every cell (which would save me a lot of processing time since I'm running this on work computers from the bronze ages)?
 
Last edited:
Upvote 0
In the mean time, is there any way we can also put in exits on those sub-parts?
Yes, you can put in an "Exit Sub" at the end of each If block (before the "End If" line).

Something along the line of "IF cell 5 then run code, else if cell 12 run code, else exit macro"
A Case statement would work well here, but note that if you have Error Handling, you will still need an Exit Sub statements (or more than one) somewhere in your code. That is always the case if you use Error Handling.

Here is a structure with a Case statement with error handling and just one Exit Sub:
Code:
    On Error GoTo ErrProc

    Select Case Target.Column
'       For column 5
        Case 5
'           Do this here
'       For column 12
        Case 12
'           Do this there
    End Select
    
'   Exit sub before error handling
    Exit Sub
    
'   Error handling below
ErrProd:
'   Error handling code
And here is the structure with an Exit Sub in each section
Code:
    On Error GoTo ErrProc

    Select Case Target.Column
'       For column 5
        Case 5
'           Do this here
            Exit Sub
'       For column 12
        Case 12
'           Do this here
            Exit Sub
'       All else, exit sub
        Case Else
'           Exit Sub
    End Select
    
'   Exit sub before error handling
    Exit Sub
    
'   Error handling below
ErrProd:
'   Error handling code
See: https://www.techonthenet.com/excel/formulas/case.php

I'm thinking of a way to make it run only on the specified cells rather than on every cell (which would save me a lot of processing time since I'm running this on work computers from the bronze ages)?
You can do that too, using the Intersect method, like this:
Code:
Private Sub Worksheet_Change(ByVal Target As Range)

    Dim rng As Range
    
'   Only run if one cell manually updated at a time
    If Target.Count > 1 Then Exit Sub
    
'   See if update is in range A1:A100
    Set rng = Intersect(Target, Range("A1:A100"))
    
'   If an update is made in that range, do something
    If Not rng Is Nothing Then
'       Stuff to do here
    End If
    
End Sub
And you can set up multiple ranges and have multiple checks within that same procedure.
 
Upvote 0

Forum statistics

Threads
1,214,919
Messages
6,122,260
Members
449,075
Latest member
staticfluids

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top