Running a loop while debugging VBA - vba

The Problem
I am trying to debug some code, and somewhere in the middle I stopped at a breakpoint. Now I want to change some variables and run a certain loop several times.
How far did I get?
I know how to change the variables, but somehow I get stuck when trying to run the loop in the immediate window. Here is an example:
Dim i As Integer
Dim j As Integer
For i = 0 To 6
j=i ' Do something
Next i
I tried several variations of the code, but each time I get the following error:
Compile error: Next without for
Other relevant information
I tried searching but mostly found information about problems with loops, whilst I am quite sure the loop itself is fine. (Especially as I reached it before arriving at the breakpoint).
The only place I saw someone addres this situation, he reduced the loop to a single line, however to do this every time would be very impractical in my case.
I realize that I could call a function containing the loop, and then the function call would probably work, but again this feels quite impractical. So I guess it boils down to the following question.
The question
What is a practical way to run a loop whilst debugging VBA code in Excel?

There is actually a way for using loops or other multi-line statements in the Immediate Window - using a colon : to separate statements instead of a new line.
Full solution is described here.
Note that in the Immediate Window you also don't have to declare the variables using a Dim statement.
To summarize, your snippet would look something like this:
For i = 0 To 6: j=i: debug.Print i+j: Next i

I think I understand your question. You want to run a multi-line code block (i.e. the loop) in the Immediate Window. This throws errors because the Immediate Window is only intended for single lines of code.
I don't have any suggestions other than those you already mentioned. I'd recommend putting your test loop into a separate function and calling that from the Immediate Window:
Sub Test()
Dim i As Integer
Dim j As Integer
For i = 0 To 6
j=i ' Do something
Next i
End
Another option is to set several breakpoints. You can also run one line of code at a time with F8.
What is likely the preferred method (i.e., what most people actually do) is use the full power of the IDE, which includes the Immediate, Locals and Watch panes. You can change the value of most variables at runtime by direct assignment in the Immediate Pane (i=6 will do exactly what you think it should do). The IDE also allows you to set breakpoints, add watch conditions, step through code line-by-line using the F8, step through function or procedure calls using Shift+F8, stepping over (and back) through code using the mouse/cursor, and with a few exceptions, you can even add new variables during runtime.

Related

VBA Macro running too fast

It's weird that I'm finding ways to slow down my macro. Apart from Doevents and other time delay techniques, which are basically a workaround, is there a way through which we can get around the asynchronous execution. As in, I want the VBA code to behave like this:
start executing line 1>finish executing line 1>move to line 2;
Forgive if I'm wrong but currently it seems to follow:
Start executing line 1>without caring whether line 1 finished or not start executing line2
If you are calling external programs (vbs, exe) then the vba isn't getting any feedback on the process at all. It calls the programs and moves on to the next line of code (the vba doesn't know if/when the external programs finishes).
One way to slow this process down would be to put a application.wait or application.sleep between the calls, but that is also a workaround. Please post your actual code and perhaps we can troubleshoot further.
if the code is about refreshing data, use Refresh method with backgroundquery=False in a For Loop instead of RefreshAll.
For Each con In Me.Connections
con.ODBCConnection.BackgroundQuery = False
con.Refresh
Next

is there any command equivalent to readline in vba?

Is there a command equivalent to readLine of Java in VBA.
I want to use the text input in the immediate window and put it in a variable.
Is it possible?
You can't use the Immediate Window interactively. For one thing -- while a sub is running it won't accept any keyboard input. You can, however, use it to pass data to a sub or function when you invoke it, so in a sense you can "scrape" data that is there already. Something along these lines:
Sub AddNums(ParamArray nums())
Dim total As Double
Dim i As Long
For i = 0 To UBound(nums)
total = total + nums(i)
Next i
Debug.Print total
End Sub
For example:
Beyond that -- you could move the input-gathering phase to a VBScript script running in console mode, invoke it from VBA, and use either a file (which the script writes to) or perhaps the clipboard to get the data from the script after it is done running. This should be feasible, though it is probably better to find a more idiomatic (form-based) way to do it within VBA.
I am not quite sure why you need to write from Immediate Window to a variable at a runtime - is it some weird debugging practices?
Normally, if you need to take an input you end up with a form to interact with an user.
However, if you do need to write to a variable at a runtime consider the following:
Sub Main()
Dim immediateInput As String
Dim readImmediate As Boolean
Do While (readImmediate = False)
readImmediate = True
Loop
End Sub
now, set a breakpoint at the readImmediate = true line and add immediateInput to the Watch. Bring up both the Immediate Window and Watches and run the macro.
When the runtime hits the breakpoint enter the below in the Immediate Window:
immediateInput = "hello world"
Now have a look in the Watches; your immediateInput's value should be "hello world".

EPSDK.Recordset not looping until EOF (end of file)

