GoTo <Line number> in VBA - excel

From the VBA help file:
GoTo Statement
Branches unconditionally to a specified line within a procedure.
Syntax
GoTo _line_
The required line argument can be any line label or line number.
Remarks
GoTo can branch only to lines within the procedure where it appears.
My question is, how can I jump to a line number using GoTo? (I know how to jump to a label.)
(Note: I'm asking this for curiosity's sake. I have no intention of actually using GoTo this way.)

I understand your dislike of the answer "start the line with a line number", but you can't argue with facts. That is exactly what they mean.
The syntax of VBA/VB6 is designed to be backwards-compatible with the syntax of QuickBasic, and before that with the syntax of GW-Basic/MS-Basic, which dates to the late 1970's and even earlier: the original Dartmouth BASIC Language was created in the '60s.
In MS-Basic, like in every other Basic implementation of the era, every line you added to a program had to start with a line number. The line number told the Basic interpreter two things: a) that you were storing the line (otherwise the interpreter would execute it immediately), and b) in what position of the program the line belonged. Why do something so arcane? because when Basic was invented it was intended to be interactive, in a world where the only form of interactivity was a command-line prompt, on a teletype-style printing terminal.
And there were no labels.
A typical Basic session might have looked like this, where > stands for a command processor prompt (this is made-up, but close enough to how it worked). Remember: there are no cursor keys or screens. You are typing on a typewriter - with a roll of paper instead of a screen - and the typewriter responds back at you by printing on the paper as well!:
Welcome to B.A.S.I.C.
Ok <--- Ok told you the interpreter was ready
>LIST <--- print the program
Ok <--- No program, so nothing to list.
>PRINT 2 + 7 <--- No line number, so execute immediately
9 <--- The command executes
Ok
>30 PRINT 2 + 7 <--- Line number, so store the command in position 30
Ok
>10 I = 42 <--- Line number, so store in line 10
Ok
>20 PRINT I + 12 <--- Store on line 20, so insert between 10 and 30
Ok
>LIST <--- Print the program so far
10 I = 42
20 PRINT I + 12
30 PRINT 2 + 7
Ok
>RUN <--- Execute the stored program now
54 <--- line 10 has no output. Line 20 outputs this
9 <--- line 30 outputs this
Ok <--- Done running the program
>20 <--- an empty line number: it means delete the line
Ok
>LIST
10 I = 42
30 PRINT 2 + 7 <--- line 20 is gone!
Primitive? Maybe, but you have to start somewhere.
Back then, you always used GOTO by providing the line number where you wanted the code to jump. It was just how it worked. For example:
10 PRINT "Testing, "
20 I = 1
30 PRINT I; ","
40 IF I >= 3 THEN 60
50 GOTO 30
60 END
QuickBasic was an enhanced version of Basic published by Microsoft that supported optionally compiling programs into executables, rather than running then in the interpreter interactively. Among other enhancements, it also added these two features:
Because it ran full-screen with a fully-featured GUI text editor, it didn't need line numbers to designate where each new line went; you just moved the cursor and typed: traditional line numbers were now optional. In fact, they were discouraged because in a full-featured editor, they just got in the way. But they couldn't just remove them because they were so central to BASIC compatibility, so they were still supported. And they still are, even in VBA.
Since they didn't want you to use line numbers, they needed an alternative for commands that required line numbers as targets, such as GOTO. you were now allowed to place line text labels that could be used as targets for GOTO, etc.
So, you can see that line numbers are not just "line labels made out of digits". They are actually an alternative syntax that has been maintained for compatibility with older versions of the language.
That's it. The help file is simply telling you about the "modern" syntax of GOTO (with text labels), and that - if you really want to - you can still use the legacy syntax with line numbers and legacy GOTO syntax that was invented in the mid-1960's.

Sub Jump()
10 Dim A As Integer
20 A = 25
30 GoTo 50
40 A = 50
50 Debug.Print A
End Sub
It's a throwback to the old (really old) BASIC days, where line numbers were required. Now labels are used.
Sub Jump2()
Dim A As Integer
A = 25
GoTo JumpToHere
A = 50
JumpToHere:
Debug.Print A
End Sub
But using GoTo is considered poor programming, with the exception of OnError GoTo ...

