Ty Anderson

Working with Word document designs, styles and printing

I know a gentleman that likes to send emails to his “email list”. I put it in quotes because I’m on the list and I didn’t sign up. He knows me, put me on his list, and there I will stay. There is no mechanism for removal.

And… I DON’T CARE!

Designers

Why? Because the emails are terrible and I find that entertaining. Actually, I don’t know for certain if they are terrible. I’ve never read one from start to finish. I simply assume they are terrible because they look terrible. They are just a bunch of words with no thought to style and formatting. There is nothing that draws your eye to the content and says “look at me? I’m important! READ ME! READ ME FIRST! Read Me if you read nothing else!”

Treating your readers in this manner IS terrible. It’s not mannerly and it’s disrespectful. Worse, it is a waste of the author’s time and energy.

I like to say to anyone who will listen (and to many others who will not) that, “You have to respect the reader.” Meaning, you need to make the document easy and entertaining to read. It can’t be painful to the eyes. Instead, your document must please the reader’s eye and invite the reader to stay, read, and learn a thing or two.

This is exactly my aim today as I explain how to work with Microsoft Word document design elements as well printing objects.

Styles

Designing Microsoft Word documents is not all that different from designing a web page; you want to keep the content and the design separate. In Word, you keep them separate by utilizing styles. Styles include a plethora of design elements (e.g. font, borders, paragraph format, etc). Let’s have some fun with them via code.

I’m taking the first person view with today’s samples. These are things I would find useful in my writing life… if only I would turn them into a viable add-in.

Enumerate styles

It’s always good to know how to loop through a collection and process all of its objects in one fell swoop. I especially like working with the Styles collection because each style has a slightly different purpose. In this sample, I perform a loop around the Styles collection and change the font to the best font ever.

Private Sub EnumerateStyles()
    Dim curDoc As Word.Document
    curDoc = WordApp.ActiveDocument
 
    Dim i As Integer
 
    'Change all styles to use my favorite font :-)
    For i = 1 To curDoc.Styles.Count
        With curDoc.Styles.Item(i)
            .Font.Name = "Comic Sans MS"
        End With
    Next
 
    Marshal.ReleaseComObject(curDoc)
End Sub

This should be the default font. Anyone can use Helvetica or Arial. It takes an artist to use this font.

Setup styles

When I create a new Word document or receive one to edit, I find I am always enhancing the heading styles. If the document involves code, I typically add a code style as well. I realize I could add these styles to a template and attach it but that is not how I like to automate. Templates are for users while code is for developers.

In this sample, I add two styles to the document and enhance two others.

Private Sub SetupMyWritingHeadings()
    Dim curDoc As Word.Document
    curDoc = WordApp.ActiveDocument
    Dim styleTitle As Word.Style
    Dim styleCode As Word.Style
 
    'Add Article Title style
    styleTitle = curDoc.Styles.Add(Name:="ArticleTitle", _
                                   Type:=Word.WdStyleType.wdStyleTypeParagraph)
    With styleTitle.Font
        .Bold = True
        .Name = "Arial"
        .Size = 28
        .Underline = Word.WdUnderline.wdUnderlineSingle
        .AllCaps = True
    End With
    styleTitle.ParagraphFormat.SpaceAfter = 12
 
    'Add Code Sample  style
    styleCode = curDoc.Styles.Add(Name:="CodeSample", _
                                  Type:=Word.WdStyleType.wdStyleTypeParagraph)
    With styleCode.Font
        .Bold = False
        .Name = "Consolas"
        .Size = 9
    End With
    With styleCode.ParagraphFormat
        .SpaceAfter = 6
        .SpaceBefore = 6
    End With
    'Don't include this style in Spell Checks
    styleCode.NoProofing = True
 
    'Change the default headings to how I like them
    With curDoc.Styles(Word.WdBuiltinStyle.wdStyleHeading1)
        .Font.Bold = True
        .Font.Size = 18
        .Font.Name = "Arial"
        .NameLocal = "Heading1"
        .ParagraphFormat.SpaceBefore = 12
        .ParagraphFormat.SpaceAfter = 6
        .ParagraphFormat.PageBreakBefore = True
        .ParagraphFormat.KeepWithNext = True
    End With
 
    'Change the default headings to how I like them
    With curDoc.Styles(Word.WdBuiltinStyle.wdStyleHeading2)
        .Font.Bold = True
        .Font.Size = 14
        .Font.Name = "Arial"
        .NameLocal = "Heading2"
        .ParagraphFormat.SpaceBefore = 9
        .ParagraphFormat.SpaceAfter = 3
        .ParagraphFormat.KeepWithNext = True
    End With
 
    With curDoc.Styles(Word.WdBuiltinStyle.wdStyleNormal)
        .Font.Bold = False
        .Font.Size = 11
        .Font.Name = "Arial"
        .ParagraphFormat.SpaceBefore = 0
        .ParagraphFormat.SpaceAfter = 3
        .ParagraphFormat.KeepTogether = True
    End With
 
    Marshal.ReleaseComObject(styleTitle)
    Marshal.ReleaseComObject(styleCode)
    Marshal.ReleaseComObject(curDoc)
