Insert two fields in Word 2010 page header using VBA - vba

I am trying to insert two fields in a page header. I am able to insert them at the current selection (see code below), but I would prefer not having to select the page header before inserting the fields. Can this be done?
Sub insertFields()
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:="DOCPROPERTY LastSavedTime ", PreserveFormatting:=True
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:="FileName", PreserveFormatting:=True
End Sub

If you specify the section of the document to place the field in as well as the type of header (wdHeaderFooterPrimary, wdHeaderFooterFirstPage or wdHeaderFooterEvenPages) you can use this code:
Dim myRange As Range
Set myRange = ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Range
ActiveDocument.Fields.Add Range:=myRange, Type:=wdFieldEmpty, Text:="DOCPROPERTY LastSavedTime ", PreserveFormatting:=True
Additional Information in response to comment
You can use the Collapse method, which places the insertion point at the start or end position of a range, to insert multiple fields within the header. Add appropriate additional code to insert spaces, formatting or carriage returns:
myRange.Collapse wdCollapseEnd
ActiveDocument.Fields.Add Range:=myRange, Type:=wdFieldEmpty, Text:="FileName", PreserveFormatting:=True

Related

VBScript Syntax: MS Word Merge Field

I need a macro that places a conditional merge field with nested IF statements. Most users just copy the merge fields from one document and paste them into their final draft. However, there are numerous conditional merge fields to choose from. Using a command button that inputs the merge field instead of copying and pasting will illuminate user error and speed up this process. Any help is much appreciated.
A macro that places a multi-nested conditional IF statement into a
document.
Below is the code I created. Where it reads, “truetext:=”True,” is where I need to insert another merge field.
Thank you for reading and for your interest!
Dim doc As Word.Document
Dim mName As String
Dim dField As Word.MailMergeDataField
Set doc = ActiveDocument
doc.MailMerge.Fields.Add Range:=Selection.Range, Name:="""Client_FirstName"""
Selection.TypeText Text:=" "
doc.MailMerge.Fields.AddIf Range:=Selection.Range, _
mergefield:="""Client_MiddleName""", Comparison:=wdMergeIfIsNotBlank, _
truetext:="True", _
falsetext:="False"
Selection.TypeText Text:=" "
doc.MailMerge.Fields.Add Range:=Selection.Range, _
Name:="""Client_LastName"""
doc.MailMerge.Fields.AddIf Range:=Selection.Range, _
mergefield:="""Client_NameSuffix""", Comparison:=wdMergeIfIsNotBlank, _
truetext:="""Client_NameSuffix""", _
falsetext:=""
Selection.TypeText Text:=" "

Run-time error 4198, command failed, when trying to set ms word doc to print view

