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.
Related
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 new to VBA and am trying to write a macro that will execute a field update before the user saves the document. My first attempt was going to be intercepting the Save command like this:
Sub FileSave()
'
' FileSave Macro
' Saves the active document or template, and updates fields
'
Fields.Update
ActiveDocument.Save
End Sub
But one guide recommended not doing that and instead using DocumentBeforeSave(), so this is my new attempt:
Private Sub oApp_DocumentBeforeSave(ByVal Doc As Document, _
SaveAsUI As Boolean, Cancel As Boolean)
Fields.Update
End Sub
The first example gives me the following error:
"Runtime error '424': Object required"
The second example doesn't update the fields. I've tried the second code in both the ThisDocument object, and as a new module class. Nevertheless, the fields are still not updating when I save. On a side note, they work with this.
Private Sub Document_Close()
Fields.Update
Save
End Sub
It seems like a simple task but it just doesn't seem to work.
In your ThisDocument code module, add an Application object using the WithEvents keyword so that you can respond to its events:
Dim WithEvents TheApp As Word.Application
Add an event handler for Document_Open() that assigns your variable to the active Application object:
Private Sub Document_Open()
Set TheApp = ThisDocument.Application
End Sub
Add an event handler for Application_DocumentBeforeSave(). Within this event use the Doc object that's passed to it to update your document:
Private Sub TheApp_DocumentBeforeSave(ByVal Doc As Document, SaveAsUI As Boolean, Cancel As Boolean)
Doc.Fields.Update
End Sub
Save your document as a "Macro-Enabled Document (*.docm)".
Close the document and reopen it.
That should be it. If you want to make sure your code is working properly, add a breakpoint or a MsgBox() before your Doc.Fields.Update statement to make sure the event handler is getting called and check your values before and after the update.
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.