End Sub

The code adds two styles: ArticleTitle and CodeSample. For each, the code sets font properties and paragraph format properties. The ParagraphFormat property allows me to control spacing and document flow options like KeepWithNext and PageBreakBefore.

Notice the CodeSample style’s NoProofing property is set to true. This value prevents Microsoft Word from lighting-up with red squiggly, spell-check, lines. Instead, Word ignores this style when spell checking.

Notice too that I rename the styles for Heading 1 and Heading 2. Renaming them using this technique allows me to call them by name when needed. For example, when looking for them as the next sample “samplifies” (My word… I thought about using illustrates but I am not drawing. I am providing samples (VB.NET).

Change to sentence case

Here at the Add-in Express blog, we use Sentence case for headings. I forget about this standard often. This code corrects the issue.

Private Sub ChangeAllHeadingsToSentenceCase(headingLevelName As String)
    'Find each heading1
    'Change to SentenceCase
    Dim curDoc As Word.Document = WordApp.ActiveDocument
 
    With WordApp.Selection.Find
        .ClearFormatting()
        .Forward = True
        .Text = ""
        .Style = curDoc.Styles(headingLevelName)
        .Execute()
        While .Found
            WordApp.Selection.Range.Case = Word.WdCharacterCase.wdTitleSentence
            WordApp.Selection.Collapse(Word.WdCollapseDirection.wdCollapseEnd)
            .Execute()
        End While
    End With
 
    Marshal.ReleaseComObject(curDoc)
End Sub

I can call the ChangeAllHeadingsToSentenceCase procedure and pass the heading name. This allows for finer control. The code executes Find using the passed heading name. If found, the code loops through the found heading items and changes their case to sentence case. This is guaranteed to make Sveta happy!

Apply a style

When I write an article that includes code samples, I paste the code into Word. I then apply the CodeSample style to it. Sure, I can use the Style Gallery to do it but the following code can be called from anywhere.

Private Sub ApplyCodeSampleStyle()
 
    WordApp.Selection.GoTo(What:=Word.WdGoToItem.wdGoToBookmark, Name:="\para")
    'This will fail if the style does not exist.
    WordApp.Selection.Style = WordApp.ActiveDocument.Styles("CodeSample")
 
End Sub

The code utilizes a built-in paragraph bookmark to select the entire paragraph. It then applies CodeSample style. Easy-peasy.

Fonts

List fonts

For Word fonts, the common use case is to apply a font to selection of text and then format the font settings. The ListFonts procedure does this and more. Run this puppy and you will have a nice font document that lists each of your installed font name while also providing of a display sample for each.

Private Sub ListFonts()
    Dim newDoc As Word.Document
    Dim fontTable As Word.Table
 
    'Create a document to contain the list of Fonts
    newDoc = WordApp.Documents.Add
    'Add a title to the document and apply the Title Style
    WordApp.Selection.Style = newDoc.Styles("Title")
    WordApp.Selection.Text = "Font List & Samples"
    WordApp.Selection.InsertParagraphAfter()
 
    Dim i As Integer
 
    'Borrowed and adapted from 
    'https://support.microsoft.com/kb/209205
    'Add a table and set the table header
    fontTable = newDoc.Tables.Add( _
        WordApp.Selection.Range, WordApp.FontNames.Count + 1, 2)
    With fontTable
        .Borders.Enable = False
        .Cell(1, 1).Range.Font.Name = "Arial"
        .Cell(1, 1).Range.Font.Bold = 1
        .Cell(1, 1).Range.InsertAfter("Font Name")
        .Cell(1, 2).Range.Font.Name = "Arial"
        .Cell(1, 2).Range.Font.Bold = 1
        .Cell(1, 2).Range.InsertAfter("Font Example")
    End With
    'Go through all the fonts and add them to the table
    For i = 1 To WordApp.FontNames.Count
        With fontTable
            .Cell(i + 1, 1).Range.Font.Name = "Arial"
            .Cell(i + 1, 1).Range.Font.Size = 10
            .Cell(i + 1, 1).Range.InsertAfter(WordApp.FontNames(i))
            .Cell(i + 1, 2).Range.Font.Name = WordApp.FontNames(i)
            .Cell(i + 1, 2).Range.Font.Size = 10
            .Cell(i + 1, 2).Range.InsertAfter("ABCDEFG abcdefg 1234567890")
        End With
    Next i
    fontTable.Sort(SortOrder:=Word.WdSortOrder.wdSortOrderAscending)
 
    Marshal.ReleaseComObject(fontTable)
    Marshal.ReleaseComObject(newDoc)
End Sub

The code creates title and then loops through the FontNames collection to build a table of font samples. Notice the use of the Range object. The Range contains the area where the code inserts new text and the Font formatting occurs.

Themes ( aka QuickStyles)

Word provides a gallery of themes or quick styles that allow users to quickly change the entire look and feel of a Word document. You can control the application of themes as well as save new ones.

Apply a quick style

To apply a theme takes a single line of code:

Private Sub ApplyTheme(themeName As String)
    WordApp.ActiveDocument.ApplyQuickStyleSet2(themeName)
End Sub

This method accepts a theme name as a parameter and then applies it. The code also assumes the theme exists. You might prefer to add error handling in case the theme does not exist.

Note. If you apply a theme and have custom styles in the document, the custom styles will be unaffected by the new theme. Just wanted you to know.

Saving a quick style

You can save a style just as easily as you apply one.

Private Sub SaveDocumentStylingsAsAQuickStyle(styleName)
    WordApp.ActiveDocument.SaveAsQuickStyleSet(styleName)
End Sub

The code above will take all the styles within the current Word document and add a new theme. This theme will be available in the Design tab under Document Formatting.

Page layout and printing documents

Formatting and styling are one thing. Printing is another. In some ways, getting the print job executed correctly is 80% of the battle. I know because I have a finicky HP printer that never cooperates. Anyway, the next two code chunks samplify how to take some control of the print process within Microsoft Word.

Configure page setup

For some print jobs, I want to print the first page on nicer piece of paper. This first page is the report cover sheet and resides in the lower bin of my printer. The other pages can print on paper in the default bin. This method takes care of things for me.

Private Sub ConfigThePageSetupForReports(showFieldCodes As Boolean)
    With WordApp.Selection.PageSetup
        .Orientation = Word.WdOrientation.wdOrientPortrait
        'I like the cover page to print on thicker paper
        .FirstPageTray = Word.WdPaperTray.wdPrinterLowerBin
        'After the first page, pring to the default bin
        .OtherPagesTray = Word.WdPaperTray.wdPrinterDefaultBin
        .HeaderDistance = 25
        .TopMargin = WordApp.InchesToPoints(3) 'Our letterhead has a really large logo
    End With
    WordApp.ActiveWindow.View.ShowFieldCodes = showFieldCodes
End Sub

For fun, I set the HeaderDistance to large size to allow for a ridiculous amount of space. I don’t actually have a large logo in my letterhead. But if you do, you now know how to allow room for it. Just note that changes like this will impact your document pagination.

The procedure has Boolean parameter used to hide or show field codes. I sometimes need to see the field codes and you might too.

The DocumentBeforePrint event

The DocumentBeforePrint allows us to control and edit the print job immediately after the user clicks the print button. It’s the ideal place to apply your business logic.

In my scenario, I have three printers.

  1. An envelope printer for printing envelopes
  2. A legal printer for printing to legal-sized paper
  3. A printer contain standard-sized paper

The code takes a look at the document’s PaperSize property and branches.

Private Sub adxWordEvents_DocumentBeforePrint(sender As Object, _
    e As ADXHostBeforeActionEventArgs) Handles adxWordEvents.DocumentBeforePrint
 
    'If document's Page size is legal send to the bottom tray
    Dim docToPrint As Word.Document = WordApp.ActiveDocument
 
    Select Case docToPrint.PageSetup.PaperSize
        Case Word.WdPaperSize.wdPaperEnvelopePersonal
            WordApp.ActivePrinter = "Envelope Printer"
        Case Word.WdPaperSize.wdPaperLegal
            WordApp.ActivePrinter = "Legal Printer"
            ConfigThePageSetupForReports(False)
 
        Case Else
            WordApp.ActivePrinter = "Standard Printer"
    End Select
 
    Marshal.ReleaseComObject(docToPrint)
End Sub

If the paper size is legal, the code changes the ActivePrinter to the legal printer. This is the printer for some fancy reports with fancy report paper, therefore, it calls the ConfigThePageSetupForReports procedure to set things up.

***

Working with Word document designs and automating the design process is a deep topic. This is an area where you, as a Word solution developer, can dig-in and provide valuable features to your users.

Available downloads:

This sample Word add-in was developed using Add-in Express for Office and .net:

VB.NET Word Document Designs add-in

Word add-in development in Visual Studio for beginners:

Post a comment

Have any questions? Ask us right now!