I am trying to set the window view to printView.
I've used the "record macro" in word, to see how word suggests I set something to print view. Here's the code:
If ActiveWindow.View.SplitSpecial = wdPaneNone Then
ActiveWindow.ActivePane.View.Type = wdPrintView
Else
ActiveWindow.View.Type = wdPrintView
End If
Each time, the execution stops and gives me the above error. The debug points out:
ActiveWindow.View.Type = wdPrintView
as the buggy line. I've also tried:
If ActiveWindow.View.SplitSpecial = wdPaneNone Then
ActiveDocument.ActiveWindow.View.Type = wdPrintView
Else
ActiveWindow.View.SplitSpecial = wdPaneNone
ActiveWindow.View.Type = wdPrintView
End If
The issue seems to happen when the splitspecial is 4 (wdPanePrimaryFooter). But changing the conditional to account for that doesn't seem to work. If I comment out the view type line, everything goes fine.
Any ideas?
Thank you in advance.
Edit, here is the entire block, but I cannot replicate this error half the time:
Sub pageNumber()
ActiveDocument.Sections(ActiveDocument.Sections.Count) _
.Footers(wdHeaderFooterPrimary).Range.Select
With Selection
.ParagraphFormat.Alignment = wdAlignParagraphCenter
.TypeText Text:="Page "
.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"PAGE ", PreserveFormatting:=True
.TypeText Text:=" of "
.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"NUMPAGES ", PreserveFormatting:=True
.Collapse
End With
ActiveDocument.Content.Select
Selection.Collapse wdCollapseStart
If ActiveWindow.View.SplitSpecial = wdPaneNone Then
ActiveDocument.ActiveWindow.View.Type = wdPrintView
Else
ActiveWindow.View.SplitSpecial = wdPaneNone
ActiveWindow.View.Type = wdPrintView
End If
End Sub
The kind of code in the question is the result of using the macro recorder. This tool is really great, but because it only mimics the user actions, the code it creates is sometimes not optimal. Working with headers and footers, especially, can make life more complicated than it ought to be... When code selects a header/footer range that triggers the display of the old Word 2.0 "panes" that were necessary for editing these. Word 6.0 introduced WYSIWYG and the panes were "retired" and only show up in this context.
When working with headers and footers a Range object is usually preferable than using Selection. You can think of a Range as a invisible selection, with the advantages: 1. It doesn't move the actual selection. 2. There can be as many Range objects as required for the task, while there can be only one selection.
The following code sample gets the Footer range and adds content to it. Since it never changes the selection, the screen is quieter and the pane never shows up (and the code is faster).
Working with ranges is relatively straight-forward, until field codes come into play. Then it takes a bit of work to get the "target" point for new material to follow a field.
Sub pageNumber()
Dim rngFooter As Word.Range
Dim fld As Word.Field
Set rngFooter = ActiveDocument.Sections(ActiveDocument.Sections.Count) _
.Footers(wdHeaderFooterPrimary).Range
With rngFooter
.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Text = "Page "
.Collapse wdCollapseEnd
Set fld = .Fields.Add(Range:=rngFooter, Type:=wdFieldEmpty, Text:= _
"PAGE ", PreserveFormatting:=False)
End With
Set rngFooter = fld.result
With rngFooter
'Move the end of the range outside the field
.MoveStart wdCharacter, 1
.InsertAfter " of "
.Collapse wdCollapseEnd
.Fields.Add Range:=rngFooter, Type:=wdFieldEmpty, Text:= _
"NUMPAGES ", PreserveFormatting:=False
End With
End Sub

How do you capture the number of lines in a paragraph in a word document using a macro?

