RefreshAll BeforeSave - excel

I am using power query to combine several tables together and output some info to another table, all within the same workbook.
I would like to ensure the output table is always up-to-date when the file is saved and don't want to depend on ppl using the 'Refresh All' button. Ideally I would have the queries update when the file is being saved.
For each query I have disabled the 'Enable background refresh' option in the query properties. I then have added the following vba code to ThisWorkbook:
Option Explicit
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
ThisWorkbook.RefreshAll
End Sub
This does cause the queries to be updated before the file is saved. However if a user clicks on the save button (causing the queries to update & file saved), and then closes the file they are prompted to save the file again as if something has been edited... I have tried adding a wait command to the BeforeSave method after the refresh however the same behaviour occurs. We could of course just save it again or close without saving (since it was saved when we first hit the save button) however both are not ideal (file is on a network drive, so even though it is only a couple MB it takes several seconds to save, and not a fan of closing without saving).
Any tips for stopping Excel from asking us to save a workbook that we just saved?
Edit
From comments and suggested answers it seems that BeforeSave can be inconsistent. I did want to allow users to be able to close the workbook without saving so wanted to avoid using BeforeClose(for example a user made large changes to the workbook and wanted to undo everything). By manually setting the workbook saved state to true in Aftersave seems to have resolved the issue; atleast in my testing so far (even though it should already be true since it just saved?).
Option Explicit
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
If Success Then
ThisWorkbook.Saved = True
End If
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
ThisWorkbook.RefreshAll
End Sub

Workbook.RefreshAll
It seems like the BeforeSave isn't always working as expected so your feedback is most welcome.
Option Explicit
Private DoNotBeforeSave As Boolean
Private Sub Workbook_BeforeClose(Cancel As Boolean)
With Me
If Not .Saved Then
.RefreshAll
DoNotBeforeSave = True
.Save
Debug.Print "Just refreshed and saved via 'BeforeClose'. Closing!"
Else
Debug.Print "No action taken via 'BeforeClose'. Closing!"
End If
End With
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Not DoNotBeforeSave Then
With Me
If Not .Saved Then
.RefreshAll
Debug.Print "Just refreshed and saved via 'BeforeSave'!"
Else
Cancel = True
Debug.Print "No action taken via 'BeforeSave'!"
End If
End With
End If
End Sub

Related

Strange behavior when closing a workbook twice

Strange issue when closing a workbook twice from VBA (Workbook_BeforeClose)
Hi. This problem appears to me in an extremely simple workbook: Workbook_BeforeClose only.
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Close SaveChanges:=False
End Sub
If I open and close the workbook twice, the main Excel screen looks like this, and it's impossible to do something, I can only close it from the status bar:
If all you are trying to do is to not prompt the user to save changes, just play with the appropriate flags to 'trick' Excel that changes have already been saved.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Me.Saved = True
End Sub
This will allow the workbook to close, without prompting any changes to be saved, but this does not actually save them.
Notice the subtle difference between the words: Me.Saved and Me.Save.
Saved is a property that gets flipped to False when Excel detects changes were made as of the last save.
Save is a method - not a property as above - that actually will save the workbook.
Your workbook is already closing, which is what fired this event to begin with. No need to try to close it again within this event. Just tell Excel that no changes have been made since the last save, and it should close all on it's own - without the prompts.
It's possible you're re-triggering the event. Try something like this:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Static InProgress As Boolean
If InProgress Then Exit Sub
InProgress = True
ThisWorkbook.Close SaveChanges:=False
End Sub

How to read destination path after the SaveAs UI is used

I have a macro running in the Workbook BeforeSave event
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If SaveAsUI = True Then
'read destination path somehow
'perform business logic using the destination folder
End If
End Sub
Certain validation on the workbook content need to take place only if the file is saved to a certain destination, this may result in the save action being cancelled.
I have been unable to find a way to read what the user specified as the destination path. I need some help please as I am not a VBA specialist.
It appears to me the event fires before a destination path is chosen. You probably have to use the WorkbookAfterSave event and then perform the validation afterwards.
https://learn.microsoft.com/en-us/office/vba/api/excel.application.workbookaftersave

Titus add-on won't allow me to save to PERSONAL.XLSB

