Not long ago I explained how to work with Microsoft Excel spreadsheets using PowerShell. Today, I'll show you how you can easily use PowerShell as a "macro language" to create and modify Word documents.

To manipulate Word documents with PowerShell, you first have to create a Word Application COM object.

Creating Word Application COM object

Creating Word Application COM object

As you can see below there are a lot of options to work with:

Word COM methods and properties

Word COM methods and properties

To create a new Word document with PowerShell, you can use the commands below:

$word = New-Object -ComObject "Word.application"
$word.Visible = $true
$document = $word.documents.Add()

I assign $true to the $word.Visible property, so I can see the document I'm working on in Word.

Now let's add a "nice" title to the document:

$word = New-Object -ComObject "Word.application"
$word.Visible = $true
$document = $word.documents.Add()
$selection = $word.selection
$selection.font.size = 14
$selection.font.bold = 1
$selection.Style ="Title"
$selection.typeText("Nice Title")
$selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"

I used the selection property and its font, typetext, and ParagraphFormat methods to put text into the newly created Word document, set the font size, set the text in bold, change its style, and center the title. Below you can see the result of these PowerShell commands:

The title of a Word document created with PowerShell

The title of a Word document created with PowerShell

Next, I'll add a little calendar in the form of a table to our document:

$selection.TypeParagraph()
$Range = $selection.Range
$Table = $document.Tables.Add($Range,6,7)
$Table.AutoFormat(11)
$Table.Borders.InsideLineStyle = 1

I added a new paragraph to my document using the Selection object and read the Range property of the selection, so I know where I'm adding the table. Then I use the Table method of the Word COM application object to add new table.

I am using the AutoFormat property to choose the table format. I just played with the format numbers till I found something I like. Then I'm using the InsideLineStyle property to make the inside borders of my table visible. Finally, I add column captions to my table:

$Column = 1
$Row = 1
$SysDateObject = new-object system.globalization.datetimeformatinfo
$DayNames = $SysDateObject.Daynames
$DayNames | %{
   $Table.Cell($Column,$Row).Range.Text = $_
   $Table.Cell($Column,$Row).Range.Font.Name = "Forte"
   $Row++
   }

Since I'm working with a table, I need to establish cell coordinates so I can manipulate the cells. Thus, I add $Row and $Column variables and assign 1 to each of them. Then I get the weekday names from the PowerShell system.globalization.datetimeformatinfo object and assign them to the top cells of my table. To make them look a little better, I change the font. And this is how my Word document looks now:

A Word table created with PowerShell

A Word table created with PowerShell

I have weekday names, but it would be nice to add dates to my little calendar:

$i = 1
$Column = 2
$Row = 2
for($i -eq 1; $i -le [datetime]::DaysInMonth(17,5); $i++){
    $Table.Cell($Row,$Column).Range.Text = $i
    $Table.Cell($Row,$Column).Range.ParagraphFormat.Alignment = "wdAlignParagraphRight"
    $Column++
    if($Column -gt 7){
       $Row++
       $Column = 1
       }
    }

Firstly, I set up some variables: $i will be my day index, and you already know $Row and $Column. I get the number of days in May from the datetime PowerShell object and then loop from 1 to 31, because May has 31 days. Then I assign the value of $i to the corresponding cell. Because I have only seven columns, I reset the $Column value to 1 every time it becomes greater than 7.

And this is my calendar:

The Word calendar with dates

The Word calendar with dates

Here is the entire script that adds a title and table to a Word document using PowerShell:

$word = New-Object -ComObject "Word.application"
$word.Visible = $true
$document = $word.documents.Add()
$selection = $word.selection
$selection.font.size = 14
$selection.font.bold = 1
$selection.Style ="Title"
$selection.typeText("Nice Title")
$selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"
$selection.TypeParagraph()
$Range = $selection.Range
$Table = $document.Tables.Add($Range,6,7)
$Table.AutoFormat(11)
$Table.Borders.InsideLineStyle = 1
$Column = 1
$Row = 1
$SysDateObject = new-object system.globalization.datetimeformatinfo
$DayNames = $SysDateObject.Daynames
$DayNames | %{
   $Table.Cell($Row,$Column).Range.Text = $_
   $Table.Cell($Row,$Column).Range.Font.Name = "Forte"
   $Column++
   }
$i = 1
$Column = 2
$Row = 2
for($i -eq 1; $i -le [datetime]::DaysInMonth(17,5); $i++){
    $Table.Cell($Row,$Column).Range.Text = $i
    $Table.Cell($Row,$Column).Range.ParagraphFormat.Alignment = "wdAlignParagraphRight"
    $Column++
    if($Column -gt 7){
       $Row++
       $Column = 1
       }
    }
    
$word = New-Object -ComObject "Word.application"
$word.Visible = $true
$document = $word.documents.Add()
$selection = $word.selection
$selection.font.size = 14
$selection.font.bold = 1
$selection.Style ="Title"
$selection.typeText("Nice Title")
$selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"
$selection.TypeParagraph()
$Range = $selection.Range
$Table = $document.Tables.Add($Range,6,7)
$Table.AutoFormat(11)
$Table.Borders.InsideLineStyle = 1
$Column = 1
$Row = 1
$SysDateObject = new-object system.globalization.datetimeformatinfo
$DayNames = $SysDateObject.Daynames
$DayNames | %{
   $Table.Cell($Row,$Column).Range.Text = $_
   $Table.Cell($Row,$Column).Range.Font.Name = "Forte"
   $Column++
   }
