I am trying to develop vba that inserts a Cover Page that is identical to that inserted when one uses the Insert Cover Page command in the UI.
In current Windows versions of Word (2016+) this
The best I've been able to come up with is the following vba which uses a Section break. The page will be counted in the NumPages field as well as the Pages document property. I've explored this in my writing in my chapter on Sections as Cover Page Anomalies.
Selection.HomeKey Unit:=wdStory
Selection.InsertBreak Type:=wdSectionBreakNextPage
Selection.EndKey Unit:=wdStory
Selection.HomeKey Unit:=wdStory
With Selection.Sections(1).Headers(1).PageNumbers
.NumberStyle = wdPageNumberStyleArabic
.HeadingLevelForChapter = 0
.IncludeChapterNumber = False
.ChapterPageSeparator = wdSeparatorHyphen
.RestartNumberingAtSection = True
.StartingNumber = 0
End With
With ActiveDocument
.Sections(2).Headers(wdHeaderFooterFirstPage).LinkToPrevious = False
.Sections(2).Footers(wdHeaderFooterFirstPage).LinkToPrevious = False
.Sections(1).PageSetup.DifferentFirstPageHeaderFooter = True
.Sections(1).Headers(wdHeaderFooterFirstPage).Range.Text = ""
.Sections(1).Footers(wdHeaderFooterFirstPage).Range.Text = ""
End With
I do not know of any Word command or vba command that corresponds to the user interface command. Is there a way to use vba to insert a Cover Page that gives the same result as using the command in the UI?
You could try the following as a starting point for the Cover Page insertion, assuming that you want to insert the built-in cover page called "Whisp". You may still have to deal with the First Page section issue etc.
Sub InsertWhispCoverPage()
Dim bb As Word.BuildingBlock
Dim d As Word.Document
Set d = ActiveDocument
Set bb = getCPBBOrNothing("Whisp")
If bb Is Nothing Then
Debug.Print "Could not find the specified cover page"
Else
' Perhaps need to deal with things at the beginning of the doc. that cannot be overwritten
' but if we don't insert the Page Break first,
' the Cover Page layout will probably break, e.g. one or
' more of the floating content controls may be re-anchored
' on the next page. It looks like trying any other approach
' would make it almost impossible to get the Page back to how
' it should be.
d.Range(0, 0).InsertBreak Word.WdBreakType.wdPageBreak
bb.Insert where:=d.Range(0, 0), RichText:=True
End If
Set d = Nothing
Set bb = Nothing
End Sub
Function getCPBBOrNothing(BBName As String) As BuildingBlock
Dim i As Long
Dim j As Long
Dim k As Long
With Application.Templates
.LoadBuildingBlocks
For i = 1 To .Count
With .Item(i).BuildingBlockTypes(wdTypeCoverPage).Categories
For j = 1 To .Count
With .Item(j).BuildingBlocks
For k = 1 To .Count
If .Item(k).Name = "Whisp" Then
Debug.Print .Item(k).Category.Name, .Item(k).Type.Name
Set getCPBBOrNothing = .Item(k)
Exit Function
End If
Next
End With
Next
End With
Next
End With
End Function
This raises several questions, such as "how are you actually deciding which cover page to use", "are you actually trying to do this without using a cover page?", "what does Word do with pagination and headers with various different document layouts, e.g. double-sided, facing pages layouts", and so on.. I feel sure that the building blocks could be handled better than I have done.
The problem if you are trying to avoid using a Cover Page Building Block is that as @TimothyRylatt mentioned, it's the building block that triggers the page numbering behaviour. I had a look at the inserted OOXML and the Document Part starts something like this
<w:body>
<w:sdt>
<w:sdtPr>
<w:id w:val="1382976450"/>
<w:docPartObj>
<w:docPartGallery w:val="Cover Pages"/>
<w:docPartUnique/>
</w:docPartObj>
</w:sdtPr>
<w:sdtContent>
followed by the content of the sdt, then closing with
</w:sdtContent>
</w:sdt>
and eventually
</w:body>
You might be able to simulate having a suitable Building Block Building Block and inserting that. I haven't tried. Failing that, I have now tried inserting the necessary <w:sdt> code using Range.InsertXML. It seems to work. I think the most you need is
<w:sdt>
<w:sdtPr>
<w:docPartObj>
<w:docPartGallery w:val="Cover Pages"/>
<w:docPartUnique/>
</w:docPartObj>
</w:sdtPr>
</w:sdt>
You have to have the w:val
attribute in the DocPartGalleryElement
and it has to be set to "Cover Pages"
Some code for doing that, starting with an empty document:
Sub insertCPsdt()
Dim sa As String ' Essential Flat OPC format "head"
Dim s As String ' The document content you want to insert
Dim sz As String ' Essential Flat OPC format "tail"
sa = ""
sa = sa & "<pkg:package xmlns:pkg=""http://schemas.microsoft.com/office/2006/xmlPackage"">" & vbCrLf
sa = sa & " <pkg:part pkg:name=""/_rels/.rels"" pkg:contentType=""application/vnd.openxmlformats-package.relationships+xml"" pkg:padding=""512"">" & vbCrLf
sa = sa & " <pkg:xmlData>" & vbCrLf
sa = sa & " <Relationships xmlns=""http://schemas.openxmlformats.org/package/2006/relationships"">" & vbCrLf
sa = sa & " <Relationship Id=""rId1"" Type=""http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"" Target=""word/document.xml""/>" & vbCrLf
sa = sa & " </Relationships>" & vbCrLf
sa = sa & " </pkg:xmlData>" & vbCrLf
sa = sa & " </pkg:part>" & vbCrLf
sa = sa & " <pkg:part pkg:name=""/word/document.xml"" pkg:contentType=""application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"">" & vbCrLf
sa = sa & " <pkg:xmlData>" & vbCrLf
sa = sa & " <w:document xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">" & vbCrLf
sa = sa & " <w:body>" & vbCrLf
s = "<w:sdt><w:sdtPr><w:docPartObj><w:docPartGallery w:val=""Cover Pages""/></w:docPartObj></w:sdtPr></w:sdt>" & vbCrLf
sz = ""
sz = sz & " </w:body>" & vbCrLf
sz = sz & " </w:document>" & vbCrLf
sz = sz & " </pkg:xmlData>" & vbCrLf
sz = sz & " </pkg:part>" & vbCrLf
sz = sz & "</pkg:package>" & vbCrLf
ActiveDocument.Range(0, 0).InsertXML sa & s & sz
End Sub
This was all done in the current version of Word 365 on Windows. The Cover Page XML contains a fair amount of "compatibility mode" XML which may make some differences to the page behaviour in different versions, but my guess is that it is the version of Word itself that decides about the page numbering and not something in the compatibility code that tells it to do so.