VBA While Loop Trouble (Should be easy fix) [duplicate] - vba

The code below is VBA for Excel. I am using the Visual Basic editor that comes with Excel 2007.
Dim counter As Integer
counter = 1
While counter < 20
counter = counter + 1
end while '<- the compiler is complaining about this statement
The code doesn't compile. Above the code I have only declarations. According to MSDN this should work but it doesn't. What has happened?

While constructs are terminated not with an End While but with a Wend.
While counter < 20
counter = counter + 1
Wend
Note that this information is readily available in the documentation; just press F1. The page you link to deals with Visual Basic .NET, not VBA. While (no pun intended) there is some degree of overlap in syntax between VBA and VB.NET, one can't just assume that the documentation for the one can be applied directly to the other.
Also in the VBA help file:
Tip The Do...Loop statement provides a more structured and flexible way to perform looping.

VBA is not VB/VB.NET
The correct reference to use is Do..Loop Statement (VBA). Also see the article Excel VBA For, Do While, and Do Until. One way to write this is:
Do While counter < 20
counter = counter + 1
Loop
(But a For..Next might be more appropriate here.)
Happy coding.

Related

Dynamically select Excel cells with VB .Net in a VS 2010 project

I'm using Visual Studio 2010, to create a project from a Excel Workbook template. VS2010 already gives me a workbook with one worksheet. I added another one. The project consist of the following files:
ThisWorkbook.vb
Sheet1.vb
Sheet2.vb
Each file consist of class for each object: Sheet1.vb has its Sheet1 class, Sheet2.vb Sheet2 class and so on.
From MSDN help and another sources, I understood I can access from on vb file, or another class, the other class objects using Globals statement:
Me.Range("A10").Value = "Validation time:"
Me.Range("B10").Value = ValidationTime_T1.Item(ValidationTime_T1.Count - 1) - ValidationTime_T0.Item(ValidationTime_T0.Count - 1)
Dim x As Double
Dim rowOffset As Integer
rowOffset = 3
For x = 0 To JobCounter
Globals.Sheet2.Cells(x + rowOffset, 1) = x
Globals.Sheet2.Cells(x + rowOffset, 2) = ASy_Start_Mem.Item(x)
Globals.Sheet2.Cells(x + rowOffset, 3) = WSZ_Start_Mem.Item(x)
Globals.Sheet2.Cells(x + rowOffset, 4) = WSZ_Start_Pk_Mem.Item(x)
Globals.Sheet2.Cells(x + rowOffset, 5) = PFU_Start_Mem.Item(x)
As you can see, I move data from one sheet to another, or put data that is in memory to sheet2 from sheet1.
So far, so good. There were not that many issues I could not solve by my self.
I think is good to point out here that my background is C, C++, Perl and VBA in the last 4 years, so I'm struggling with VB since quite a bit already, I find .Net more useful, until I had to use it with Excel, it is giving me a hard time.
Now, I need to select specific cells base on positions and it is not always the same position so I need to select them dynamically, NO HARD CODED, as I have found in MSDN, forums, StackOverFlow and different sites, the solution they give is to use:
Globals.Sheet2.Range("C7").Select()
And yeah, that's fine for specific cells for which you use a string to select.
The problem is that I need to select different cells every time depending on the each day data, andt I don't know how to do it with Range. In the previous code you can see I used Cells for that.
I've tried:
Globals.Sheet2.Range(Globals.Sheet2.Cells(2, 2), Globals.Sheet2.Cells(6, 3)).Select()
Because one of Range definitions states that I can receive as parameter two Cells objects, but gives an error. I've tried creating Range objects for the cell positions. I have used Object object with CType, and it also fails.
If anyone could help how I can dynamically select cells, either with Range or Cells, or both, or if you have another solution, I will gladly appreciate it.
First thanks to TnTinMn, for replying, and I apologize for the late response again, it's been crazy at work.
Well, I found the solution thanks to your comment.
There seems to be a known issue with Excel.Interop and Visual Basic .Net called "two dots".
Normally, when you go programming VB in VS write a few letter and IntelliSense prompts you with what may be available (property, method or object) then you enter a dot and another list comes up showing you what’s available, once you chose the previous two categories you either assign them to a variable or object, or given them a value. But you can still put another dot and get another list, here is where VB get messed up and not working, probably VS will let you put whenever amount of dos, but at runtime you'll get the error I got.
Hope an experienced StackOverflow fellow can explain this much better.
So the solution for the Select method:
First you need to make the sheet active, then you can use the Select method, as TnTinMn predicted the error was with the Select method.
Globals.Sheet2.Activate()
Globals.Sheet2.Range(Globals.Sheet2.Cells(2, 2), Globals.Sheet2.Cells(6, 3)).Select()
And now Select method does not throw the runtime error.
With the previous code you can now have an option to go through any cell without hard coding.
The following can also be used to store data ranges from different section, to later use in chart for example:
Dim dataX As Excel.Range
Dim dataY As Excel.Range
Dim dataRange As Excel.Range
dataX = Globals.Sheet6.Cells(xRow, XColumn)
dataY = Globals.Sheet6.Cells(yRow, yColumn)
dataRange = Application.Union(dataX, dataY)
Thank you and hope this help someone.

QlikView ActiveDocument.NoOfSheets not working

I created a new qlikview doc and in the script I just wanted to know the no of sheets. So I wrote
iNumSheets = ActiveDocument.NoOfSheets;
iVar = 2;
FOR t = 0 to iNumSheets
iVar = 4;
NEXT
I get the following error
Script line error:
FOR t = 0 to iNumSheets
What am I missing? I am a programmers for years and these simple things often drive me nuts in qlikview. Please help.
It appears that you are using the Load Script editor for your code, rather than the Module Editor.
You can access the module editor using Ctrl+M.
You will need to remove the semicolons at the end of your code lines and also enclose your code with Sub and End Sub if you are using VBScript as the lanuage for the code.
Since the for loop counter is starting from 0 you'll have to do iNumSheets - 1 i.e., for t = 0 to iNumSheets - 1.
You can try the below code to loop over the visible sheets which avoids the additional step.
Code
for i = 0 to ActiveDocument.NoOfSheets - 1
your code...
next

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.

Running a loop while debugging 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.

VBA: Why do people include the variable's name in a "Next" statement?

I have always written my For-loops like this:
For foo = 1 to 10
' do something
Next
However, when I read code snippets online, people always do this:
For foo = 1 to 10
' do something
Next foo
I have not noticed any difference between the two, and I can't find any documentation on next statement is more desirable. What is the difference between those two (if any)?
The counter after the Next statement is optional. It used to be required in BASIC-derived languages, but this is no longer the case in VBA.
You can check the VBA reference:
If you omit counter in a Next statement, execution continues as if counter is included. If a Next statement is encountered before its corresponding For statement, an error occurs.
The reason people still add the counter it to increase readability.
It's for when you have multiple for loops.
For example,
For i to j
For k to l
next k
next i
Otherwise, the next is ambiguous. It's not absolutely necessary, as the loop will still work without it, but it's just good practice to have it marked for the sake of anyone else reading your code.