Auto-updating Power Query Connection via VBA when closing a file - vba

I have an excel workbook (which is updated daily) to which I have established a couple power query connections, they look like this:
IMG
When clicking the little button to update the connection it works fine, updates, new lines are added, changes in data happen. I've then set out to execute this update through VBA in an automatic fashion when the data source files finishes being worked on and is closed (In a manner that would make opening the file with the queries and manually updating them unnecessary), following are examples of what I've tried(All using the "Workbook_BeforeClose" event):
Method 1 (Unsuccessful):
Sub Workbook_BeforeClose(cancel As Boolean)
CarryOn = MsgBox("Update connections? (May take a minute)", vbYesNo, "Update connections")
If CarryOn = vbYes Then
Dim strFilename As String: strFilename = "R:\filepath\Querydestination.xlsm"
Dim QD As Workbook 'QD = Query Destination
Set QD = Workbooks.Open(Filename:=strFilename)
QD.RefreshAll
QD.Connections("Query - Database").Refresh
QD.Connections("Query - Support$_FilterDatabase").Refresh
QD.Save
QD.Close
ThisWorkbook.Save
Beep
MsgBox "Connections updated!"
End If
End Sub
I've since found the code from the first answer of the following post:
Auto-updating Power Query Connection via VBA
The code currently looks like this:
Sub Workbook_BeforeClose(cancel As Boolean)
CarryOn = MsgBox("Update connections? (May take a minute)", vbYesNo, "Update connections")
If CarryOn = vbYes Then
Application.DisplayAlerts = False
ThisWorkbook.SaveAs Filename:= _
"R:\filepath\Database.xlsb" _
, FileFormat:=50
Dim strFilename As String: strFilename = "R:\filepath\Querydestination.xlsm"
Dim QD As Workbook 'QD = Query Destination
Set QD = Workbooks.Open(Filename:=strFilename)
Dim con As WorkbookConnection
Dim Cname As String
For Each con In ActiveWorkbook.Connections
If Left(con.Name, 8) = "Query - " Then
Cname = con.Name
With ActiveWorkbook.Connections(Cname).OLEDBConnection
.BackgroundQuery = False
.Refresh
End With
End If
Next
QD.Save
QD.Close
ThisWorkbook.Save
Beep
MsgBox "Connections updated!"
Application.DisplayAlerts = True
End If
End Sub
Here's the problem: I've tried Refresh_all, Update connections, Updtade individual connection by name and a bunch of other stuff, only the method in the link and shown in the code above has worked. Sometimes it hiccups in the .Refresh line but thats it. I works on my machine, when opening the Query Destination file new lines and changes are there, without the need to manually open the file and hit the "Refresh" or "Refresh all" buttons.
The only matter is: the code runs smoothly sometimes, but sometimes it doesn't and throws an error: [IMG] [IMG].
I really don't know what is causing it, the queries destination workbook is not open and nobody is using it, I've made sure of that. How to stop this error from occuring?

Related

continue if the workbook is already open

Hello I am working on "Packing list Form (PL)" have a set of codes which opens a "Tracing Form", and copy whatever that is on there to "Packing list Form (PL)"
but when I run the code the second time, "Tracing Form" is already open,
so it prompts me saying
""Tracing Form" is already open. reopening will cause any changes you made to be discarded. do you want to reopen "Tracing Form"?"
I want it to say No and continue with the rest of the code !!
please help...
here's part of the code that's relevant
Set PL = Workbooks("PACKING LIST FORM").ActiveSheet
userprofile = Environ$("userprofile")
Workbooks.Open userprofile & "\Dropbox\Tissue Tracing Form"
Set tracingform = Workbooks("Tissue Tracing Form.xlsx").Worksheets("2018_1")
ActiveWindow.WindowState = xlMinimized
'execution
from_lastrow = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).row
.
.
.
.
The function below allows you to check if a workbook is already open and assign xRet a boolean value, you can then use that within a case to run the rest of your code or open the workbook and then run the rest of your code. This will avoid you trying to open the workbook when it is already open and so you wont get that pop up message.
Sub CheckExcelOpen()
Dim myPath As String
Dim xRet As Boolean
xRet = IsWorkBookOpen(Tissue Tracing Form.xlsx)
If xRet Then
'YOUR CODE WHEN ALREADY OPEN
Else
Workbooks.Open (TissueTracingFullFilePath) 'action needs the full file path to open
'YOUR CODE ONCE OPEN
End If
End Sub
The function-
Function IsWorkBookOpen(Name As String) As Boolean
Dim xWb As Workbook
On Error Resume Next
Set xWb = Application.Workbooks.Item(Name)
IsWorkBookOpen = (Not xWb Is Nothing)
End Function
I hope this helps