I'm working on spacing on a word document and I need to vary the location of page breaks and number of blank paragraphs for spacing that the macro inputs based on the number of lines of a previous paragraph so that the 2 fields that are input by the ClientNameandDate sub are on the same page.
I've used the number of agents to vary the spacing, but the problem is that some agents' information takes up more space than others, and therefore the variable length paragraph may have a different number of lines even when the number of agents is the same. This results in the macro sometimes generating a blank page, which I don't want. The HIPAANumber variable is the one that stores how many agents there are on the form. I looked at the options when I write Selection. and Selection.Paragraph. but none of the options seem to capture the information I need.
With Selection
If HIPAANumber > 2 And HIPAANumber < 5 Then
.InsertBreak Type:=wdPageBreak
End If
Call ClientNameandDate(ClientName) 'The Sub inputs the Date and Client's Name fields. These fields always take up the same amount of space.
.TypeParagraph
If HIPAANumber <= 2 Then
.InsertBreak Type:=wdPageBreak
Else
.TypeParagraph
End If
End With
Private Sub ClientNameandDate(ClientName)
Selection.TypeParagraph
With Selection
.ParagraphFormat.Alignment = wdAlignParagraphLeft
.TypeText Text:="_______________________________" 'This code inputs the Date field
.TypeText Text:=Chr(11)
.TypeText Text:="Date"
.TypeParagraph
.Font.Size = 4
.TypeText Text:=Chr(11)
.Font.Size = 12
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & vbTab & vbTab & "__________________________________________"
.TypeText Text:=Chr(11)
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & vbTab & vbTab
.Font.Bold = True
.TypeText Text:=UCase(ClientName)
End With
End Sub
'''
I don't really know how to use objects in VBA, so if someone could explain how to use objects for this, I would really appreciate it. I think the easiest way to do this is to capture the number of lines of text in the paragraph that has a variable length and then use that in an If statement later, but I don't know how to capture the number of lines of text of a paragraph.
The Information property can return a line number, as in the following code.
Sub CountLinesInTheSelectedParagraph()
Dim rngFirst As Range, rngLast As Range
Set rngFirst = Selection.Range
rngFirst.Expand Unit:=wdParagraph
rngFirst.Collapse Direction:=wdCollapseStart
Set rngLast = Selection.Range
rngLast.Expand Unit:=wdParagraph
rngLast.Collapse Direction:=wdCollapseEnd
Debug.Print _
rngLast.Information(Type:=wdFirstCharacterLineNumber) _
- rngFirst.Information(Type:=wdFirstCharacterLineNumber) _
& " lines in the selected paragraph"
End Sub

How to insert PRINTDATE field code in a sentence using Word VBA?

I'd like to get the following sentence inside my doc: "This document was last printed on 01/01/2019 2:10 AM". The date and time must be dynamic. Right now I only have this part:
Element.Range.Text = "This document was last printed on "
It works, but it's missing the date part. What should I do to get the PRINTDATE field concatenated into this sentence?
I tried
Selection.Fields.Add Range:=.Footers(wdHeaderFooterPrimary).Range, Type:=wdFieldPrintDate, Text:="\#""DD MMM YYYY""", preserveformatting:=True
and it works, but it's overwriting all the footer, how can I append it to the text to make it similar to my example?
To access the Footer associated with a Selection:
Dim rng as Word.Range
Set rng = Selection.Sections(1).Footers(wdHeaderFooterPrimary).Range
To then append to that Range:
rng.InsertAfter " This document was last printed on " 'don't forget a space at the beginning
rng.Collapse wdCollapseEnd 'so the inserted field comes AFTER
rng.Fields.Add Range:=rng, Type:=wdFieldPrintDate, _
Text:="\#""DD MMM YYYY""", preserveformatting:=False
Note: I highly recommend using PreserveFormatting:=False as the field is more likely to pick up the formatting of the surrounding text if other formatting is applied. Setting this to True will retain the originally applied formatting for the number of characters originally in the field. If the field is updated and the number of characters changes, some of the characters may be formatted differently from the rest.
Indeed, I prefer using the method more as follows, with all the field content in the Text parameter, including the CharFormat switch. CharFormat will force the entire field to use the character formatting applied to the first character in the field code - much more reliable:
rng.Fields.Add Range:=rng, Type:=wdFieldEmpty, _
Text:="PrintDate \#""DD MMM YYYY"" \* CharFormat", preserveformatting:=False
The code below will change all footers in a document to show "The document was last printed on {dd.mm.yyyy}. It might be modified not to replace all of the footer.
Sub ModifyFooter()
' 03 Jan 2019
Dim Doc As Document
Dim Txt As String
Dim Foot As HeaderFooter
Dim Para As Paragraph
Dim Rng As Range
Dim i As WdHeaderFooterIndex
Set Doc = ActiveDocument
For i = wdHeaderFooterPrimary To wdHeaderFooterFirstPage
Set Foot = Doc.Sections(1).Footers(i)
Txt = "This document was last printed on "
Set Para = Foot.Range.Paragraphs(1)
Set Rng = Para.Range
With Rng
.Text = Txt
.Collapse wdCollapseEnd
End With
Txt = "\# ""dd.MM.yyyy"""
Doc.Fields.Add Rng, wdFieldPrintDate, Text:=Txt, PreserveFormatting:=True
Next i
End Sub
Try:
With ActiveDocument
.Fields.Add Range:=Selection.Sections.First.Footers(wdHeaderFooterPrimary).Range.Characters.Last, _
Type:=wdFieldEmpty, Text:="PRINTDATE \#""'This document was last printed on 'DD MMM YYYY""", PreserveFormatting:=False
End With

Insert blank lines in a document before creating a table

I am creating a table in a word document - but want to add 2 blank lines before creating the table. The code below creates the blank lines but I need to move the cursor (clear the selection) before creating the table. The code currently creates the tables on top of the 2 new blank lines.
I'm sure I'm missing one simple line of code :). Thanks for your help!
With ActiveDocument.Sections(1)
Selection.InsertParagraph
Selection.InsertParagraph
End With
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=1, NumColumns:=2
1. method:
Selection.TypeParagraph
Selection.TypeParagraph
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=1, NumColumns:=2
2. method:
Selection.InsertParagraph
Selection.InsertParagraph
Selection.EndKey Unit:=wdStory
ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=1, NumColumns:=2