VBA Compile Error 'Wend Without While' - vba

I have a VBA macro in excel that has run fine for a while. I've been making changes with these loops already working and suddenly the code is not compiling:
Compile error: Wend without While
I have tried changing to Do While...Loop loops, but I got the equivalent
Compile error: Loop without Do
Here is the structure of my code:
'This loop is fine
While '(code for evaluation)
'code to run in loop
Wend
While '(more eval code)
'code
While '(eval code)
'code
Wend '<--This is where the compile error occurs
'code
While '(eval code)
'code
Wend
'code
Wend
Does anyone have any idea what could be the issue? (Bonus: Does the indentation of code actually matter?)

This message Wend without While usually indicates an un-terminated IF
Somewhere there may be an IF without the matching End If
(This kind of error message is a bit annoying since it hides the true error)

The real problem is that you have a method that does too many things.
You can locate the mismatched code block, and fix it - but you'd be dismissing a readability issue with an "hey it works, leave it alone" excuse.
While
'code to run in loop
Wend
' **** move to another method
While
'code
' **** move to another method
While
'code
Wend
' **** move to another method
'code
While
'code
Wend
'code
Wend
Extracting methods in VBA code can be a bit of a pain, because parameters and return values must be determined, and then the extraction point needs to be turned into a method/function call. Fortunately, there's a tool for that (disclaimer: I wrote it).

Related

How to access the previous clipboard in VBA Word?

I am writing macro where I need to paste clipboard into MS Word. When I have run my code it happens error 4605 and debugger stops on line #11.
On Error GoTo ErrHandler
Documents.Add.Content.Paste
If False Then
ErrHandler:
' Add a delay
Dim tmpStart
tmpStart = Timer
Do
DoEvents
Loop While (tmpStart + 1) > Timer
Documents.Add.Content.Paste
End If
When I check the clipboard panel in MS Word I see this:
The last item caused problem. But what I need to access is the item marked in red rectangle. So in the case that the error happens I need to get the previous clipboard in the Word's Memory. Can you tell me how to achieve it?
Edit:
So far I have found this question, which is concerned about the problem.

How to ignore a Syntax Error without correcting the code?

This is my first question at stackoverflow and I hope you can help me.
On a big work project, I have to import some VBA codes (that are written on *.txt files), test them and run them if they're working properly.
The problem is that some of that codes have Syntax errors like the one next:
Sub ExampleScript()
Dim variable as Double
MsgBox variable +
End sub
Sure, I know that the code line MsgBox variable + is going to originate an error and pop up the warning
How do I get rid of the warning? Just by ignoring it? I tried already commands like On Error Resume Next or On Error GoTo... but simply can't fix the problem
Sub ExampleScript()
On Error Resume Next
Dim variable as Double
MsgBox variable +
End sub
or
Sub ExampleScript()
On Error GoTo Debugs
Dim variable as Double
MsgBox variable +
Debugs:
End sub
Note please that my question is about simply ignore the errors (by moving forward or ending the sub), not correct them. There are a lot of them on the *.txt files and I don't pretend to correct them all. I just want to run the codes that work properly. Thank you all for your help.

Adding Control to worksheet causes "Can't execute code in break mode"

I'm trying to add a checkbox to my worksheet using code:
Sub DropCheckboxOnSheet()
ActiveSheet.OLEObjects.Add ClassType:="Forms.CheckBox.1"
End Sub
When I run this code, I do get a checkbox added to the worksheet, however I also receive the message that Excel "Can't execute code in break mode". I get that my code adds an object to the object model and that this is why it breaks, but it also offeres me the option of continuing.
How do I tell VBA to continue after adding the object?
What i've tried:
Adding DisplayAlerts=False does not work.
MSDN offers no help either:https://msdn.microsoft.com/en-us/library/office/gg264133.aspx
I am not sure this is the safest solution but you will not get a error since adding "End" kills all macros. The only time i ever really use it is on progressbars. I would dig harder on the real issue using "On error resume next" is a bandaid. If you do use it make sure to restore your default error handling with "On error goto 0".
Sub DropCheckboxOnSheet()
ActiveSheet.OLEObjects.Add ClassType:="Forms.CheckBox.1"
End
End Sub
e.g.
Sub DropCheckboxOnSheet()
On error resume next
ActiveSheet.OLEObjects.Add ClassType:="Forms.CheckBox.1"
On error goto 0
End Sub
Changing the name of the sub might fix your issue. If you have the same sub in another open workbook it could be throwing the error.

Cannot run the macro