Excel vba, Opening new Application: Microsoft Excel is waiting for another application to complete an OLE action

I have the following vba code. It creates new Excel application and uses it to open a file. Then it MsgBoxes some cell's value in this file.
Sub TestInvis()
Dim ExcelApp As Object
Set ExcelApp = CreateObject("Excel.Application")
Dim WB As Workbook
Set WB = ExcelApp.Application.Workbooks.Open("Y:\vba\test_reserves\test_data\0503317-3_FO_001-2582480.XLS")
Dim title As String
title = WB.Worksheets(1).Cells(5, 4).Value
MsgBox (title)
WB.Save
WB.Close
ExcelApp.Quit
Set ExcelApp = Nothing
End Sub
The problem is that after MsgBoxing it slows down and eventually gives a Microsoft Excel is waiting for another application to complete an OLE action window. Why does it do this? It's not like there are any hard commands being implemented. And how should I deal with it?
This happens because the Excel instance in ExcelApp is waiting for User Input, most likely.
You can try to add ExcelApp.DisplayAlerts = False to skip any pop-ups that might be there.
Also, while troubleshooting add the line ExcelApp.Visible = True so you can see what's going on in the second instance and troubleshoot there.
I encountered this problem in the following situations:
An alert was opened by the Application Instance and it was awaiting user input.
While opening a file, it was coming up with some message about a crash when the file was previously opened and whether I wanted to open the saved version or the in memory version (although this should happen before the msgBox)
If you run the code multiple times and it crashes, it might have the file open as read only since there's another hidden instance of Excel that locked it (check your task manager for other Excel processes)
Rest assured that in any case the problem is not with your code itself - It runs fine here.
Code that works for me.
You can select the file from FileDialog. In comments You have code that close the workbook without saving changes. Hope it helps.
Option Explicit
Sub Import(Control As IRibbonControl)
Dim fPath As Variant
Dim WB As Workbook
Dim CW As Workbook
On Error GoTo ErrorHandl
Set CW = Application.ActiveWorkbook
fPath = Application.GetOpenFilename(FileFilter:="Excel file, *.xl; *.xlsx; *.xlsm; *.xlsb; *.xlam; *.xltx; *.xls; *.xlt ", Title:="Choose file You want to openn")
If fPath = False Then Exit Sub
Application.ScreenUpdating = False
Set WB = Workbooks.Open(FileName:=fPath, UpdateLinks:=0, IgnoreReadOnlyRecommended:=True)
Set WB = ActiveWorkbook
MsgBox("File was opened.")
'Application.DisplayAlerts = False
'WB.Close SaveChanges:=False
'Application.DisplayAlerts = True
'MsgBox ("File was closed")
Exit Sub
ErrorHandl:
MsgBox ("Error occured. It is probable that the file that You want to open is already opened.")
Exit Sub
End Sub
None of these methods worked for me. I was calling a DLL for MATLAB from VBA and a long simulation would pop up that Excel was waiting on another application OLE action, requiring me to click it off for the routine to continue, sometimes quite a few times. Finally this code worked (saved in a new module): https://techisours.com/microsoft-excel-is-waiting-for-another-application-to-complete-an-ole-action/
The way I used it is a little tricky, as the directions don't tell you (here and elsewhere) which causes various VBA errors, so I add to the description for what works in Excel 365:
Create a new module called "ToggleOLEWarning" (or in any new module, important!) which only contains the following code:
Private Declare Function CoRegisterMessageFilter Lib "ole32" (ByVal IFilterIn As Long, ByRef PreviousFilter) As Long
Public Sub KillOLEWaitMsg()
Dim IMsgFilter As Long
CoRegisterMessageFilter 0&, IMsgFilter
End Sub
Public Sub RestoreOLEwaitMsg()
Dim IMsgFilter As Long
CoRegisterMessageFilter IMsgFilter, IMsgFilter
End Sub
Then in your main function, just decorate the long running OLE action with a couple lines:
Call KillOLEWaitMsg
'call your OLE function here'
Call RestoreOLEwaitMsg
And it finally worked. Hope I can save someone the hour or two it took for me to get it working on my project.

