Cannot fully intercept or trap SaveAs Dialog - vba

With the help of the web, I have been able to write some VBA to check content controls on a Word 2013 template document and use the content to create a filename when Save or Save As are chosen, using custom subroutines with the appropriate names:
Sub FileSave()
If Left(ActiveDocument.Name, 4) = "PDR " Then
ActiveDocument.Save
Else
Call FileSaveAs
End If
End Sub
Sub FileSaveAs()
' too much to list, but in essence it
' checks contents of content controls
' and if properly populated build a string to use as a filename
' with the standard ActiveDocuments.SaveAs2 command
End Sub
The code works when using the keyboard methods of [Ctrl]+S/ pressing [F12], when using the standard Save button in the ribbon, and when using Save from the File menu.
However, if the user opts for the menu option and chooses File \ Save As... (i.e. the one that looks like this -
then it seems that the code in my FileSaveAs() routine gets bypassed and we get a normal Save As dialog box with the first couple of words from the document being suggested as the filename (i.e. standard Word behaviour).
How can I capture the menu method?
Alternatively, I did consider disabling "Save As..." from the File menu within a autonew() subroutine utilising CommandBars, but I can't get this to work. The sites I researched suggested that this ceased to be possible from Word 2010 onward.

I found that after Office 2007 you need to use a Custom UI editor to manipulate the XML of the file.
I then found that there was a change in some of the key words from Office 2013 onwards (when the "Office" button in the top left corner was replaced by the "File" menu). Not only does this link allow you to download the Custom UI Editor, but it gives the subtle details in the commands between Office 2010, 2013 and 2016: http://www.rondebruin.nl/win/s2/win005.htm
Whilst the page above refers to Excel, it appears to be common across Office as a whole. I used it to alter a Word 2013 file to successfully hide "Save As" from the File menu. Below is the relevant XML I employed to solve my particular issue:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<backstage>
<tab idMso="TabSave" visible="false" />
</backstage>
</customUI>

Related

Late Binding Word Ribbon

First post here, and also still learning VB so be gentle :).
I'm trying to understand how to late bind the Word Ribbon to a .dotm file.
I have a large number of users working in the Windows 10 (64 bit) platform using Office 2010 (32 bit), but we are transitioning to Office 365 (64 bit) in the next few months.
Both versions support ribbon customization using XML and VB. I'm trying to do the following:
Create a Custom Ribbon
Add various buttons, etc with custom images
When each button is clicked it runs a macro
The .dotm file will be distributed to each users machine to one of the trusted locations so that the ribbon loads each time a word session is opened and that the macros run when clicked.
I have a working prototype for Office 2010, but the same file in Office 365 does not work due to missing references to the Microsoft Office 15 Object library. From my understanding by "late binding" rather than "early binding", I can solve this problems since I wont be referencing the Microsoft Office 2015 object library directly and when Word loads it will look to whatever reference library the computer has and uses to initialize the Ribbon.
I see I need to change the code to reference the ribbon as an Object, but am not sure what the specific call to the Word Ribbon customization needs to be (and how to tie everything together). Looking through the various MSDN library links hasn't helped, its mainly just confused me further.
I've posted my generalized code below. Any help and advice would be appreciated.
The XML file looks like this
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Onload">
<ribbon>
<tabs>
<tab id="CustomTab1" label="Tab1">
<group id="Grp1" label="Group1" >
<button id="Grp1Btn1" size="large" label="Button1" image="Button1Image" onAction="Button1Clicked"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Then within the Project\Microsoft Word Objects\ThisDocument I have the code that loads the Custom Ribbon, and then links the button click to the appropriate macro.
Option Explicit
Public myRibbon as IRibbonUI
'This is the link to the XML file so the custom ribbon loads at startup
Sub Onload(Ribbon as IRibbonUI)
Set myRibbon = Ribbon
End Sub
'Code for a single button which then runs a macro
Sub Button1Clicked(ByVal control as IRibbonControl)
Macro.Button1
End Sub
'Each button has its own Sub like this one, just with an different name and link to its macro
Then under Project\Modules\Macro, I have all the code associated with each macro, like this:
Sub Button1()
MsgBox Prompt:="At this point Macro 1 would run, but for this example, all you get is this silly dialog box", Title:="Button 1 Success"
End Sub
You do not need to use late binding to make the ribbon work under O365. Word will pick up the later object libraries automatically.
You will need to test all your code to ensure that it is 64 bit compatible, but that is a different issue.
For O365 the object libraries (.OLB) will be under C:\Program Files\Microsoft Office\root\Office16. The Office 16 library (MSO.dll) should be under C:\Program Files\Common Files\Microsoft Shared\OFFICE16. If they're not there you need to find out why.
There are some additional security options that system admins can set for O365 including disabling the use of macros. You need to check what options are being applied as part of the install and ensure that whoever is responsible for the rollout understands that you need to use macros.
You also need to ensure that the .dotm is stored in the folder designated as the Startup folder. You can check this in File | Options | Advanced | File Locations
This location must be the same as the one listed for Startup in the Trusted Locations. By default it is C:\Users\UserName\AppData\Roaming\Microsoft\Word\STARTUP. You should note that the Startup folder under C:\Program Files\Microsoft Office\root\Office16\ is not a trusted location anymore (under Office 2010 it was an implicitly trusted folder and any .dotm located there would work regardless of the trusted folder settings).
If this needs to be run on different machines, you can use code to find the Startup Folder on the particular machine. The user, though, will need to set that folder as a trusted location. Here is a macro that puts the path in a message.
Sub ShowStartUpPath()
' Macro written by Charles Kenyon 2014-02-25
' Shows setting for Startup Folder location in Microsoft Word in a message box.
'
MsgBox _
Prompt:="Your StartUp folder location is " & _
Application.StartupPath & _
"." & Chr(13) & Chr(10) & Chr(13) & Chr(10) & ".", _
Buttons:=vbOKOnly, _
Title:="Current Startup Folder Setting Information"
'
End Sub

