I have written a VBA macro that attaches a review slip at the end of a document that is to be reviewed by coworkers and management. The section of the document where the review slip is attached is protected for filling in forms. I also have enabled tracked changes, but it is applied to the entire document.
My problem arises when people enter values on the review slip (e.g., sign off on their review of the routed document), tracked changes makes a mess of the review slip.
Management does desire to print out this form once the document has completed the review and editing process, which is one reason it was appended to the document.
Similar to how I can restrict editing in a portion of the document to only filling in forms,
(e.g., ActiveDocument.Sections(ActiveDocument.Sections.Count).ProtectedForForms = True)
I want to only enable tracked changes for all but the last section of the document.
Or, is there a way to automagically accept all changes only within the last section of the document?
You could use Word's SelectionChange event to test which Section the user is working in and turn off track-changes if the selection is in the last Section. The actual code would be:
Private Sub oApp_WindowSelectionChange(ByVal Sel As Selection)
With ActiveDocument
.TrackRevisions = (.Range(0, Sel.Start).Sections.Count <> .Sections.Count)
End With
End Sub
However, you can't just use the above code on its own. For implementation, see: https://wordmvp.com/FAQs/MacrosVBA/AppClassEvents.htm
Related
My document has a form with bookmarked content controls that link to Custom Document Properties via the Link-to-Content option. The Custom Document Properties are used to display form values in reports later in the document. The only problem with that approach is that when a value is updated in the form, it doesn't automatically update the value of the linked custom document property.
When updating the form manually, I found just accessing the Advanced Properties dialog updates the links. (Then I select report content and press F9 to update the DOCPROPERTY fields.) But now I need to automate filling in the form, and I can't find a way to update the links in VBA. I've tried accessing the custom document properties, and even replacing the link source with the original source thinking that accessing the links might update them (see code below), but the linked values aren't changed this way. Does anyone know how to programmatically update those links? How does the Advanced Properties dialog do it?
With wdDoc
For Each dp In .CustomDocumentProperties
If dp.LinkToContent Then
dp.LinkSource = dp.LinkSource
End If
Next dp
.Content.Fields.Update
End With
I found that by setting Options to "Update Links at Open", the links are updated when I Save the document. So after saving it, I could update the fields, and Save the document again to achieve what I wanted.
With wdApp
'updates OLE links to Content Controls
.Options.UpdateLinksAtOpen = True
End With
...
With wdDoc
.SaveAs sFileName
.Content.Fields.Update
For i = 1 To .Sections.Count
.Sections(i).Headers(wdHeaderFooterPrimary).Range.Fields.Update
.Sections(i).Footers(wdHeaderFooterPrimary).Range.Fields.Update
.Sections(i).Headers(wdHeaderFooterFirstPage).Range.Fields.Update
.Sections(i).Footers(wdHeaderFooterFirstPage).Range.Fields.Update
Next i
.Save sFileName
End With
I will continue to investigate Custom XML Parts though as a longer term solution. It looks like that's where Microsoft's direction is, and eventually support for the binary Custom Document Properties may disappear. Thanks for steering me in that direction.
Is there a way to apply "auto-updatable" style for hyperlink?
I believe, this question is not trivial.
When you normally click on hyperlink, it will change it's color to violet. Next, if you save, close, and then reopen the document, the link will be updated back to blue. This is default behaviour of Word, and there is no need to use any macros for it.
I'm trying to replicate this behaviour with VBA. Here is the code:
Sub Test1()
Selection.Range.Hyperlinks(1).Range.Fields(1).Result.Style = Word.WdBuiltinStyle.wdStyleHyperlinkFollowed
End Sub
To make it work, simply put caret into the link, run macro, and see the results:
This works fine, except such visited links will not be auto-updated after you save, close, and then reopen the document. See the difference in the picture below. The link "Google" was opened normally, using the mouse Ctrl-click; the link "StackOverflow" was opened using the macro:
As I already said, I want to make my VBA-opened links (StackOverflow) auto-updatable as well (as Google).
Yes, I understand, there is a workaround - simply create another macro, which will be started every time the document opened and change all violet hyperlinks back to blue. However, this is just workaround, and I don't like it. Using it, we use conversion from "permanent violet" to "permanent blue", instead of using "temporary violet" (that's mean, auto-updatable without any additional efforts).
Hope everything is clear. Thanks in advance.
Update (was added after several answers were already posted).
Yes, I understand, this will work:
Sub Test1()
On Error Resume Next 'To avoid an error in case if the link isn't reachable
Selection.Hyperlinks(1).Follow
End Sub
But I want just simulate following, without really opening the link in the browser. That's why, I can't use Selection.Hyperlinks(1).Follow.
you need to remove the line, the link will change once followed and change back once the doc is reopened.
Selection.Range.Hyperlinks(1).Range.Fields(1).Result.Style = Word.WdBuiltinStyle.wdStyleHyperlinkFollowed
this does it for me
Sub resetHyperlinks()
Dim hLink As Hyperlink
For Each hLink In ActiveDocument.Hyperlinks
hLink.Address = hLink.Address ' this works
' hLink.ScreenTip = hLink.ScreenTip ' this works also
Next hLink
End Sub
You don't need to change the style with code to make the link purple. Just use the Follow method. This will click the link and turn it purple and then it will be reset to blue upon opening the document again.
Sub Test1()
Selection.Range.Hyperlinks(1).Follow
End Sub
You can reset link styles with VBA code that runs at startup, i.e. is a part of Document_Open() routine in ThisDocument VBA module.
The Hyperlink class doesn't have any .Visited property or anything relevant (i.e. you cannot even see if it was visited), so there's no other way beside .Follow() that also opens the link as it should.
You're basically trying to falsify the information that the document provides about its state: make a link appear visited when it actually wasn't.
The fact that the class doesn't even provide a property means that Word's designers do not consider the visited status a part of the editor's functionality (i.e. it effectively doesn't exist as far as the program's job is concerned).
This evidence suggests that Word doesn't, and is not designed to, have any specialized facility to switch link status other than .Follow(). Which means, any way that you find that happens to have the desired effect in bound to be what you're calling a "workaround".
The "temporary" color of a followed hyperlink is an embedded (and not directly accessible) feature of the built-in Hyperlink character style. It is not exposed through the normal UI's Style tools, nor through the object model.
You can readily compare all formatting between two selections using the Reveal Formatting pane (Shift+F1) in the document window in Word.
If you compare a normally followed hyperlink with a hyperlink affected by your snippet, you'll see that the followed hyperlink still has the Hyperlink style, while your simulated follow has changed the style of the second hyperlink.
If you compare a never-followed hyperlink and a normally followed hyperink, Word identifies their formatting as exactly the same. Word does not acknowledge that any aspect of formatting (style, font color, etc.) has changed.
It seems likely that the Word.WdBuiltinStyle.wdStyleHyperlinkFollowed you are using exists explicitly to address this gap (which is somewhat disappointing).
I recommend using your existing approach, and then reverting the style in a procedure triggered by the Before Save and Before Close events of the document. Using those events will prevent the followed style from saving at all, and so avoid issues caused by someone opening the document without enabling macros.
Option Explicit
Sub test()
Dim HL As Hyperlink
For Each HL In Sheet1.Hyperlinks
HL.Range.Style.Font.Color = vbBlue
Next
End Sub
Can't you simply make it any colour you want without invoking it. As others have stated above whatever you you I think will be a work around as it's not an intended function.
There are several instances of this problem, but this one is predominant. This is in relation to updates (our most notable problem child being KB2726958). We have a Leave Spreadsheet that looks like this:
Leave Spreadsheet example
By pressing the grey Leave button, you end up here:
Leave Word doc
All the programming for these is written in VBA (i've never worked with VBA before, I can understand it to a degree).
Now, the issue is that using the ActiveX button in the 'Leave Spreadsheet example' causes the 2 buttons 'Send by Email' and 'Save' to switch functions; Send by email attempts to save and save opens up Outlook and creates the email message.
Both functions have completely retained functionality, just on the wrong buttons.
The thing I find weird is that a hyperlink to the very same file works; the buttons aren't switched and have full functionality. The only hint that I have towards resolution is that when using a hyperlink, it's directly opening the file. When using the ActiveX button, it seems to be creating a new file based off the file it's linking to. For example, the hyperlink directly opens C:\Report.dotm but the ActiveX button opens Document1.doc with a template based on Report.dotm.
I'm considering that maybe the activeX button is opening up Word with an incorrect extension? But i'm not sure how to figure this out (code below shows that the linked file on the activeX control is a .dotm).
What further throws a spanner into the mix is that it only affects some computers... Considering on-site we all use the same type of PC with the same image... :(
My question is, does anyone know why they may be swapping? They're located on the same network drive albeit different directories. They require the same permissions to access. The code for the buttons is as follows:
Excel Button:
Private Sub CommandButton1_Click()
' This button links the excel spreadsheet to the word doc
Dim wrdApp As Object
Dim wrdDoc As Object
Dim i As Integer
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
Set wrdDoc = wrdApp.Documents.Add("\\networkdrive\directories\Request for Leave.dotm")
End Sub
Word buttons 1 and 2:
Private Sub cmdSend_Click()
' This is the code for the button 'Send by Email'
MsgBox "Send the following email to your Team Leader/Line Manager", vbInformation
SendDocumentAsAttachment "", "IPL Request for Leave"
End Sub
Private Sub cmdSave_Click()
' This is the code for 'Save'
modSend.SaveLeaveForm
End Sub
Please Note: The comments above are not in the code in VBA, i've written them in myself in this question to provide clarity.
Troubleshooting that i've done:
Removing all .exd files
Running the MS Hotfix (removes all .exd files in a GUI)
The next step would be to try running all 6 patches related to fixing ActiveX controls with the particular patches we've done to see if that fixes the problem. The reason I haven't done this yet is because of ITIL (Change management) although I may try testing this later today.
What is the outcome i'm after?
Ideally, I want to understand what is causing these buttons to, from what it looks like, swap their functions. I have different scenarios of button swaps, some of which are remedied by removing the .exd files, and some that aren't.
By understanding what is happening, I hope that I can apply the knowledge to the other scenarios (same problem, different coding).
Then, I'll be able to document my findings so that when we perform the next round of patching that is known to break ActiveX controls, my organization will know how to deal with it.
So the patch mentioned below has fixed this issue. There's still some other issues that I need to test this patch against, but I definitely should have started there. Lesson learnt.
From my work email:
I’ve just tried using the patch related to the ActiveX controls breaking, KB2920754. I’ve used it on two PC’s here in the training room; both had different issues:
- The first one had buttons that had switched around (save attempted to email, email attempted to save)
- The second one couldn’t use the buttons at all.
This patch cured both w/o requiring a restart or logging out and back in. I didn’t remove any .exd files, either.
It does state, however:
“Important For this fix to be fully effective, you also have to apply the other patches for Office 2013 that are listed in the "Resolution" section of the following Microsoft Knowledge Base article”
There are 6 in total.
Patches:
1. KB2920754 – (the one I’ve used successfully)
2. KB2956145
3. KB2956163
4. KB2965206
5. KB2956176
6. KB2956155
Using Word Automation, I want to save the active document programmatically. In Office 2007/2010, the document needs to be saved explicitly as "macro enabled" to preserve any VBA code in that document.
Rather than asking the user to choose, I would like my application to be able to determine if there is VBA code in the active document. Is that possible?
Yes this can be determined via the HasVBProject property. For example:
If ActiveDocument.HasVBProject = True Then
'Code to save as .dotm
Else
'Code to save as .dotx
End If
For those who might stumble upon this post later, it is worth noting that this code should be placed outside the document being tested for the presence of macros (otherwise it would detect itself). Two often-used options would be to access the code from an external application or from a template stored in Word's Startup folder.
I am working on a Word VBA macro app for 80 or so users. The office has high staff turnover, so training suffers, and so one of the self imposed requirements for this project is comprehensive, friendly documentation. However, to supplement this, and to save newbies having to open up a 100 page document when they want to try something new, I want a status bar on every userform (there are five) that provides contextual help. I find tooltips annoying.
I don't have a lot of experience, so I was wanting to
Essentially, I have a file containing every status string. (This is currently a text file, but I was wondering if I should use a spreadsheet or csv for ease of editing by other staff in future.) Every control has a MouseMove event which refers to a function: getStatus(cID) that opens the file, grabs the line and displays it in the status label. It also grabs a few parameters from the same line in the file, such as whether the label is clickable (to link to a page in the help file), and what colour the label should be.
So a few questions really:
Will the application be slow if a userform is constantly referring to a file? It feels fine to me, but I've been in it far too long, and I'm the only user accessing that file. There will be 80 constantly accessing it.
Is MouseMove over a control the best way? Should I instead use co-ordinates?
Most importantly (in terms of me having to do as little work as possible) is there some way to do this so that I do not have to have a MouseMove event on every single control? I have a good few hundred or so controls, each with their own identifier (well, not yet, but they will if this is the only way to do it). Maybe when the form loads I could load ALL the possible status lines so they're ready for whenever the control is moused over. But then, maybe the loading time is negligible?
Appreciate any ideas or thoughts - especially if VBA already has a whole range of functions to do this already and I'm just trying to reinvent the wheel. I can't use the application status bar, because the user rarely sees the application itself.
Thanks!
EDIT:
It is for both data entry, clicking around and a bit of document generation.
It is a controlled environment so macro security issues aren't a big concern for me - and if something goes wrong it's someone else's fault or problem :)
Is this data entry app or do they just click stuff? Because often the field with focus is different to the item the mouse is hovering over, this can cause a lot of confusion.
Constantly reading from a file is a huge waste of time and resources - it is much better to load them only once into an array or collection when the form is loaded.
On MouseMouse event is better than coordinates because you can move things around without worrying. It's a lot of code but you should be able to generate most of that if you have a list of control names because the code should be identical.
ie
Sub Control_MouseMove()
DisplayStatus(Control)
End sub
I would consider the StatusText property and ControlTipText property of controls for this kind of help.
StatusText
This example sets the status bar help text for the form field named "Age."
With ActiveDocument.FormFields("Age")
.OwnStatus = True
.StatusText = "Type your current age."
End With
ControlTipText
This can be assigned from the property sheet for the control.
Private Sub UserForm_Initialize()
MultiPage1.Page1.ControlTipText = "Here in page 1"
MultiPage1.Page2.ControlTipText = "Now in page 2"
CommandButton1.ControlTipText = "And now here's"
CommandButton2.ControlTipText = "a tip from"
CommandButton3.ControlTipText = "your controls!"
End Sub