I am currently half way through a project where I am migrating data from an ancient Adobe Workflow server using Visual Basic and COM.
I have hit a bit of a brick wall really as I am trying to perform a simple while loop that counts the number of records in a recordset, and I keep getting this error...
"An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in microsoft.visualbasic.dll
Additional information: Unspecified error"
There is little to no documentation to help me online so I am hoping there is some sort of VB wizard/veteran that can point me in the right direction.
I have set the record as a global variable like so...
Dim record As New EPSDK.Recordset
I have then tried...
Dim recCount As Integer = 0
Do Until record.EOF
recCount += 1
Loop
This...
Dim recCount As Integer = 0
Do While Not record.EOF
recCount += 1
Loop
This...
Dim recCount As Integer = 0
Do
recCount += 1
Loop Until record.EOF
And lots of other variations, but still cannot seem to source the problem. There are no code errors, nothing comes up in the console, and I just keep getting that message back.
Can anyone spot what I am doing wrong? Thanks
Ok, I've looked up the documentation for EPSDK. For those who are unaware (as I was), it's an object collection from Adobe for manipulating COM data. It's basically the most popular functionality in ADO.
MoveFirst, as its name suggests, moves to the first record in a recordset. There doesn't appear to be any such method supported by the EPSDK Recordset object. Since you can use the Move method to do the same thing, it isn't needed. In either case, you don't need to use it to move to the end of the file.
What you're doing wrong is expecting that you can increment a variable called recCount that you made up and the recordset cursor will magically move along. Doesn't happen. As you say, the doc is insubstantial, but you probably need to use MoveNext. Here's a cheat sheet you can use to look up what's supported.
Also, you need to specify a connection, open it, point the recordset to the open connection, and open the recordset. I would suggest that you familiarize yourself with ADO (NOT ADO.Net! Not the same thing), upon which this is clearly based. There's much more documentation, and it should apply fairly well. Read up on Connections and Recordsets in particular.
Now, your loops do pretty much the same thing. While Not is the equivalent of Until. However, if you put the while/until condition after the Do statement, you won't enter the loop unless the condition is met. If you put it after the Loop statement, you will always run the loop at least once. In this case, you should put "Do Until myRecordset.EOF", because then if the recordset is empty, you won't go into the loop.

Strange / unstable behaviour on CreatePivotTable()

I am writing VBA code to automate some processes in Excel and I am encountering a very strange behavior for which I have not been able to find documentation / help.
I have a procedure MAJ_GF that first executes function GF.Update, checks the result, and then launches procedure GF.Build (which basically takes the data obtained by GF.Update from different worksheets and does a bunch of stuff with it).
At some point, this "bunch of stuff" requires using a pivot table, so GF.Build contains the following line:
Set pvt = ThisWorkbook.PivotCaches.Create(xlDatabase, _
"'source_GF'!R1C1:R" & j & "C" & k).CreatePivotTable("'TCD_GF'!R4C1", "GFTCD1")
The strange behavior is this:
when I run MAJ_GF, VBA properly executes GF.Update, then launches GF.Build, and stops at the line described above complaining "Bad argument or procedure call"
when I manually run GF.Update, then manually run GF.Build, everything goes smoothly and GF.Build does what it has to do from beginning to end with no errors
even stranger, when I set a break-point on the incriminated line, run MAJ_GF then VBA pauses on the line as expected, and when I say "Continue"... it just continues smoothly and with no errors !
I turned this around and around and around, double-checked the value of every variable, and this just makes no sense.
Ideas anybody?
Few ideas come to my mind:
There's still some update going on in the background. Try DoEvents and Application.Wait before the line you mentiond
Also check, if any data connections are able to update in the background - if so disable the background refresh
Very rarely (usually in older version and when involving Charts), unhiding the Excel window (in case you used Application.Visible = False and enabling ScreenUpdating helped..
Are you using any "exotic" references/add-ins? Disable them and see if the problem persists.
Try restarting your machine
Not that I'm too optimistic that either will solve your problem - but give it a try! Best of luck!

vb.net: Jump out of exceptioned function

I am just reworking my VB6 in .NET.
I have a function that is called NonNullString(byval uAny As Object) As String
In VB6 I worked with a sqlite wrapper, and a recordset's member could be accessed by using
Dim sString$
sString = r("somefield")
(without ".Value")
I have really many of these fields, and I changed most of them to ".Value", but for some I forgot it.
An exception is therefore raised in the function NoNullString, and I am looking for a way to quickly jump out of the function in order to see what the caller was and improve the code.
F5 does not do the job.
Does anybody have any ideas?
Thank you!
Press CTRL+L to see call stack. From there you can navigate through the stack.
You can then use Set Next Statement (CTRL+F9) on the End Function of your errored function. Two times F10 to complete execution of this function. Repeat this step till you are in the scope where you think the error originated. Then, if you are on x86 (so you have Edit&Continue available), fix your code, and drag your currently executed line to the moment when this fix would occur. And then try running your function again.
Unfortunately, you cannot Set Next Statement outside of the current block function/sub, which I was going to suggest originally.