We use Titus for classification. I can save a macro in a local workbook, but I can't save anything to my universal PERSONAL.XLSB workbook. The Titus pop up won't go away no matter what options I choose.
The apparent cause is that Titus is trying to save to the wrong place, as shown in the picture below. Is there any fix for this other than disabling Titus? I'm on Win10, using Titus ClassificationSuite 4.5 HF3, Excel 2013. This exact macro saved to my personal.xlsb before my Win10 upgrade. (And by upgrade, I mean I got a new box with a fresh install)
You may want to use EnableEvents=False before saving and then EnableEvents = True.
The Idea is to disable the events so the popup is supressed and then save the file. Once the save operation is done we'd want to enable the events.
Titus is a Com Addin and usually this is visible on the
Depending upon what you select the CustomDocumentProperties are set. You can find this by clicking File-->Info-->Adavnced Properties as shown here
Now this is how you'd add customProperties programatically
Application.EnableEvents = False
With ActiveWorkbook.CustomDocumentProperties
.Add "CompanyClassification", False, msoPropertyTypeString, "Company-Public"
.Add "CompanyClassification", False, msoPropertyTypeString, "Company-Internal"
.Add "CompanyClassification", False, msoPropertyTypeString, "Company-Confidential"
.Add "CompanyClassification", False, msoPropertyTypeString, "Company-Secret"
End With
'Do the Save Operation here. Also if your company wants to Comply with EU GDPR (European General Data Protection Regulatory) then add the appropriate footer (Internal/Public/....)
Application.EnableEvents = True
I hope this should give you an idea on how to go forward.
I've found that if you edit the Personal.xlsb Workbook, and use the BeforeClose method such that:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.EnableEvents = False
End Sub
Then call the BeforeClose method to re-enable:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.EnableEvents = True
End Sub

Saving Personal.xls automatically

I use Excel 2003 on a Windows 7 Professional setup.
In my Personal.xls file, I have compiled snippets of code/formulae that I have picked up from different places, to be available for ready reference when I use Excel. These contain a number of volatile functions such as cell(), rand(), today() etc. As a result, when I close Excel, it asks me whether I would like to save Personal.xls.
I would like to keep my Personal.xls as it is, and yet disable the popup somehow. I am fine with saving, not saving, either way, as I won't be changing Personal.xls.
I have tried the following code in my personal.xls in the Workbook_BeforeClose section
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Save
End Sub
But it doesn't seem to work. I have tried some variations, including .Save and .Saved=True, and also tried to alternatively use ThisWorkbook., Me. & Workbooks("PERSONAL.xls"). However, Excel still asks me save Personal.xls
I have also tried to disable calculations in my Personal.xls viz.
Private Sub Workbook_Open()
For Each ws In ThisWorkbook.Worksheets
ws.EnableCalculation = False
Next
End Sub
This doesn't solve the problem either. Finally I tried to do a 'ThisWorkbook.Save' after changing calculation mode to manual, but that doesn't change anything either.
Am I missing something here? Any advice would be appreciated. Thanks in advance!
You want:
Me.Save
In your workbook BeforeClose event.
Why not just force-shut the document?
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Close savechanges:=True
End Sub
For what I was trying to do I am actually using savechanges:=False. Both ways worked.
I just remove the Cancel As Boolean
Private Sub Workbook_BeforeClose()
ThisWorkbook.Save
End Sub

Sub App_WorkbookBeforeSave doesn't work on VBA Add-in/Excel 2010

I am going to show a MessageBox before save workbook. I have tried with event handler Sub App_WorkbookBeforeSave() and Sub Workbook_BeforeSave but both doesn't work! Why?
There are my Sub in addin:
Private Sub App_WorkbookBeforeSave(ByVal Wb As Workbook, _
ByVal SaveAsUI As Boolean, Cancel As Boolean)
MsgBox "Good bye! Data is save."
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
MsgBox "Good bye! Data is save."
End Sub
UPDATE
I was put them in ThisWorkbook modules belong to Microsoft Excel Objects
This kind of functionality requires...
The code to be in ThisWorkbook module of the Add-In, OR
Using a class to hold the event handling code, while still kicking it off in the ThisWorkbook module
Either way, you need to create an instance of a WithEvents Application object which, while you don't touch the object directly after you create it, enables the events to be captured.
I like the second option (cleaner, makes you look like a boss, etc.). Create a class and call it something. I like to call my class ImAGoodListener. In the class, include the appropriate Subs for any application events you want to use
Public WithEvents App As Application
Private Sub App_WorkbookBeforeSave(ByVal Wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)
On Error Resume Next
MsgBox "Good bye!"
End Sub
With the arguments, you can do cool and mischievous things like prevent the workbook from being saved...
(I like On Error Resume Next for this so we don't risk not allowing a user to save his/her workbook should our code go haywire)
In the ThisWorkbook module put something like this...
Dim objAppLis As New ImAGoodListener
Private Sub Workbook_Open()
Set objAppLis.App = Application
End Sub
This will start the event listening when your Add-In is initially opened.
Alternatively, if you're using CustomUI for the ribbon, you use a Ribbon Onload event to trigger the start of listening (I do this when my events are used primarily for ribbon behavior so I can easy disable listening in the CustomUI xml).
Some other application events of use are:
App_SheetActivate
App_WorkbookActivate
App_WorkbookOpen
App_WorkbookBeforeClose
App_WorkbookBeforeSave
Here's a list of all events, but note that some of them are workbook (event handlers start with Workbook_ events which won't work for this sort of thing.
Chip goes into great detail about these sort of events on his site here.

Resources