Display a custom tab on Word Ribbon depending on the version of Word detected?

I have customized the Office Ribbon adding a new tab to the Word ribbon by creating a custom XML file. The customization is in a template in the Word start-up directory. I am using Word 2016. It works under Word 2016; however it does not work in Word 2010. When opening a document in Word 2010 I get the dreaded "Error in hidden module" message. After hours of debugging and researching I cannot find the cause of this error in my VBA code.
All the users in my company should be using Word 2016, however I must assume that some users will still be using Word 2010.
If a user opens a document using Word 2010 I don't want my custom tab to be visible, that is I don't want the OnLoad event to fire.
I tried the following code in the OnLoad Event callback:
If Application.Version = "16" Then
Set myribbon = ribbon
Else
End
End If
In the other callbacks such as ToggleOn Action, getlabel, getTag, GetImage I checked for the Word Version like this:
Public Sub…
If Application.Version = "16" then
Do callback code
Else
End
End If
End Sub
However, the ribbon always loads and I could not find a way to stop it from loading. I also believe that you cannot hide a custom tab on the ribbon using VBA.
To solve this problem I did the following:
I put a template in the startup directory that checked for the correct version of Word. If the correct version was found, it loaded a template as an add-in from the users template directory with the ribbon customisation and my VBA code.
It works, but it means I have to distribute two templates to the users. Ideally I'd like to have to distribute only one template.
Is there a way to enable or prevent the OnLoad event firing, that is display a custom tab, depending on the version of Word detected?
Use getVisible callback.
XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="tab1" label="CUSTOM" getVisible="OnGetTabVisible">
<group id="group1" label="Group1">
<button idMso="SaveAll" label="Save All" size="large"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Callback:
Sub OnGetTabVisible(ctrl As IRibbonControl, returnVal)
If Val(Application.Version) = 14 Then
returnVal = False
Else
returnVal = True
End If
End Sub
UPDATE
I would suggest following resources:
RibbonX: Customizing the Office 2007 Ribbon
Excel 2007 VBA Programmer's Reference
Ron de Bruin Excel Automation

Auto displaying form on opening a template file, dotm from explorer

