Reputation: 1257
I have a data connection in a workbook and I refresh it using VBA.
sub RefreshData()
ActiveWorkbook.Connections("LoadData1").Refresh
End Sub
The code runs without error but the data does not change or update. But when I step through the code, it works fine and the data is updated. I also tried doing a wait
.
sub RefreshData()
ActiveWorkbook.Connections("LoadData1").Refresh
Application.Wait (Now + TimeValue("00:00:20"))
End Sub
I have also tried ActiveSheet.Unprotect
, Application.ScreenUpdating = True
but to no avail.
Upvotes: 1
Views: 1637
Reputation: 1
In place of Application.Wait
use-
ScheduledTime = Now + TimeValue("0:00:15")
Application.OnTime ScheduledTime, "procedure next"
optimize TimeValue based on quantum of data/connections, etc
Upvotes: -1
Reputation: 1728
I had issues with some of my subs ending before the data had finished refreshing. If I understand correctly, that's what's happening with your sub. If so, you could try adding the line:
Application.CalculateUntilAsyncQueriesDone
Adding this line into my code directly after the refresh command worked for me.
Note: When I had the queries set as background queries, I occasionally got weird freeze/crash issues; so I would recommend turning off the background query option with any query you use the above code with.
If the simple solution doesn't work, an alternative is to add a custom class that raises an event when the refresh is finished. The downside to this solution is that you may need to rewrite existing code to be triggered by an event, instead of having an in-line refresh command.
An example of such a custom class is below. Please note that there are some assumptions built into the code -- the most prominent being that the query is set to load onto a sheet in the workbook, and refresh in the background.
To use the custom class, insert a "class module" (this is not the same as a "Module"), and copy the code from the "class code" section below into the "class module". Next, in the code module for the worksheet holding the resulting query table, add this code:
Private WithEvents queryData As QueryClass
Public Sub querySetup()
Set queryData = New QueryClass
Set queryData.QryTble = Me.ListObjects("QueryName").QueryTable
End Sub
Private Sub queryData_Refreshed(ByVal RefreshSuccess As Boolean, ByVal isEmpty As Boolean)
End Sub
(Note that this code is assuming that the class module has been renamed to "QueryClass", and that the query was named "QueryName". If you used different names, you'll need to adjust the code accordingly.)
You can put custom code in the queryData_Refreshed
sub to happen after the query has finished refreshing. Note that the sub has two indicators -- if the query refreshed successfully, and if the query is empty (did not return any records). Then, to refresh the data, just call:
queryData.Refresh 5 'optional maximum of attempts; defualt is 1
These questions may also be helpful.
Class Code
Option Explicit
'class basics from Paul Renton, https://stackoverflow.com/questions/18136069/excel-vba-querytable-afterrefresh-function-not-being-called-after-refresh-comp
Private WithEvents mQryTble As Excel.QueryTable
Private RefreshFinished As Boolean
Private RefreshSuccessful As Boolean
Private attemptCount As Long
Private attemptMax As Long
Public Event Refreshed(ByVal RefreshSuccess As Boolean, ByVal isEmpty As Boolean)
Public Property Set QryTble(ByVal QryTable As QueryTable)
Set mQryTble = QryTable
End Property
Public Property Get QryTble() As QueryTable
Set QryTble = mQryTble
End Property
Public Property Get RefreshDone() As Boolean
RefreshDone = RefreshFinished
End Property
Public Property Get RefreshSuccess() As Boolean
RefreshSuccess = RefreshSuccessful
End Property
Private Sub mQryTble_AfterRefresh(ByVal Success As Boolean)
attemptCount = attemptCount + 1
If Success Or attemptCount = attemptMax Then
RefreshFinished = True
RefreshSuccessful = Success
RaiseEvent Refreshed(Success, mQryTble.ListObject.DataBodyRange Is Nothing)
Else
mQryTble.ListObject.Refresh
End If
End Sub
Public Sub Refresh(Optional attempts As Long = 1)
If Not mQryTble.Refreshing Then
RefreshFinished = False
attemptMax = attempts
mQryTble.ListObject.Refresh
End If
End Sub
Upvotes: 2