I have encountered a problem in the macro below
Sub RefreshAction()
Range("b7").Select
Application.Run "RefreshCurrentSelection"
Application.OnTime (Now() + TimeValue("00:00:05")), "thisworkbook.Action"
End Sub
The cell refreshes when I run the macro the first time but I get the error message immediately after
Message: Cannot run the macro "C\Desktop\XYZ.xlsm'!thisworkbook.Action'. The macro may not be available in this workbook or all macros may be disabled.
I have already gone through "Trust Center->Trust Center Settings->Macro Settings->Enable all macros and it didn't work.
The "Trust access to VBA project object model" box is also clicked.
First of all, here is a snapshot of the error you get when you attempt to run OnTime from a worksheet (not a module) as I will explain. I was getting this error too and trying to figure out why.
It looks like a security error, but in this case it isn't exactly a normal security error.
To run code on a timer you have to add it to a VBA module.
Go to the VisualBasic editor and right click the VBAProject (book).
In Excel it looks like the following:
Once the module is added you add your timer code there.
Since you want to call RefreshAction every 5 seconds you would do something like the following:
Sub StartProcess()
Debug.Print Now()
Application.OnTime Now() + TimeValue("00:00:05"), "RefreshAction", Schedule = True
End Sub
Sub RefreshAction()
Application.EnableEvents = True
Debug.Print Now() + TimeValue("00:00:05")
Application.OnTime Now() + TimeValue("00:00:05"), "RefreshAction", Schedule = True
End Sub
I'll let you add the code that you want it to do each time in the RefreshAction subroutine.
Here's what it will look like in the Module. Make sure yours shows that it is in a module as it does in the image:
Also, I found it to be quite flaky. If you have anything even slightly wrong in the OnTime call it will fail silently. Copy my code (I tested it) and try it first. Once it runs, just add your code to the RefreshAction sub.
StartProcess()
Run the StartProcess to start the thing going.
Additionally Odd Thing
After I added that Module, I still had my code in the Worksheet and I went back and attempted to run it to see the error again and the odd thing is that once the code is in the Module you won't get the error from the Worksheet any more. It's probably referencing the code in the Module now.
See the absolute reference for more details : CPearson OnTime
First issue, you need to store the time that you'll input in your OnTime method to be able to stop it. (Here I declared a Public TimeToRun As Date)
Second Point To use the OnTime method continuously, you need to reset the timer at the end of your timed procedure (here RefreshAllStaticData).
So your whole code should look like this :
Public TimeToRun As Date 'so that TimeToRun can be used in both the functions
Sub RefreshAction()
Range("b7").Select
Application.Run "RefreshCurrentSelection"
DoEvents
'Store the next date of execution in TimeToRun
TimeToRun = Now() + TimeValue("00:00:05")
'Launch the next OnTime
Application.OnTime TimeToRun, "RefreshAllStaticData"
End Sub
Sub RefreshAllStaticData()
'--++-- Place your code here, as it is now --++--
'----Call RefreshAction to reset the OnTime method
'---------to another 5 seconds and keep "looping"
RefreshAction
End Sub
Sub Kill_OnTime()
'Launch this to stop the OnTime method
Application.OnTime _
earliesttime:=TimeToRun, _
procedure:="RefreshAllStaticData", _
schedule:=False
End Sub
A different but related cause of this error can be the string-length limitation of the OnTime method's Procedure parameter's argument. See my post at: Getting around the Max String size in a vba function?

why Excel session has to be killed from Windows Task Manager on VBA error

I have a excel book with VBA. When an error is triggered, I try to close the entire Excel app. But I find the Excel session is still running in Windows Task Manager. So I have to kill the session before I can properly reboot the app and run the VBA program.
How can I handle errors so that even when there is an error I still can run the VBA program without killing and rebooting Excel itself?
At the top of your sub/function write
'ErrHandler is a label we put at the bottom of our code section.
On Error Goto ErrHandler
and at the bottom of the function/sub
Exit Function
ErrHandler:
'Do something here if there is an error
'For Example
Msgbox(Err.Description)
End Function
or
Exit Sub
ErrHandler:
'Do something here if there is an error
'For Example
Msgbox(Err.Description)
End Sub
Note that you have to put the Exit statement or you will enter the code block at the end of the execution
The err object is used to get information about the error in the error section of the sub/function. You can use this to do different things based on the type of error.
eg.
Select Case err.Number
Case 13
Msgbox("Type Mismatch, macro will continue")
'Go back to the point of the error and resume code execution..
Resume Next
Case Else
Msgbox("A fatal error has occurred. Macro will end " & err.Description)
End Select
Nice reference for catching specific error codes.
http://www.mcoffice.com/faq/edi/errors.html
if you have given the user control over the application with the following lines
xlApp.Visible = True
xlApp.UserControl = True
it will not go away, else Ending the sub or function should release the errant process