One very useful purpose for old fashion line numbers is for error handling. Many folks utilize a standard error handler of the Sort:
proc name (args)
on error goto handler
code
.
.
exit proc
handler:
debug.print err.number & "(" & err.description & ") in Module: " & ModuleName & "- Proc:" & ProcName at & now
resume next
Exit Proc
Which can be made somewhat more useful In the code Is line numbered, as the ErrLine Property will return the line number
of the offending executable line.
debug.print err.number & "(" & err.description & ") - on Line " & errLine & " in Module: " & ModuleName & "- Proc:" & ProcName at & now

declaring the line number and declaring a lable is basicly the same
but using a line number as a big advantage: it does not use memory!
if your "our of memory" you will not be able to declare a lable
but you will be able to declare a line numer and use that as a "goTo"
sub mySub()
....
on error goto 100
...
exit sub
100: msgbox("Error")
end sub

I read many comments about GOTO being poor programming..
Back in the olden days when
a Hewlit Packard 25 had 25 memories to store all instructions and variables
BASIC was still Beginners All purpose Symbolic Instruction Code and
much better than doing things in 6502 Assembler
I went to computer conference where the
one of the experts was takling about a new language that used blocks and
None of GOTO GOSUB AND RETURN .. yea PASCAL
At the time I KNEW it was impossible to have such a language
but since have spent about 20 years teaching
and designing commercial software in PASCAL
With MS backing their Office with VBA of course Pascal has become rare
even though Delphi was still used as a early years teaching language.
To cut IT short
If you consider the machine code constructed for IF then else end if
and the fact that VBA still evaluates ALL of AND OR NOT XOR in an
If ....... Then when you need to evaluate one a few million times
the then GOTO can save you a few seconds.
However on the topic of ON Error Resume Next
many use these to test if a workbook is open or a Sheets exists
on a closed workbook... ...etc etc ..
In some cases that is poor programming in that the program has to
check all before showing an error whereas
for each ....
while Not Found
found = a = b
wend
only has to check until found
My first teaching computer was a PDP 8 ... 8Kb ..
Punched tape teletype for printing and I/O .. 7 Octal switches to boot.
Then moved up to Comodore 64 ..
Current 16 GB computer has memory of 250,000 of them.
a topical comment
with the FBI CIA etc .....Homeland Security Trumps them all.

Related

Runtime Error 53 "File Not Found" from LotusScript agent (SOLVED)