VBA code restarting halfway through without error message

I have the below code it seems to work fine however halfway through it, it stops and restarts when I am debugging the code.
When it restarts is does not show any error message. Does anyone know why my code is doing this?
Sub ExportPICs()
If FileIsOpen("U:\FBS\PROJECTS_TEAM\MI\Sean's Projects\PICS and Benefits\Pics & Benefits upload file.xlsm") Then
MsgBox "That file's open, or doesn't exist - do something else."
Exit Sub
End If
Sheets("Post Implementation Costs").Visible = True
Sheets("Post Implementation Costs").Activate
Sheets("Post Implementation Costs").Unprotect Password:="Projects123"
Dim Tracker As String
Tracker = ThisWorkbook.Name
Dim wkbk As Excel.Workbook
Set wkbk = Workbooks.Open(Filename:= _
"U:\FBS\PROJECTS_TEAM\MI\Sean's Projects\PICS and Benefits\Pics & Benefits upload file.xlsm") '***********CODE RESTARTS HERE WITHOUT ERROR MESSAGE
Dim pics As String
pics = Dir("U:\FBS\PROJECTS_TEAM\MI\Sean's Projects\PICS and Benefits\Pics & Benefits upload file.xlsm")
Workbooks(Tracker).Activate
Sheets("Post Implementation Costs").Activate
Dim rng As Range
Dim CountTrue As Long
Set rng = Range("D16:D100")
CountTrue = Application.WorksheetFunction.CountIf(rng, "PIC")
If CountTrue > 0 Then
Rows("19:" & (CountTrue + 18)).EntireRow.Copy
End If
End Sub
If you have any code in the Workbook Open Event in "Pics & Benefits upload file.xlsm" that would do the Loop.
Try Application.EnableEvents = False
before
Dim wkbk As Excel.Workbook
Set wkbk = Workbooks.Open(Filename:= _
"U:\FBS\PROJECTS_TEAM\MI\Sean's Projects\PICS and Benefits\Pics & Benefits upload file.xlsm")
And after that you can activate it again via Application.EnableEvents = True
This code stops Excel event handlers from being called. Setting it to false is usually done because the effect of the event handler is undesirable or to prevent an infinite loop.
I have discovered too that with some statements the Step command doesn't step but lets all the following code run. To avoid this, set a breakpoint at the line following where the step gets confused.

Excel VBA: Waiting for another application to complete an OLE action when macro tries to open another workbook

