How to make Microsoft Word to run a VBA macro every time before any document is saved? Could it be done without adding macros into the document itself?
You can subscribe to application events in Document_Open by using WithEvents variable and conventional method names (VariableName_EventName). Works in templates as well.
You can put this code into ThisDocument object, or make a separate class module as described here.
Private WithEvents App As Word.Application
Private Sub Document_Open()
Set App = Word.Application
End Sub
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
MsgBox("BeforeSave")
End Sub
List of all application events.
You must add the code bits at the correct place.
This must be at the top of your code page amongst your public variables or constant declerations
Private WithEvents App As Word.Application
Then add this as an open document event.
Private Sub Document_Open()
Set App = Word.Application
End Sub
This is the event that fires on save command Ctrl+s or save icon. I added my own save format and print as I saw It most useful in the case of people filling out forms and you don't want them to overwrite the initial template.
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
''save file with the saveas2 command.
ActiveDocument.SaveAs2 FileName:="YourDocumentNameORVariable" + _
" Date_" + Format(Now(), "yy-mm-dd"), _
FileFormat:=wdFormatDocumentDefault, _
SaveFormsData:=True
''addition to print file upon save
ActiveDocument.PrintOut Background:=True, Range:=wdPrintAllDocument, Copies:=1, Collate:=True
End Sub
Read more about Printout methods: Microsoft VBA - PrintOut
Read more about SaveAs2: Microsoft VBA - SaveAs2
Read more about FileFormat for Saving: Microsoft VBA - FileFormat for Saving
try saving your file in .xlsm, then close, open and save it again. it should work fine.
Related
I have created a simplistic menu in word that opens a number of word files with various macros built in. Some of the macros function as normal when opened via the menu (e.g. forms that are showed on Private Sub Document_Open), but others (code to ignore warnings about saving in a macro free environment) are ignored.
Other issues, such as a debug errors about Word being 'unable to fire event', also seem to be occurring, but only when the files are opened via the menu. All the menu does is use Documents.Open and open the file.
When users open the file without the menu, no issues occur (no warnings about saving in a macro free environment, no errors about firing events).
Any help would be appreciated! I would prefer to not have to scrap the menu entirely for usability, as there are quite a few files that the menu serves as an index for.
Code below:
If ComboBox1.Text = "- Full title page" Then
Documents.Open ("A:/Workgroup Documents/Folder 1/templates/name of file.docm")
End If
Code from document that is opened (ThisDocument module):
Private WithEvents App As Word.Application
Option Explicit
Dim sDocName As String
Dim kcsval As String
Private Sub Document_Open()
frmFooters.Show
Set App = Word.Application
CATform.Show
On Error Resume Next
Documents("J:\Workgroup Documents\Edited Transcript\templates\menu.docm").Close SaveChanges:=wdDoNotSaveChanges
FixSaveError
End Sub
Then some forms, and a module and class module that deal with the save error. Module:
Option Explicit
Dim MyClass As New Class1
Sub FixSaveError()
Set MyClass.App = Word.Application
End Sub
Class module (Class1):
Public WithEvents App As Word.Application
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, _
SaveAsUI As Boolean, Cancel As Boolean)
Application.DisplayAlerts = wdAlertsNone
ActiveDocument.Save
Application.DisplayAlerts = wdAlertsAll
End Sub
The module and class module function purely to remove the warning message about saving in a macro-free environment when saving as docx from docm.
The forms that open up on Document_Open function fine, if it gets that far (the 'error firing event' error sometimes stops it getting there, but only sometimes and only on some machines - and only when using the menu to open the files).
I’m wondering if there is a way to block the “save as” function (I.e. being able to change the name) of a word doc through VBA. The user should only be able to save as if they’ve filled in certain mandatory fields. I’m not sure if this is even possible as I have really found nothing on the topic.
A decent answer on how to subscribe to events can be found in this question: How to run a macro in Word before save?
Private WithEvents App As Word.Application
Private Sub Document_Open()
Set App = Word.Application
End Sub
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
Cancel = True
MsgBox ("Cancelled")
End Sub
This will run after you open the document
I want to detect when user press ctrl-S or click on Save option of Microsoft word using VBA excel macro code.
I found related links about Save changes while closing and Detecting if a document is getting close but I not able to find some example code for detecting saving of word document.
Any help would greatly appreciated.
Thanks
Unfortunately (or fortunately) Word does not work like excel and there the keybinding follows different logic. Thus, in Word, you should try something like this, to bind Ctrl + S. The idea is that on openning of the file you tell the application to bind Ctrl + S to the SaveMe Sub.
Option Explicit
Private Sub Document_Open()
With Application
.CustomizationContext = ThisDocument
.KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyControl, wdKeyS), KeyCategory:=wdKeyCategoryCommand, Command:="SaveMe"
End With
End Sub
Public Sub SaveMe()
MsgBox "User Saved"
End Sub
Put the code in ThisDocument:
Until now, it works this way only for Ctrl+S. If you go for the Save through the menu, it will not follow this logic. This is what you should do then:
For the general solution, follow these instructions:
I. Create a clsWord and put the following code inside:
Option Explicit
Public WithEvents appWord As Word.Application
Private Sub appWord_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
Call SaveMe
End Sub
II. Change the code in ThisDocument to this:
Option Explicit
Dim myWord As New clsWord
Private Sub Document_Open()
With Application
.CustomizationContext = ThisDocument
.KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyControl, wdKeyS), _
KeyCategory:=wdKeyCategoryCommand, Command:="SaveMe"
End With
Set myWord.appWord = Word.Application
End Sub
III. In a module:
Option Explicit
Public Sub SaveMe()
MsgBox "User Saved"
End Sub
Parts of the ideas are taken from the MSDN here - https://msdn.microsoft.com/en-us/library/office/ff838299.aspx But the code there was not complete :)
I've ended up cleaning up someone's mess on a Word document that's used throughout my company. It is a macro-heavy document that needs to be saved as a .docm exclusively. I'm worried about it getting "save as"-d as something other than a .docm, but I can't seem to find a way to limit the save as file picker or swap out the extension on save as while still using VBA.
How can I achieve this?
Edit: Some of the things I've tried, to no avail:
This has the right idea, but doesn't actually limit the filetypes down on save https://answers.microsoft.com/en-us/msoffice/forum/msoffice_word-mso_other/how-to-set-path-for-wddialogfilesaveas-dialog/535b7f9c-9972-425c-8483-35387a97d61d
Towards the bottom, Microsoft says that SaveAs isn't compatible with filter.clear and filter.add https://msdn.microsoft.com/en-us/library/office/aa219834(v=office.11).aspx
In order to hijack the native "SaveAs" dialog in Word, you need to lever the Application-level event for DocumentBeforeSave, and then call the FileDialog manually, in order to validate the extension.
1. Create a standard code module and name it modEventHandler. Put the following code in it.
Option Explicit
Public TrapFlag As Boolean
Public cWordObject As New cEventClass
'You may not need these in a DOCM, but I needed to implement this in an ADD-IN
Sub TrapEvents()
If TrapFlag Then
Exit Sub
End If
Set cWordObject.DOCEvent = Application
TrapFlag = True
End Sub
Sub ReleaseTrap()
If TrapFlag Then
Set cWordObject.DOCEvent = Nothing
Set cWordObject = Nothing
TrapFlag = False
End If
End Sub
2. Create a Class Module called cEventClass and put this code in the module:
Option Explicit
Public WithEvents DOCEvent As Application
Private Sub DOCEvent_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
' Do not prevent SAVEAS for *other* documents
If ObjPtr(Doc) <> ObjPtr(ThisDocument) Then
Exit Sub
End If
If SaveAsUI Then
' The user has invoked SAVE AS command , so we will hijack this and use our own FileDialog
Call CustomSaveAs(Doc)
' Prevent duplicate appearance of the SAVEAS FileDialog
Cancel = True
End If
End Sub
Private Sub CustomSaveAs(ByRef Doc As Document)
Dim fd As FileDialog
Dim filename$
Set fd = Application.FileDialog(msoFileDialogSaveAs)
fd.Show
If fd.SelectedItems.Count = 0 Then Exit Sub
filename = fd.SelectedItems(1)
If Not Right(filename, 4) = "docm" Then
' ### DO NOT EXECUTE this dialog unless it matches our .DOCM file extension
MsgBox "This document should only be saved as a DOCM / Macro-Enabled Document", vbCritical, "NOT SAVED!"
Else
fd.Execute
End If
End Sub
3. In ThisDocument module, do the following code:
Private Sub Document_Close()
Call modEventHandler.ReleaseTrap
End Sub
Private Sub Document_Open()
Call modEventHandler.TrapEvents
End Sub
How Does This Work?
ThisDocument raises the Document_Open event which calls on the TrapEvents procedure.
TrapEvents procedure creates a WithEvents instance of Word.Application class, exposing additional events to automation. One of these is DocumentBeforeSave.
We use the DocumentBeforeSave event to trap the SaveAs operation. If the User has requested a SaveAs, then we force the dialog with logic as created in CustomSaveAs procedure. This uses simple logic to test the file extension provided, and prevents the document from being saved if it is not a DOCM extension. If the FileDialog does receive a valid DOCM extension, then we Execute the dialog which saves the file as the new name.
I'm a novice with VBA and fillable fields.
However here is my question:
I have created a word template which has one fillable field called "Title"
I would like to know how to proceed to have the following:
Once I open the template as a normal .doc document, and I have finished to work with it and filled in the fillable field called title
that when I click save that the document file name automatically becomes the
text that I have within the fillable field called title.
Please help.
According to this post - How to run a macro in Word before save?, you can have your code in BeforeSave, cancel the save and run SaveAs2
Private WithEvents App As Word.Application
Private Sub Document_Open()
Set App = Word.Application
End Sub
Private Sub App_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
MsgBox ("BeforeSave")
Cancel = True
ThisDocument.SaveAs2 FileName:="test.docx"
End Sub
But beware you should check the filename in DocumentBeforeSave, if it is same as the title, you should not cancel the save.