For unknown reasons a server-side LotusScript agent is throwing Error 53 "File not found" while trying to read the physical file size of an existing mail archive file. Situation is as follows:
the LS agent is looping all files in a given directory "\archive" right below the server's "\Data" dir. The Server in question is Domino 10.0.1 running on a Windows 2016 Server.
The LS code is looping the directory looking for database files whose names follow a given pattern like "a_EmployeeID.nsf". If a DB's filename fits the pattern the code scans the server's names.nsf for the archive owner using the EmployeeID from the filename. If no person doc for that ID is found the code tries to read the db's physical file size using FileLen(filePath & FileName). Then the resulting data (filepath + file size) + EmployeeID are written to a report file on disk. Files that don't follow the pattern are also at least written back to the report. The idea behind that agent is to find "orphaned" or misplaced databases.
For ~80% of the files scanned this works fine, the records with exact file sizes are written to the report. But for the other ~20% runtime error 53 "File not found" pulls up. In those case the record just contains the file path/name + EmployeeID (if available) + "-1" for the file size. Because the file obviously do exist I assume that this is an access or security problem.
The agent is signed with an admin ID having maximum access rights on both the server and the archive files in question (the ID by policy has Manager access in the dbs' ACLs).
The agent's security settings are set to level 3 (unrestricted access with full admin rights) because I first had signed the agent with an ID having Full Admin Access on the server (same result as with the now used ID).
Comparing the databases' ACLs I can't find any differences between those that "work" and the ones that don't. What I see, though, is that it's apparently always the same databases that are throwing this error, so this isn't a random problem.
For completeness here are the crucial parts of the agent code:
sFileName = Dir$(sPath & "*.nsf")
Do Until sFileName = ""
iCount = iCount + 1
sEmpid = "" 'reset
lSizeArc = 0 'reset
dblSizeArc = 0 'reset
sSizeArcFmt = "" 'reset
If(sFileName Like sPattern) Then
sEmpid = Left(Right(sFileName, Len(sFileName) - 2), 6)
Set vec = vwEgid.Getallentriesbykey(sEmpid, True)
If(vec.count = 0) Then
On Error 53 Resume Next 'Error 53 ("File not found")
lSizeArc = FileLen(sPath & sFilename)
If(Err = 53) Then
lSizeArc = -1
sSizeArcFmt = "-1 (no size available)"
Err = 0
Else
dblSizeArc = Round((lSizeArc / 1024 / 1024), 3)
sSizeArcFmt = Format$(dblSizeArc, "0.000") & " MB"
End If
Print #iFileNum,_
"ORPHANED_ARCHIVE;" & sEmpid & ";" & sFileName & ";" & sSizeArcFmt
End If
Else
On Error 53 Resume Next 'Error 53 ("File not found")
lSizeArc = FileLen(sPath & sFilename)
If(Err = 53) Then
lSizeArc = -1
sSizeArcFmt = "-1 (no size available)"
Err = 0
Else
dblSizeArc = Round((lSizeArc / 1024 / 1024), 3)
sSizeArcFmt = Format$(dblSizeArc, "0.000") & " MB"
End If
Print #iFileNum,_
"BAD_FILE_PATTERN;NO_EGID;" & sFilename & ";" & sSizeArcFmt
End If
sFileName = Dir$() 'next file
Loop
Before I start moving in a different direction like looking into using Windows shell or .dll commands I'd really like to understand why in some cases the code insists that some of the files looked at cannot be "found".
Any ideas?
UPDATE 2021-05-19
So finally I found the solution to that weirdness (and it's not a compliment to my programming skills, I admit):
looking again at the files that are throwing error 53 I realized that they all are rather big, > 2.1 GB to be exact. So I have to admit that I made a stupid programming error: assigning a value that size to a LONG variable won't work, of course. Stupid amateur error ...
(But then why doesn't the code throw the proper error telling the value exceeds the limits, as it usually does?)
Anyways, so I changed the variable to be a DOUBLE.
But: result is still the same, though >> error 53.
Then again looking at Designer help I found this small note:
FileLen returns a Long value
In other words: FileLen itself cannot handle files that size, and that error apparently is thrown before the interpreter finds out about my bad coding.
In other words: no way to solve my problem that way. Back to #TorstenLink's comment: I'll use his method now
Extremely strange error message, still, I would say...
Thanks to everyone helping me think ;)
LotusScript is probably making a call to a 32 bit WinAPI to obtain the file-length and this call will be returning a unsigned 32 bit value, for a maximum file size of ~4.2Gb. However, LS doesn't support unsigned 32 bit values, only signed, so any value returned over 2.1Gb is represented by a negative value.
You can take the absolute value of the negative value and put it in a currency or single/float, and add 2.1Gb to get a file-size up to 4.2Gb, but no bigger, since the API call won't be returning a bigger number and therefore, the API call probably doesn't consider this an error and LS hasn't technically 'overflowed' generating a size error.
Alternatively, if you consider any size over say 1Gb as 'reportable' just look for values that are either +ve and > 1gb or < 0 as any negative value means 'big'. I'm guessing the exact file size isn't that important to you.
Since you only READ from disk: DIR and FileLen, you should'nt suffer from Domino LOCK on the file (but don't try to write !)
I suggest you to change your code in order to determine where it falls and on which files:
f(vec.count = 0) Then
placeInCode = 1 'declare this before as int
On Error 53 Resume goto handelError'Error 53 ("File not found")
in the second part, affect placeInCode = 2
then declare a
handelError:
print "we got error 53 on " & sPath & sFilename & " for the " & placeInCode & " part"
resume next

Limit text to allowed characters only - (not by enumerating the wrong characters) | VBA

I would like to limit certain textboxes to accept only [A-Za-z]
I hope, a counterpart to Like exists.
With Like I would have to make a long list of not allowed characters to be able to filter.
Not MyString like [?;!°%/=....]
I can think of a solution in the form of:
For Counter = 1 To Len(MyString)
if Mid(MyString, Counter, 1) Like "*[a-z]*" = false then
MsgBox "String contains bad characters"
exit sub
end if
next
... but is there a more sophisticated 1liner solution ?
Until then, I have created a function to make it "Oneliner":
Function isPureString(myText As String) As Boolean
Dim i As Integer
isPureString = True
For i = 1 To Len(myText)
If Mid(myText, i, 1) Like "*[a-zA-Z_íéáűúőöüóÓÜÖÚŐŰÁÉÍ]*" = False Then
isPureString = False
End If
Next
End Function
If i add 1 more parameter, its also possible to define the allowed characters upon calling the function.
Ok, it seems my question was a bit of a duplicate, even though that did not pop in my search results.
So credits for #QHarr for posting the link.
The solution I can forge from that idea for my "oneliner" is:
If myText Like WorksheetFunction.Rept("[a-zA-Z]", Len(myText))=false then 'do something.
Using .rept is inspiringly clever and elegant in my oppinion.
So what is does: Multiplies the search criteria for each charater instead of looping through the characters.
EDIT:
In an overaboundance of nice and elegant solutions, the most recent leader is:
If not myText Like "*[!A-Za-z]*" then '... do something
Statistics update:
I have tested the last 3 solutions' performance:
I have pasted # in the below text strin at the beginning, at the end or nowhere.
The criteria were: "*[a-zA-Z \S.,]*"
For 100000 repetitions
text = "This will be a very Long text, with one unwanted in the middle, to be able to test the difference in performance of the approaches."
1.) Using the [!...] -> 30ms with error, 80ms if no error
2.) Using .Rept -> around 1800ms for all cases
3.) Using characterLoop+Mid -> around 3000ms if no error / 40-80ms ms if early error

