I have a MS Access database that displays an error message about a SQL syntax error on launch. "Syntax Error in query. Incomplete query clause." It also shows another error a few seconds after I hit "OK" on the first one.
Here's the two errors: https://imgur.com/a/PesjIFk
But it doesn't tell me where the syntax error is. There are SQL statements in a bunch of different places all over this project. This is a really large project and it wouldn't be practical to just look through all the code hoping that I notice an error someplace. How can I find out where this error is?
EDIT: Ok, so apparently you have to have a keyboard that has a "Break" key on it in order to even find where the error is. Wow. Fortunately I happen to have one. Here's the code that Access takes me to if I press break when I see the error message. This code is for a subform of another form. It highlights the first line (Private Sub Form_Current()).
Private Sub Form_Current()
If NumEnums > 0 Then
CurrentEnum = val(Nz(bit_value_edit.value)) 'Update CurrentEnum to the currently selected enum
Call UpdateEnumsLabel(Me.Parent![enums label]) 'Update label
End If
End Sub
...and here's UpdateEnumsLabel():
Public Sub UpdateEnumsLabel(ByRef label As Control)
If NumEnums > 0 Then
label.Caption = "Enums: " & CurrentEnum & "/" & NumEnums
Else
label.Caption = "Enums: 0"
End If
End Sub
The definition for CurrentEnum:
Public CurrentEnum, CurrentPort, CurrentFile, CurrentGroup As Long
I'm thinking that this error is unrelated to the code in Form_Current(), but Access is highlighting that line because the error happens when the form is opened. But the form doesn't contain anything that uses a query, so I'm confused as to what query Access has a problem with.
When the error Message pops up, Use Control+Break. It will take you to the line causes the issue.
You should also open a module and form the debug option in the VBA editor select "Compile All Modules"
And since it appears to happening on open/load, you can check both the macros and the main modules to find anything that triggers on AutoExec.
Often ctrl-break will hit the line where you errored out. However, in the case of multiple “events”, and code without error handling, then often the error occurs in the routine that called the code, not the actual code that caused the error.
What I would do launch the application (hold down the shift key to prevent any start up code, or forms running).
Now that you launched the application, but without forms or code running, then check for an autoexecc macro (if there is one, check what code it attempts to run).
If there not an autoexec macro in use, then check under file->options->current database. In this view, you can look/see/determine what the name of the start-up form is.
Once you determined the start-up form (or start up module/code) called from autoexec macro, then you can simply add a blank code module, and place in your code the SAME command that is used to start your application.
So let’s assume no autoexec macro, and you determine that the start-up form is frmMain.
So now, we can launch the application (hold down shift key to prevent any start up code from running). Now, type into a new “test” standard code module the following code:
Sub MyGo
Stop
Docmd.OpenForm "frmMain"
End sub
So you type in above code, hit ctrl-s to save the above code. Now with your cursor anyplace inside of the above code, you simply hit F5 to run.
At this point you hit/stop on the “stop” command in the debugger. At this point, you then can hit f8 to step to the next line of code. If the form in question calls other code etc., you still be able to single step, and “eventually” you hit the line which causes the error.
While the application may be large, a simple look at the start up forms (and huts then the start-up code) means that you ONLY really need to trace and look at the start up code – not the whole application.
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
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.
I have a sub that calls on ActiveWorkbook.RefreshAll to bring new data in from an XML source, and then performs multiple modifications to it. The problem is that not enough time is given for the RefreshAll command to finish, so the following subs and functions end up not executing correctly, which result in repeated rows not being correctly erased.
I have tried using Application.Wait and the Sleep function, but they seem to pause the refresh process too. I simply want the rest of the code to wait until the refresh process finishes before executing the rest of the code.
Any ideas on how to implement this? Right now I was only able to fix it by not calling on RefreshAll, which gives me the idea of implementing a second flow to be executed afterwards, but that's not a good workaround.
Please let me know if any of this wasn't clear. Thanks
EDIT
So I tried a few suggestions from the posts below, and this is what I was able to come up with.
Doing a "record macro" and then UNCHECKING the "Enable background refresh" in the table properties did not result in anything. I did a refresh as well afterwards. This was the result of the recorded macro:
With ActiveWorkbook.Connections("XMLTable")
.Name = "XMLTable"
.Description = ""
End With
ActiveWorkbook.Connections("XMLTable").refresh
The class ActiveWorkbook.Connections does NOT have a BackgroundQuery option so that I can set it to False. Any ideas?
Just to be clear. This is an XML file hosted on a website which Excel goes and imports into a table. I then call that data into a pivot and other things. The goal here is to allow the import process from the website to the table to finish BEFORE executing any other commands.
Thanks
EDIT2:
After a little more research, I have found this page: http://www.mrexcel.com/forum/excel-questions/564959-execute-code-after-data-connection-refresh-finished.html
It appears that an XML type of connection does not have a BackgroundQuery boolean. That option is only available for ODBC and OLEDB connections, which are types xlConnectionTypeODBC and xlConnectionTypeOLEDB, respectively. The XML connection I am using is of type xlConnectionTypeXMLMAP which does not have a BackgroundQuery option.
Does anyone have any idea on where to go from here? The only solution I have in mind right now is to make two seperate macro buttons on the excel sheet, one for refreshing and one for data modification, but I'd rather keep that option to the very last.
I had the same issue, however DoEvents didn't help me as my data connections had background-refresh enabled. Instead, using Wayne G. Dunn's answer as a jumping-off point, I created the following solution, which works just fine for me;
Sub Refresh_All_Data_Connections()
For Each objConnection In ThisWorkbook.Connections
'Get current background-refresh value
bBackground = objConnection.OLEDBConnection.BackgroundQuery
'Temporarily disable background-refresh
objConnection.OLEDBConnection.BackgroundQuery = False
'Refresh this connection
objConnection.Refresh
'Set background-refresh value back to original value
objConnection.OLEDBConnection.BackgroundQuery = bBackground
Next
MsgBox "Finished refreshing all data connections"
End Sub
The MsgBox is for testing only and can be removed once you're happy the code waits.
Also, I prefer ThisWorkbook to ActiveWorkbook as I know it will target the workbook where the code resides, just in case focus changes. Nine times out of ten this won't matter, but I like to err on the side of caution.
EDIT: Just saw your edit about using an xlConnectionTypeXMLMAP connection which does not have a BackgroundQuery option, sorry. I'll leave the above for anyone (like me) looking for a way to refresh OLEDBConnection types.
Though #Wayne G. Dunn has given in code. Here is the place when you don't want to code. And uncheck to disable the background refresh.
DISCLAIMER: The code below reportedly casued some crashes! Use with care.
according to THIS answer in Excel 2010 and above CalculateUntilAsyncQueriesDone halts macros until refresh is done
ThisWorkbook.RefreshAll
Application.CalculateUntilAsyncQueriesDone
You must turn off "background refresh" for all queries. If background refresh is on, Excel works ahead while the refresh occurs and you have problems.
Data > Connections > Properties > (uncheck) enable background refresh
Here is a solution found at http://www.mrexcel.com/forum/excel-questions/510011-fails-activeworkbook-refreshall-backgroundquery-%3Dfalse.html:
Either have all the pivotcaches' backgroundquery properties set to False, or loop through all the workbook's pivotcaches:
Code:
For Each pc In ActiveWorkbook.PivotCaches
pc.BackgroundQuery = False
pc.Refresh
Next
this will leave all pivotcaches backgroundquery properties as false. You could retain each one's settings with:
Code:
For Each pc In ActiveWorkbook.PivotCaches
originalBGStatus = pc.BackgroundQuery
pc.BackgroundQuery = False
pc.Refresh
pc.BackgroundQuery = originalBGStatus
Next
This may not be ideal, but try using "Application.OnTime" to pause execution of the remaining code until enough time has elapsed to assure that all refresh processes have finished.
What if the last table in your refresh list were a faux table consisting of only a flag to indicate that the refresh is complete? This table would be deleted at the beginning of the procedure, then, using "Application.OnTime," a Sub would run every 15 seconds or so checking to see if the faux table had been populated. If populated, cease the "Application.OnTime" checker and proceed with the rest of your procedure.
A little wonky, but it should work.
Try executing:
ActiveSheet.Calculate
I use it in a worksheet in which control buttons change values of a dataset. On each click, Excel runs through this command and the graph updates immediately.
This worked for me:
ActiveWorkbook.refreshall
ActiveWorkbook.Save
When you save the workbook it's necessary to complete the refresh.
Here is a trick that has worked for me when some lines of VBA code have trouble executing because preceding lines haven't completed doing their thing. Put the preceding lines in a Sub. The act of calling the Sub to run those lines may help them finish before subsequent lines are executed. I learned of this trick from https://peltiertech.com/ and it has helped me with timing issues using the Windows clipboard.
If you're not married to using Excel Web Query, you might try opening the URL as a separate Workbook instead. Going that route lets you work on the resulting data once the web request completes, just like if you turn off "Enable background refresh."
The nice thing is though, Excel displays a progress bar during the request, instead of just freezing up / showing a load message in the destination cell.
See my answer on this question: How can I post-process the data from an Excel web query when the query is complete?
The tradeoff of that approach is you have to manage processing the data you get back yourself - Excel won't put it in a given destination for you.
We ended up going this route after we tried something pretty similar to what you seem to have been doing.
I was having this same problem, and tried all the above solutions with no success. I finally solved the problem by deleting the entire query and creating a new one.
The new one had the exact same settings as the one that didn't work (literally the same query definition as I simply copied the old one).
I have no idea why this solved the problem, but it did.
I tried a couple of those suggestions above, the best solution for me was to disable backgroundquery for each connection.
With ActiveWorkbook.Connections("Query - DL_3").OLEDBConnection
.BackgroundQuery = False
End With
For Microsoft Query you can go into Connections --> Properties and untick "Enable background refresh".
This will stop anything happening while the refresh is taking place. I needed to refresh data upon entry and then run a userform on the refreshed data, and this method worked perfectly for me.
I have had a similar requirement. After a lot of testing I found a simple but not very elegant solution (not sure if it will work for you?)...
After my macro refresh's the data that Excel is getting, I added into my macro the line "Calculate" (normally used to recalculate the workbook if you have set calculation to manual).
While I don't need to do do this, it appears by adding this in, Excel waits while the data is refreshed before continuing with the rest of my macro.
For me, "BackgroundQuery:=False" did not work alone
But adding a "DoEvents" resolved problem
.QueryTable.Refresh BackgroundQuery:=False
VBA.Interaction.DoEvents
I know, that maybe it sounds stuppid, but perhaps it can be the best and the easiest solution.
You have to create additional Excel file. It can be even empty.
Or you can use any other existing Excel file from your directories.
'Start'
Workbooks.Open("File_where_you_have_to_do_refresh.xlsx")
Workbooks("File_where_you_have_to_do_refresh.xlsx").RefreshAll
Workbooks.Open("Any_file.xlsx)
'Excell is waiting till Refresh on first file will finish'
Workbooks("Any_file.xlsx).Close False
Workbooks("File_where_you_have_to_do_refresh.xlsx").Save
or use this:
Workbooks("File_where_you_have_to_do_refresh.xlsx").Close True
It's working properly on all my files.
What I've done to solve this problem is save the workbook. This forces it to refresh before closing.
The same approach works for copying many formulas before performing the next operation.
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!