I have written a form based document generation macro (in VBA) for distribution to a sales team.
For their ease of use, I want to provide a self-contained file which will display the form as soon as the document is opened.
Using AutoOpen I can get the form to display as intended if word is already open and the dotm file is opened within. However, if I double click the file from within explorer, nothing happens and I have to launch the macro manually. I thought AutoExec might allow this but no luck there. I've spent considerable time trying to get this to work through googling etc. but I'm not getting anywhere.
How can I make the form display even when the file is opened with a double click? Is it possible to do this without having to change normal.dotm for each user?
For further background, I am using Word 2013 with macros fully enabled during testing. The dotm file is stored in a trusted location.
I am using a macro to launch the form like this...
Public Sub AutoOpen()
StartPage.Show
End Sub
I have tried using AutoExec as well to no avail.
In the "generator.dotm" file got to Visual Basic and go in to the "ThisDocument" Microsoft Word Object.
At the top of the Visual Basic Editor select "Document" in the left hand side and then click on "New" on the right hand side. Private Sub Document_New() method will appear for you to be able to edit. Then you can call your userform in there. Similar to:
Private Sub Document_New()
Dim myForm As UserForm1
Set myForm = New UserForm1
myForm.Show
End Sub
Save your Generator.dotm and double click it through Windows explorer and you should get the results that you would like.

Word add-in, custom layout

Is it possible to create a custom layout, existing ones are:
Print layout
Full Screen reading
Web layout
Outline
Draft
These can be found in the View Ribbon under the group Document Views.
My aim is to get my own layout button in either the existing View Ribbon (if it is possible to modify it) or add a new layout to my custom Ribbon.
Thanks in advance!
This answer is going to provide information on how to change standard settings of any view type control and associate these changes with certain document. This will not work with all documents and will not change the control action for whole Word Application but for one document. Operation could be repeated for few document and almost all Word button.
Important! I'm not using English version of Office application therefore some description will not match exactly to what you have. Tried and tested for Word 2010.
There are following steps to go:
Open new document- one where control should work according to your private expectations.
Go to View >> Macros >> Show list of macros
In the combo-box below middle of the Macro window choose something like Word application commands (or Word macros or similar). As a result you get list of lots of macros names.
You need to guess which of the macro is associated with ribbon control you are going to change. Use common sense and logic to find it. Sometimes two or three seems to match and possibly you will need to make a try.
A) let's try to change behaviour of draft/pending/working view ribbon control. one rounded red below:
B) find macro ViewNormal (but not ViewDraft)
C) select this macro on the list
Change back on the combo-box list to your document (while keeping your chosen macro selected)
Press Create button on the right in the macro window. You will be moved to VBA Editor to the following code:
Sub ViewNormal()
'
' ViewNormal Makro
' Zmienia widok edycji na normalny
'
If ActiveWindow.View.SplitSpecial = wdPaneNone Then
ActiveWindow.ActivePane.View.Type = wdNormalView
Else
ActiveWindow.View.Type = wdNormalView
End If
End Sub
This code is responsible for working of chosen ribbon control.
First, let's check if we can take control of ribbon button- add MsgBox "Control taken" at the end of the code, before End sub. Back to Word App and press button on the ribbon which result should be- setting of chosen view and our message box.
Now you need to change your code accordingly to set your view as you need. Use VBA for that.
Save document as .Docm and all the changes will be applied to the document each time you press chosen ribbon button.

How can I programmatically bring up the document properties window in Word and go to the Summary tab?

I am developing a VB6 COM add-in for Microsoft Word and I have added a button to the Ribbon which will save the document to a database. But before the document is saved, I want to take the user to the document properties window so they can fill in the properties for the document (like Title, Subject and Author). I am using the following statement to bring up the window:
Application.Dialogs(750).Display
This works fine, but it defaults to showing them the General tab. The fields for Title, Subject and Author) are on the Summary tab. Is there any way to bring up this dialog box and force it over to the Summary tab? I thought about sending keystrokes, but the tabs don't have hotkeys associated with them.
I need this to work in Word 2007 and Word 2010. The line above already works fine in Word 2003 because 2003 doesn't have a multi-tabbed properties window.
You can bring up a seperate box for this (works in both Word 2000, 2003, 2007 and 2010):
Application.Dialogs(wdDialogFileSummaryInfo).Display
or
Application.Dialogs(86).Display
You can also program against this dialog. See here for an example.
You could record a macro then execute it as needed.
Changing .Display to .Show works, except you get an error if you press ESC, so you have to wrap it in On Error Resume Next (no idea why).
Sub CustomProperties()
On Error Resume Next
Application.Dialogs(750).Show
End Sub