Excel VBA On Error error

I am rather new at programming, and while learning Python also started experimenting with Excel VBA. I have an issue with the last one.
I have some large Excel sheets and tried to validate that data in specific columns matches data on another sheet in certain columns as they will be supposed to relate to each other by these values (and will be connected by a third value). To make this a bit more difficult, both of these columns may contain more than one value separated by "|". So, I have split these values in a list and I try to iterate through them to make sure all these values are set correctly, the connection will work fine.
All is fine as long as all is fine :) I have however an issue where there are two values in one of those columns and only one in the other. I would like this discrepancy to be noted on a sheet and then proceed to the next item.
The way that seemed to be applicable for me is to use "On Error GoTo ErrHandler", then note error on another sheet, and then user Resume to proceed.
Here is what I came up with:
For h = 0 To UBound(Split1())
For j = 1 To GetMaxRow("SpecificSheet", A)
On Error GoTo ErrHandler:
If Sheets("SpecificSheet").Cells(j, 1).Value = Split1(h) And Sheets("SpecificSheet").Cells(j, 2).Value = Split2(h) Then
DependencyOk = DependencyOk + 1
End If
Next j
Next h
ErrProceed:
Also ErrHandler is:
ErrHandler:
Sheets("Issues").Cells(x, 1) = "IssueDescription"
GoTo ErrProceed
It stops at line 2 with Subscript out of range for Split2(h) rather than moving on to ErrHandler and then ErrProceed. I have the feeling this must be something very obvious but I am just unable to get this working, and I am not able to find other way (like a try/except) in Excel VBA.
UPDATE:
Trying to clarify things a bit. The root of the issue is, that the Split2 list is shorter than Split1 - which is an issue with the input data and I'd like to capture this. I get the Split values from cells, where the values are separated by "|" characters:
CellValue = Sheets("SomeSheet").Cells(RowNumber, ColumNumber)
CellValueSplit() = Split(CellValue, "|")
And then iterate as:
For h = 0 To UBound(Split1())
So as Split1 moves on to the for example 3rd value, Split2 throws error and script stops. The best I was able to do so far was, that I let it proceed with the loop, but as this is a rather large sheet, it will fill the same error report ca. 200k times in this case, which I'd like to avoid. So I'd prefer it to proceed from after this loop once it hits out of range error, and proceed examining the next value.
Thank you for your help so far and in advance!
You have an issue with your syntax. The proper Error statement syntax is:
On Error GoTo <string>
On Error Resume Next
On Error GoTo 0
When using On Error GoTo <string> there is no ":" at the end. The ":" doesn't come into play until you create the target location. Example:
On Error GoTo Here
'// ---- Do something ---- //
Here:
'// ---- Handle the error ---- //
If you use On Error Resume Next, then you're telling the machine to ignore errors and proceed on to the next line of code.
When you useOn Error Return To 0, VBA will reset its error handling back to default. It's a good habit when using On Error Resume Next to insert On Error Return To 0 as soon as you no longer need it. On Error Resume Next has a real potential to break your code and make it behave strangely. Not to mention debugging can be a real nightmare. Check out the VBA manual from Microsoft for a more detailed explanation.
Finally, if your question is answered, you should mark it as answered.
vba-excelvbaexcel
The short and quick version is that VBA Error Handling Routine's only handle errors in the actual code execution, they do not fire when conditions expressed by the code are not met.
In your case, you do not need any error handling at all. In most cases it is actually best to avoid On Error GoTo .... There are cases where it's inevitable, but they are rare.
Try this IF THEN ELSE block:
If Sheets("SpecificSheet").Cells(j, 1).Value = Split1(h) And Sheets("SpecificSheet").Cells(j, 2).Value = Split2(h) Then
DependencyOk = DependencyOk + 1
Else
Sheets("Issues").Cells(x, 1) = "IssueDescription"
End If
Actually I have just found the issue. It was caused by a ":" left after an If statement a few rows earlier. I still don't really understand what it did, but I suggest not to reproduce it :)