$i = 1
$Column = 2
$Row = 2
for($i -eq 1; $i -le [datetime]::DaysInMonth(17,5); $i++){
    $Table.Cell($Row,$Column).Range.Text = $i
    $Table.Cell($Row,$Column).Range.ParagraphFormat.Alignment = "wdAlignParagraphRight"
    $Column++
    if($Column -gt 7){
       $Row++
       $Column = 1
       }
    }

Now let's do something a bit more complicated. Let's create a calendar for 2018 using PowerShell and Word.

Let's start from the title. There is nothing new here except the $END_OF_STORY variable, which represents the end of the Word document.

$word = New-Object -ComObject "Word.application"
$END_OF_STORY = 6
$word.Visible = $true
$document = $word.documents.Add()
$SysDateObject = new-object system.globalization.datetimeformatinfo
$DayNames = $SysDateObject.Daynames
$selection = $word.selection
$selection.font.size = 14
$selection.font.bold = 1
$selection.Style ="Title"
$selection.typeText("2018 Calendar")
$selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"

To add a calendar for each month, I will use a loop that iterates through the months from 1 to 12. I'm using the get-date PowerShell function to get the first weekday for each month.

$y = 1
for($y -eq 1; $y -le 12; $y++){
    $CURRENTDATE=GET-DATE "$y/1/2018"
    $FirstDayofMonth = ($CURRENTDATE).DayOfWeek.value__ +1
    if($FirstDayofMonth -gt 7){
       $FirstDayofMonth = 1
       $FirstDayofMonth
      }

Next I add a new page to the document and create a title for it. Because I'm still inside the for loop, the title will be the name of the current month, which the $CMonth variable represents. Then I'm adding the weekday names to the calendar:

$selection.InsertNewPage()
    $selection.font.size = 14
    $selection.font.bold = 1
    $selection.Style ="Title"
    $CMonth = (Get-Culture).DateTimeFormat.GetMonthName($CURRENTDATE.Month)
    $selection.typeText("$CMonth 2018")
    $selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"
    $selection.TypeParagraph()
    $Range = $selection.Range
    $Table = $document.Tables.Add($Range,7,7)
    $Table.AutoFormat(11)
    $Table.Borders.InsideLineStyle = 1
    $Column = 1
    $Row = 1
    $DayNames | %{
        $Table.Cell($Row,$Column).Range.Text = $_
        $Table.Cell($Row,$Column).Range.Font.Name = "Forte"
        $Column++
    }

Now I'm putting days into my table starting at the $FirstDayOfMonth column number, which I calculated before. And when all days are in place, I need to move the cursor to the end of the document, so it will add a new page in the cycle's next iteration at the end of the document.

 $i = 1
    $Column = $FirstDayofMonth
    $Row = 2
    $DMonth = $CURRENTDATE.Month
    for($i -eq 1; $i -le [datetime]::DaysInMonth(18,$DMonth); $i++){
        $Table.Cell($Row,$Column).Range.Text = $i
        $Table.Cell($Row,$Column).Range.ParagraphFormat.Alignment = "wdAlignParagraphRight"
        $Column++
    if($Column -gt 7){
       $Row++
       $Column = 1
       }
    }
    $selection.EndKey($END_OF_STORY)
}

And here is how my calendar for 2018 looks:

Word document calendar page created by PowerShell

Word document calendar page created by PowerShell

Below is the entire script to create a calendar in Word with PowerShell:

Subscribe to 4sysops newsletter!

$word = New-Object -ComObject "Word.application"
$END_OF_STORY = 6
$word.Visible = $true
$document = $word.documents.Add()
$SysDateObject = new-object system.globalization.datetimeformatinfo
$DayNames = $SysDateObject.Daynames
$selection = $word.selection
$selection.font.size = 14
$selection.font.bold = 1
$selection.Style ="Title"
$selection.typeText("2018 Calendar")
$selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"

$y = 1
for($y -eq 1; $y -le 12; $y++){
    $CURRENTDATE=GET-DATE "$y/1/2018"
    $FirstDayofMonth = ($CURRENTDATE).DayOfWeek.value__ +1
    if($FirstDayofMonth -gt 7){
       $FirstDayofMonth = 1
       $FirstDayofMonth   
      }
    $selection.InsertNewPage()
    $selection.font.size = 14
    $selection.font.bold = 1
    $selection.Style ="Title"
    $CMonth = (Get-Culture).DateTimeFormat.GetMonthName($CURRENTDATE.Month)
    $selection.typeText("$CMonth 2018")
    $selection.ParagraphFormat.Alignment = "wdAlignParagraphCenter"
    $selection.TypeParagraph()
    $Range = $selection.Range
    $Table = $document.Tables.Add($Range,7,7)
    $Table.AutoFormat(11)
    $Table.Borders.InsideLineStyle = 1
    $Column = 1
    $Row = 1
    $DayNames | %{
        $Table.Cell($Row,$Column).Range.Text = $_
        $Table.Cell($Row,$Column).Range.Font.Name = "Forte"
        $Column++
    }

    $i = 1
    $Column = $FirstDayofMonth
    $Row = 2
    $DMonth = $CURRENTDATE.Month
    for($i -eq 1; $i -le [datetime]::DaysInMonth(18,$DMonth); $i++){
        $Table.Cell($Row,$Column).Range.Text = $i
        $Table.Cell($Row,$Column).Range.ParagraphFormat.Alignment = "wdAlignParagraphRight"
        $Column++
    if($Column -gt 7){
       $Row++
       $Column = 1
       }
    }
    $selection.EndKey($END_OF_STORY)
}
avatar
1 Comment
  1. poshking 3 years ago

    At what point did you create or add a macro to the document?

    Why not learn instead of copy pasting vomited scripts you find all over….

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account