A little background to the title: I've written a macro that gets called on workbook open. It opens a [shared] workbook on a shared directory and pulls in some information to the workbook the user is using.
Any user working with this sheet already has the shared directory mapped to their computer (and the macro finds the correct drive letter).
I've tested this worksheet multiple times with users in my office. I've also tested it and had two people open the workbooks simultaneously to confirm that the macros for both users are able to pull data from the shared workbook concurrently.
So far, I've had no issues.
This sheet then got rolled out to multiple other users in my company. All in all, about 40 people are expected to use this sheet (not necessarily at the same time.. just in total).
One of the users is located in Poland (I'm located in London).
When he opens the workbook, he gets a 'Microsoft Excel is waiting for another application to complete an OLE action' notification. The notification comes with an 'OK' button. Pressing this button seems to have no effect and the workbook effectively hangs on this notification.
I'm having a lot of trouble resolving this problem as I have not been able to replicate it. Does anyone have an idea why this would come up? Code below:
Sub PreliminaryDataImport()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim x As Variant
Dim usename As String
usename = Environ("USERNAME")
Dim xlo As New Excel.Application
Dim xlw As New Excel.Workbook, wkbk As New Excel.Workbook
Dim xlz As String, regions As String
Dim LRow As Long, LCell As Long, LRow2 As Long
Dim RegionList As String
RegionList = ""
xlz = Sheet1.Range("o1").Value & "\Region Planning\TestDB.xlsx"
Set xlw = xlo.Workbooks.Open(xlz)
If Not Sheet11.Range("S1").Value = xlw.Worksheets("validation") _
.Range("N1").Value Then
MsgBox "YOU ARE USING AN OUT OF DATE VERSION" & vbLf & _
"Please check your inbox or contact xxxx for the current version."
xlw.Close False
Set xlo = Nothing
Set xlw = Nothing
Call Module7.ProtectSheets
End
End If
x = CheckValidation(usename, xlw)
'~~ Check to see if User has access to view/modify.
'~~ If they have access, return regions
On Error Resume Next
For i = LBound(x) To UBound(x)
regions = regions + " --- " & x(i)
RegionList = RegionList + x(i) & ", "
Sheet1.Cells(i + 2, 33).Value = x(i)
Next
If Err.Number <> 0 Then
MsgBox "You do not have access to view or modify any regions."
xlw.Close False
Set xlo = Nothing
Set xlw = Nothing
End
Else
MsgBox "You have access to view and modify the following regions:" & vbLf _
& vbLf & regions & "---"
I believe the issue occurs somewhere within this section of the code as the msgbox on the last line doesn't show up prior to the notification. I haven't been able to run in debug from his machine as he's located remotely and that would be a large effort (should only be done if absolutely necessary).
Anyone have ideas on why this one user is getting this error? I'm particularly confused because it's only him having the issue.
One thing that looks a bit suspicious is that you're creating a new instance of Excel
Dim xlo As New Excel.Application
Normally this is done so that a hidden instance of Excel can be used to open a workbook that you don't want to show to the user, but I don't see any code to hide this second instance, i.e.:
xlo.Visible = False
Since you open and close the shared workbook quickly, and you have ScreenUpdating = False in your main Excel instance, you may be able to do this in your main Excel instance without the overhead of creating a new Excel instance.
Also you aren't calling xlo.Quit to close the second Excel instance, so it may hang around in the background...
An alternative approach would be to use OleDb to read from the shared workbook, in which case you don't need to open it at all.

VBA function call: Excel Button vs VBS call

I'm struggling with a VBA Sub that is called by a button. This Sub opens an Configuration.xls Excel spreadsheet from a hard coded file path. A MsgBox tell me about the current workspace - the workspace changes from the current file to the just opened one. All is fine here.
I now want to execute this Sub from an outside batch that calls a VBS that calls the VBA Sub. The workspace after opening the Configuration.xls file remains the same and does not change to Configuration.xls. Additionally when calling the Sub by VBS the function gets executed twice - No clue why.
So my question is - why do I have different behaviors between the two calling mechanisms?
I simplified the code below as it shows the same behavior as my more complex real code.
Sub ReadConfiguration()
MsgBox ActiveWorkbook.Name
FileExcel = "D:\_Trash\VBA_VBS\Configuration.xls"
Workbooks.Open Filename:=FileExcel, ReadOnly:=True, IgnoreReadOnlyRecommended:=True
strFileName = FunctionGetFileName(FileExcel)
MsgBox ActiveWorkbook.Name
On Error Resume Next
Set wBook = Workbooks(strFileName)
If Err Then
Exit Sub
End If
ActiveWorkbook.Close savechanges:=False
End Sub
'*****************************************************
Function FunctionGetFileName(FullPath As Variant)
Dim StrFind As String
Do Until Left(StrFind, 1) = "\"
iCount = iCount + 1
StrFind = Right(FullPath, iCount)
If iCount = Len(FullPath) Then Exit Do
Loop
FunctionGetFileName = Right(StrFind, Len(StrFind) - 1)
End Function
'*****************************************************
The VBS looks like this
Dim args, objExcel
Set args = WScript.Arguments
Set objExcel = CreateObject("Excel.Application")
objExcel.Workbooks.Open args(0)
objExcel.Visible = False
objExcel.Run "Module1.ReadConfiguration()"
objExcel.ActiveWorkbook.Close(0)
objExcel.Quit
I just want to let you know about the solution of this issue allthough I cannot explain completely. The solution is to get rid of the "()" behind the macro call. This has the effect that the VBS script is run twice and the Workbook 'scope' is mixed up.
So easy solution but still the question WHY- What do I tell the function additionally when adding the "()"?
Thanks for your help!
TheMadMatt