What does the number in the AddChart2 VBA macro represent?

I've use my Excel 2013 to record a macro in inserting a chart, a column-clustered chart in my case. In the view code option, it shows me a line of code as below:
ActiveSheet.Shapes.Addchart2(286,xl3DColumnClustered).Select
Please help me as I cannot understand what does the number 286 represent. I know the syntax of Addchart2 is:
expression.AddChart2(Style,XlChartType,Left,Top,Width,Height,NewLayout)
If I change the "286" to "285", the chart appears with a blue background. An error comes out if the number is 100.
Can anyone kindly tell me what does the number represent?
One can also provide only the ChartType and the application will use the default style.
Set oShp = ActiveSheet.Shapes.AddChart2(XlChartType:=xl3DColumnClustered)
oShp.Chart.SetSourceData Source:=RngDta
This picture shows the default ChartStyle for all ChartTypes (excluding StockHLC and StockVOHLC)
This won't directly answer your question, but it will help you figure out what is going on.
This is pure conjecture on my part, but I would guess it's an undocumented bitfield. As you may know a bit field is just a way to use a number. So image we have a Byte variable which can be 8 bits (or flags). So in a byte we can store up to 8 values.
Example: We have field called "DaysOpen" bits 1-7 mean the store is open on that day of the week. (We'll ignore the 8th bit.) So if the store is open M-F that would be binary 0111 1100.
Then you just convert that number to decimal and we see that it's 124.
That variable is a Variant so it could be anything from a Byte to Long meaning it could be storing up to 64 different flags.
As a side note (if you are interested) you can use bit fields like so:
Option Explicit
Public Enum DayFlags
'Notice these are power of 2.
dfSunday = 1
dfMonday = 2
dfTuesday = 4
dfWednesday = 8
dfThursday = 16
dfFriday = 32
dfSaturday = 64
End Enum
Sub Example()
Dim openHours As DayFlags
'Set the flags:
openHours = dfMonday Or dfTuesday Or dfThursday
'See the binary?
MsgBox Right$("00000000" & Excel.WorksheetFunction.Dec2Bin(openHours), 8)
'Notice the order is right to left. This is call endianness.
'You can check for a specific flag like this:
MsgBox IsOpenOnDay(openHours, dfMonday) & vbNewLine & IsOpenOnDay(openHours, dfFriday)
'You can add a flag like this:
openHours = openHours Or dfFriday
MsgBox IsOpenOnDay(openHours, dfMonday) & vbNewLine & IsOpenOnDay(openHours, dfFriday)
'You can remove a flag like this:
openHours = openHours Xor dfFriday
MsgBox IsOpenOnDay(openHours, dfMonday) & vbNewLine & IsOpenOnDay(openHours, dfFriday)
End Sub
Private Function IsOpenOnDay(ByVal openHours As DayFlags, ByVal day As DayFlags) As Boolean
IsOpenOnDay = ((openHours And day) = day)
End Function
Well , I had the same situation once, and those are basically chart styles. I tried to figure out the exact numbering but then i realized that recording was a much easier way of knowing the style numbers just as you have done here.
To answer you question, record macros to know which style you want to implement in your macros.
Just checking to see if 5 years later anyone has a better answer. I sure could use an enumeration of the chart styles; I don't like putting simple numbers in my code without some explanation as to what it means. Of course, I could use a comment, but if the numbers are documented, then that means they could change.
I found a partial list: https://learn.microsoft.com/en-us/office/vba/api/excel.xlcharttype
I'm sure these numbers, plus the bitfield variations as suggested by Pillgram above to control various other chart aspects, answer the question. The possible combinations are in the thousands, so a full list would be pretty useless. Recording is still your best bet.

VBA Code in Excel randomly stops executing. No error messages occur

Essentially, I have an Updata button that takes information from two columns, in two spreadsheets (within 1 book). The overall goal of this code is to take all the values from one column, and then append the values from the other column below it.
Worksheets("Overall Flow").Range("A4:A1004").Value = Worksheets("Active").Range("A2:A1002").Value
Dim i As Integer
For i = 4 To 1004
If Worksheets("Overall Flow").Range("A" & Trim(str(i))) = "" Then
Worksheets("Overall Flow").Range("A" & Trim(str(i)) & ":A" & Trim(str(1000 + i))).Value = Worksheets("Inactive").Range("A2:A1002").Value
i = 1005
End If
Next
For some reason, the first line executes, and then finishes. When I put break points, then do step-by-step, no other steps happen afterwards.
When I run the first line individually, it appears to work fine, but not when:
Worksheets("Overall Flow").Range("A" & Trim(str(i)) & ":A" & Trim(str(1000 + i))).Value = Worksheets("Inactive").Range("A2:A1002").Value
or
Worksheets("Overall Flow").Range("A4:A1004").Value = Worksheets("Inactive").Range("A2:A1002").Value
is present aftwards.
Solution to this is very unusual.
CTRL+BREAK CTRL+BREAK CTRL+BREAK ESC
It just happened to me againg after long time, I was looking for a solution and I came here then this sequence came back to my mind and I tried.
It worked for me, I hope this will help someone.
Update: Tweaked code (now with error checking!)
Main points concerning the current code:
When copying the ACTIVE range, check for last consecutive cell used. This is faster and more effecient than a loop.
Why are you trimming a number you know will not contain spaces?
There's no need to set i = 1005, just use Exit For. This is more effecient and clear to the reader what the intention is. I don't use this in the code below since I avoided looping altogether.
Here's a different way you can do this without any looping, which I think is more clear and effecient. Try this and see if it works for you:
Sub test()
Dim lastRow As Long, offSet As Long
lastRow = Worksheets("Active").Range("A2").End(xlDown).row
'Sanity checks
If IsEmpty(Worksheets("Active").Range("A2")) = True Then offSet = 1: lastRow = 2
If lastRow > 1001 Then lastRow = 1002
Worksheets("Overall Flow").Range("A4:A" & lastRow + 2).Value = _
Worksheets("Active").Range("A2:A" & lastRow).Value
If lastRow < 1002 Then
Worksheets("Overall Flow").Range("A" & lastRow + (3 - offSet) & _
":A1004").Value = Worksheets("Inactive").Range("A2:A1002").Value
End If
End Sub
Notes:
Sanity check 1 is for if A2 is blank in the Active sheet.
Sanity check 2 is for if there are cells beyond A1002 with values in Active sheet.
This is what I am using to test your code. Since I don't know what's in the spreadsheets, I can't reproduce exactly what you're seeing so I'm first putting dummy data into the ranges.
For me it is running fine every time, and I've tried it on 2 different computers - Excel 2003, and Excel 2010.
I set a breakpoint and stepped with F8, and also Shift F8 and both worked fine.
Something may be different with your data (i.e. the first cell being copied over from the inactive sheet is blank and therefore execution stops after processing the first cell -- check that column A4 is not blank), or perhaps some memory has gotten corrupted from having Office being killed.
In a Module I have:
Sub test()
Worksheets("Active").Range("A2:A1002").Value = "active"
Worksheets("Active").Range("A5").Value = ""
Worksheets("Inactive").Range("A2:A1002").Value = "inactive"
Worksheets("Overall Flow").Range("A4:A1004").Value = Worksheets("Active").Range("A2:A1002").Value
Dim i As Integer
For i = 4 To 1004
If Worksheets("Overall Flow").Range("A" & Trim(Str(i))) = "" Then
Worksheets("Overall Flow").Range("A" & Trim(Str(i)) & ":A" & Trim(Str(1000 + i))).Value = Worksheets("Inactive").Range("A2:A1002").Value
i = 1005
End If
Next
End Sub
Have you tried the same code on another computer?
I had this issue and I tracked it down to custom VBA functions used in Conditional Formatting that was processed while application.screenupdating was still set to True.
I'm not sure how consistent this behaviour is but, when a custom VBA function is referred to in a conditional formatting rule, when the screen updates, it will not step through the code even when employing break points or the debug.assert method. Here's the breakdown of what happened:
Context:
2 open workbooks.
Conditional formatting and custom function in question were in workbook1.
The code I was attempting to execute was in workbook2.
Process
I call a procedure in workbook2.
Workbook2's procedure reaches a line executing an autofilter command.
Autofilter command triggers a screen update in all open workbooks (any command that triggers a Worksheet_Change or Worksheet_Calculate event can apply here).
Screen update processes the conditional formatting rules, including the rule in workbook1 calling workbook1's custom function.
Custom function is run in a 'silent' state (i.e. with no interaction with user, ignoring break points and "debug.assert" calls; this appears to be by design as part of the conditional formatting feature)
Custom function finishes execution and ceases all other active code execution.
I fixed my problem by adding a Application.ScreenUpdating = False line at the start to prevent screen updates and, by extension, conditional format processing (but it's best to keep custom functions away from conditional formatting to begin with).
I'm not sure if this is relevant to your situation at all but I hope it helps somebody.
It has already been mentioned in transistor1's answer, but only as a side comment.
I had a similar problem, that VBA code simply stopped executing in the middle of a function. Just before that it also jumped back a few lines of code. No Error Message was shown.
I closed all open Excel programs, and upon reopening the File everything worked fine again.
So my confirmed Answer to this problem is: Corrupted Memory, restart Excel.
Edit: after doing this, I also encountered the Problem that Visual Basic Editor crashed when I tried uncommenting a particular line. So I created a New Excel file and copied my code. Now I don't have any problems anymore.
I ran into the same problem. I had a sub routine that gave random errors throughout the code without giving error messages. By pressing F8, the code would resume.
I found someone had posted a Subroutine he called "ThatCleverDevil" I do not remember the resource or who posted it. It would warn you an error was about to occur. The routine is posted below.
I split the code into component sub-routines. The short snippits ran with no interruption or erros. I created a subroutine that called each snippit. Errors resumed.
They would run individually, but not all together.
RESOLUTION: Between called sub-routines, I ran the following line of code:
Application.Wait Second(Now) + 1
The code then ran without error.
Thanks to whomever it was that wrote ThatCleverDevil. And special thanks to the coder who wrote about Application.Wait.
Sub ThatCleverDevil()
On Error GoTo err
MsgBox "About to error"
err.Raise 12345
MsgBox "Got here after the error"
Exit Sub
err:
Stop: Resume
End Sub
Robert
VBA simply is prone to this issue. I have used it for years in corproate workflows because it is so hardcoded into lots of things, but if possible I would just consider alternatives. If this an ad-hoc project R will be faster and offer more flexibility. If this is more production oriented and meant to handle large volumes I would consider informatica.
To improve the performance I called the function DoEvents inside the loop. It solved the problem for me.

Resources