Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to add a comment to a Microsoft Word document.
Microsoft Scripting Guy, Ed Wilson, is here. I spend a lot of time using Microsoft Word. In fact, I spend more time using Word than Microsoft Outlook—and that is saying something. Actually, it is saying a lot. Word is open on my computer nearly every day of the year, and from time-to-time, at all hours of the day. Because I deal with editors, I also have to read comments that they add to Word documents. On the other hand, when I provide peer review for other writers, I also have to be able to add comments to Word documents. I find myself adding exactly the same sort of comments to documents. Here is a sample of comments that I have added to over a dozen documents in the last few months:
“Remember when writing, it is more important to show something, and not to merely tell about something. In technical writing, this can take the form of a table, a line drawing, or an image showing the GUI.”
“Please don’t mix point of views. Remember, first person can be great for a blog if you are the main writer. The first person (I) brings the reader into your world, and permits you great flexibility when discussing issues that might arise. The second person (you) is excellent for writing how-to topics, but it can break down if you are not careful. The third person (he or she) tends to add a layer of distance that you might not want to have. The most important thing is consistency.”
“When discussing technical matters, variety of word choice is not necessarily a good thing. Don’t substitute program for process, executable for service, app for application, or storage for hard disk drive. It will confuse the reader who knows the difference, and it will be meaningless for a reader who does not.”
In fact, for the documents I was reviewing, I ended up copying the comments into Notepad, and then I used Cut and Paste. For each comment, I had to make over a dozen keystrokes: switch to Notepad, select a paragraph, copy the paragraph, switch back to Word, find my spot, paste the comment, and so on. Sounds like I needed a script.
Add a comment to a Word document…it’s easy
After I decided that I wanted to write a Windows PowerShell script to add a comment to a Word document, I needed to see if it was even possible. I mean, in all the years I have been using Word, and in all the years I have been using Windows PowerShell, I only now had the need to automate adding comments. But could I do it?
When I have such an idea, I always pop over to MSDN, and look at the Word Object Model Reference documentation for automation. Because it seems there is a new version of Word nearly every year, I always have to ensure that I have the documentation for the version of Word that I am using.
Luckily, I always have the latest version. The object model changes—sometimes in subtle ways—so I always like to look things up. Here is a link to the Object Model Reference (Word 2013 Developer Reference) documentation. I can’t say how long the Comments object has been available, because, like I said, this is the first time I decided to write such a script. I scroll down the list of objects until I see Comment and Comment objects.
Luckily, the names of the objects make sense. Because I understand the Word object model, I know that a comment will come from a Comments collection. I know that there will be an Add method to add the comment, and I know that such a comment will be attached to a Range object. A Range object specifies a location in a Word document. I can create a specific Range, or I can retrieve a Range object via the Range property from a Document, Section, Paragraph,or other such object. There is a pretty good article on MSDN that talks about this: Working with Range Objects.
Adding a comment is as simple as calling the Add method from the Comments object, and specifying the Range and the comment text itself. Everything else about it is standard Word automation.
Basic Word automation stuff
The first thing I do is specify the path to the file that will receive my comments. In this example, I use the Word document that I created yesterday that holds my Shakespeare research topics. Next, I create the Word.Application object, set the application to not visible, open my Word document, retrieve the first section and the range that is associated with this section. This code is shown here:
$filePath = "C:\lit\ResearchTopics.docx"
$word = New-Object -comobject word.application
$word.visible = $false
$doc = $word.documents.open($filePath)
$section = $doc.sections.item(1)
$range = $section.Range
Add the comment
After I have my Range object (from the first section of the Word document) and the Comments object (from the Comments property of the document I opened), I can add the comment to the document. It actually makes sense. I am adding a comment to a specific location in a specific document. To specify that location, I need to supply a Range object from the $range variable and then my comment:
$doc.Comments.Add($range,"This is a great listing of topics")
Close things out and clean stuff up
I want to save my changes to the document, close the document, and exit the Word application. I then release all the objects, remove the variables, and call garbage collection to free up the memory. This code is pretty standard for most of my Word automation projects, and it is shown here:
$doc.save()
$doc.close()
$word.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($doc) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($range) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Section) | Out-Null
Remove-Variable Doc,Word, range, section
[gc]::collect()
[gc]::WaitForPendingFinalizers()
The complete script is shown here:
$filePath = "C:\lit\ResearchTopics.docx"
$word = New-Object -comobject word.application
$word.visible = $false
$doc = $word.documents.open($filePath)
$section = $doc.sections.item(1)
$range = $section.Range
$doc.Comments.Add($range,"This is a great listing of topics")
$doc.save()
$doc.close()
$word.quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($doc) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($word) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($range) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Section) | Out-Null
Remove-Variable Doc,Word, range, section
[gc]::collect()
[gc]::WaitForPendingFinalizers()
As shown here, the comment appears in my Word document when I open it:
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
This is a worthy article. I truly understand all the concepts i.e., how can we add comments to a word document. I request the author if he can write something about how to prepare a statement of income using MS Word. The response will be appreciated.