{"id":17991,"date":"2010-06-21T00:01:00","date_gmt":"2010-06-21T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/06\/21\/hey-scripting-guy-how-can-i-count-the-words-in-a-bunch-of-microsoft-word-documents\/"},"modified":"2010-06-21T00:01:00","modified_gmt":"2010-06-21T00:01:00","slug":"hey-scripting-guy-how-can-i-count-the-words-in-a-bunch-of-microsoft-word-documents","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-count-the-words-in-a-bunch-of-microsoft-word-documents\/","title":{"rendered":"Hey, Scripting Guy! How Can I Count the Words in a Bunch of Microsoft Word Documents?"},"content":{"rendered":"<p><a href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><\/p>\n<p><img decoding=\"async\" height=\"16\" width=\"125\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" alt=\"Bookmark and Share\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Question\" border=\"0\" title=\"Hey, Scripting Guy! Question\" \/><\/p>\n<p>Hey, Scripting Guy! I need to be able to use Windows PowerShell 2.0 to count the number of words in a bunch of Microsoft Word documents. All of the documents are stored in a specific folder, but there are a mixture of Microsoft Word 2010 and Microsoft Word 2007 documents and older document types in the same folder. Our company has recently opened an office in South America, and we need to have these documents translated into Spanish. To obtain a quotation from the translation service, I need to tell them how many words are contained in the documents. <\/p>\n<p>If it were just a few documents, I would perform this action manually, but there are a lot of files. I am a Human Resources (HR) manager, and not a real IT pro. I have been reading the Hey, Scripting Guy! posts for years not only because you are funny, but also because scripting makes me a more efficient power user. I have searched the Internet, but have not found a script that will do this. Help me, Scripting Guy! Help!. <\/p>\n<p>&#8212; AS<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Answer\" border=\"0\" title=\"Hey, Scripting Guy! Answer\" \/><\/p>\n<p>Hello AS, <\/p>\n<p>Microsoft Scripting Guy Ed Wilson here. I was out and about this morning, and stopped by to see my friend who owns a scuba shop. He loves to read, and we swap books from time to time. After discussing the merits of various translations of the Three Musketeers, we got down to talking about scuba diving. He is planning a trip to Cozumel, Mexico, in the next few weeks, and he is really looking forward to the trip. I went with his group on the last trip. Sadly, ear problems have me grounded for now and I am going to miss this trip. The diving down there is awesome with visibility that extends for more than 100 feet and water that is around 82 degrees or so this time of year. In addition to some excellent drift diving, there are also some really nice coral formations with white sand and friendly sea creatures such as the giant grouper seen here.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3755.hsg062110011_66CFF0D2.jpg\"><img decoding=\"async\" height=\"494\" width=\"604\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7776.hsg062110011_thumb_25C1716E.jpg\" alt=\"Photo of giant grouper\" border=\"0\" title=\"Photo of giant grouper\" style=\"border-right-width: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px\" \/><\/a> <\/p>\n<p>AS, per your request, I wrote the CountNumberOfWordsInDocuments.ps1 script that you described in your email message. The script will retrieve the number of words in documents that are in one or more folders. To use the CountNumberOfWordsInDocuments.ps1 script, you will need to modify the path to the folder. The complete script is shown here. <\/p>\n<p><strong>CountNumberOfWordsInDocuments.ps1<\/strong><\/p>\n<p><span style=\"background-color: #f0f0f0\">$intDocs = $intWords = $null <br \/>$path = &#8220;C:\\data\\ScriptingGuys&#8221; <br \/>$application = New-Object -ComObject word.application <br \/>$application.visible = $false <br \/>Get-ChildItem -Path $path -include *.doc,*.docx -Recurse | <br \/>ForEach-Object { <br \/>&#8220;Processing $($_.fullname)&#8221; <br \/>$document = $application.documents.open($_.fullname) <br \/>$intWords += $document.words.count <br \/>$intDocs ++ <br \/>$document.close() | out-null <br \/>} <br \/>$application.quit() <br \/>$application = $null <br \/>[gc]::collect() <br \/>[gc]::WaitForPendingFinalizers() <br \/>&#8220;There are $intDocs documents in the $path folder. <br \/>They contain a total of $intWords words.&#8221;<\/span><\/p>\n<p>The first thing that needs to be done is to initialize a few variables. The first two variables, <b>$intDocs<\/b> and <b>$intWords<\/b>, are counter variables that are used to keep track of the number of documents processed and the number of words that those documents contain. Because it is possible you may wish to run the script more than once, it is a best practice to initialize those variables. The easiest way to do this is to set them equal to <b>$null<\/b><b>&mdash;<\/b>each time the script runs, if the variable exists it will be assigned the value <b>$null<\/b>. If the variable does not exist, it will be created and assigned the value of <b>$null<\/b>. I love the &ldquo;equals equals&rdquo; type of syntax because it is a quick and efficient way of initializing multiple variables. For example, if I had three variables <b>$a<\/b>, <b>$b<\/b>, and <b>$c<\/b> that I wanted to initialize with the value of 1, I could do it as shown here. Notice that if a variable does not exist, such as <b>$d<\/b> in this example, no value is displayed. <\/p>\n<p><span style=\"background-color: #f0f0f0\">PS C:\\&gt; $a=$b=$c=1 <br \/>PS C:\\&gt; $a <br \/>1 <br \/>PS C:\\&gt; $b <br \/>1 <br \/>PS C:\\&gt; $c <br \/>1 <br \/>PS C:\\&gt; $d <br \/>PS C:\\&gt;<\/span><\/p>\n<p>In addition to initializing the counter variables, I also assign a value for the path that contains all of the document files. This folder, which is shown in the following image, contains a large number of subfolders and sub-subfolders. This portion of the script is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$intDocs = $intWords = $null <br \/>$path = &#8220;C:\\data\\ScriptingGuys&#8221;<\/span><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2677.hsg062110021_4C2354B9.jpg\"><img decoding=\"async\" height=\"422\" width=\"604\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5635.hsg062110021_thumb_4497E54C.jpg\" alt=\"Image of folder containing document files\" border=\"0\" title=\"Image of folder containing document files\" style=\"border-right-width: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px\" \/><\/a> <\/p>\n<p>The next thing we must do is create the <b>word.application<\/b> object. The <b>application<\/b> object for Microsoft Word is created whenever a script needs to perform automation. This object is used when working with the Microsoft Word application, and therefore has a number of methods and properties that perform things such as opening documents, closing the application, sizing the window, or even creating a list of keyboard shortcuts for Microsoft Word (something we will look at on Wednesday this week). <\/p>\n<p><span style=\"background-color: #f0f0f0\">$application = New-Object -ComObject word.application<\/span> <\/p>\n<p>After the <b>word.application<\/b> object has been created and stored in the <b>$application<\/b> variable, the <b>visible<\/b> property is set to <b>$false<\/b>. This will prevent the application from appearing while each document is opened and the number of words counted. The only thing to remember when setting the <b>application<\/b> object to <b>not visible<\/b> is that the <b>quit<\/b> method must be called to ensure that dozens of copies of Winword.exe are not left running and eating up resources. At 50&ndash;70 megabytes of memory each, it does not take too long before leftover processes begin to impact performance. By not requiring Microsoft Word to be visible and to display each document as it is processed, the script will run significantly quicker. This line of code is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$application.visible = $false<\/span><\/p>\n<p>The <b>Get-ChildItem<\/b> cmdlet is used to retrieve all the document files in one or more folders that are specified in the <b>$path<\/b> variable. The <b>&ndash;recurse<\/b> parameter is used to include the directory and subdirectories. Each <b>system.io.fileinfo<\/b> object that is retrieved by the <b>Get-ChildItem<\/b> cmdlet is piped to the <b>Foreach-Object<\/b> cmdlet. Because Windows PowerShell passes objects instead of text, each Microsoft Word document that is discovered by the <b>Get-ChildItem<\/b> is represented by an instance of the <b>system.io.fileinfo<\/b> .NET Framework class. The members of this class are shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\"><\/span><\/p>\n<p class=\"CodeBlock\"><span style=\"font-size: 10pt\"><span style=\"font-family: lucida sans typewriter\"><span style=\"background-color: #f0f0f0\">PS C:\\&gt; Get-Item C:\\fso\\HSG-6-1-10.Doc | get-member <\/p>\n<p><span>&nbsp;&nbsp; <\/span>TypeName: System.IO.FileInfo <\/p>\n<p>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MemberType<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Definition <br \/>&#8212;-<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8212;&#8212;&#8212;-<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8212;&#8212;&#8212;- <br \/>Mode<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>CodeProperty<span>&nbsp;&nbsp; <\/span>System.String Mode{get=Mode;} <br \/>AppendText<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.StreamWriter AppendText() <br \/>CopyTo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileInfo CopyTo(string destFil&#8230; <br \/>Create<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileStream Create() <br \/>CreateObjRef<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Runtime.Remoting.ObjRef CreateObj&#8230; <br \/>CreateText<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.StreamWriter CreateText() <br \/>Decrypt<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void Decrypt() <br \/>Delete<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void Delete() <br \/>Encrypt<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void Encrypt() <br \/>Equals<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>bool Equals(System.Object obj) <br \/>GetAccessControl<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Security.AccessControl.FileSecuri&#8230; <br \/>GetHashCode<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>int GetHashCode() <br \/>GetLifetimeService<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Object GetLifetimeService() <br \/>GetObjectData<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void GetObjectData(System.Runtime&#8230; <br \/>GetType<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>type GetType() <br \/>InitializeLifetimeService Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Object InitializeLifetimeService() <br \/>MoveTo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void MoveTo(string destFileName) <br \/>Open<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileStream Open(System.IO.File&#8230; <br \/>OpenRead<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileStream OpenRead() <br \/>OpenText<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.StreamReader OpenText() <br \/>OpenWrite<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileStream OpenWrite() <br \/>Refresh<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void Refresh() <br \/>Replace<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileInfo Replace(string destin&#8230; <br \/>SetAccessControl<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Void SetAccessControl(System.Secu&#8230; <br \/>ToString<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Method<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>string ToString() <br \/>PSChildName<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NoteProperty<span>&nbsp;&nbsp; <\/span>System.String PSChildName=HSG-6-1-10.Doc <br \/>PSDrive<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NoteProperty<span>&nbsp;&nbsp; <\/span>System.Management.Automation.PSDriveInfo&#8230; <br \/>PSIsContainer<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NoteProperty<span>&nbsp;&nbsp; <\/span>System.Boolean PSIsContainer=False <br \/>PSParentPath<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NoteProperty<span>&nbsp;&nbsp; <\/span>System.String PSParentPath=Microsoft.Pow&#8230; <br \/>PSPath<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NoteProperty<span>&nbsp;&nbsp; <\/span>System.String PSPath=Microsoft.PowerShel&#8230; <br \/>PSProvider<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>NoteProperty<span>&nbsp;&nbsp; <\/span>System.Management.Automation.ProviderInf&#8230; <br \/>Attributes<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.IO.FileAttributes Attributes {get&#8230; <br \/>CreationTime<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.DateTime CreationTime {get;set;} <br \/>CreationTimeUtc<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.DateTime CreationTimeUtc {get;set;} <br \/>Directory<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp; <\/span>System.IO.DirectoryInfo Directory {get;} <br \/>DirectoryName<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.String DirectoryName {get;} <br \/>Exists<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Boolean Exists {get;} <br \/>Extension<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.String Extension {get;} <br \/>FullName<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.String FullName {get;} <br \/>IsReadOnly<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Boolean IsReadOnly {get;set;} <br \/>LastAccessTime<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.DateTime LastAccessTime {get;set;} <br \/>LastAccessTimeUtc<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.DateTime LastAccessTimeUtc {get;s&#8230; <br \/>LastWriteTime<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.DateTime LastWriteTime {get;set;} <br \/>LastWriteTimeUtc<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.DateTime LastWriteTimeUtc {get;set;} <br \/>Length<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.Int64 Length {get;} <br \/>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Property<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>System.String Name {get;} <br \/>BaseName<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ScriptProperty System.Object BaseName {get=if ($this.Ex&#8230; <br \/>VersionInfo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ScriptProperty System.Object VersionInfo {get=[System.D&#8230;<\/span><\/span><\/span><\/p>\n<\/p>\n<p>&nbsp;<\/p>\n<p>Inside the <b>Foreach-Object<\/b> cmdlet, the members (both methods and properties) are available to use in processing each Microsoft Word document that has been discovered. In this script, I only need to use the <b>fullname<\/b> property because it contains the path, the file name, and the file extension. There are four properties I routinely use when working with files: <b>fullname<\/b>, <b>name<\/b>, <b>basename<\/b>, and <b>extension<\/b>. By using the proper property from a <b>system.io.fileinfo<\/b> object, it simplifies a number of string concatenation and string splitting issues that used to arise when working in VBScript. Each property is illustrated here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">PS C:\\&gt; (Get-Item C:\\fso\\HSG-6-1-10.Doc).fullname <br \/>C:\\fso\\HSG-6-1-10.Doc <br \/>PS C:\\&gt; (Get-Item C:\\fso\\HSG-6-1-10.Doc).name <br \/>HSG-6-1-10.Doc <br \/>PS C:\\&gt; (Get-Item C:\\fso\\HSG-6-1-10.Doc).basename <br \/>HSG-6-1-10 <br \/>PS C:\\&gt; (Get-Item C:\\fso\\HSG-6-1-10.Doc).extension <br \/>.Doc <br \/>PS C:\\&gt;<\/span><\/p>\n<p>To make it easier to keep track of these four properties, I decided to include them in Table 1. <\/p>\n<p><strong>Table 1: Useful FileInfo properties<\/strong> <\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\">\n<tbody>\n<tr>\n<td width=\"90\" valign=\"top\">\n<p><b>Property name<\/b><\/p>\n<\/td>\n<td width=\"174\" valign=\"top\">\n<p><b>Meaning<\/b><\/p>\n<\/td>\n<td width=\"167\" valign=\"top\">\n<p><b>Example<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"90\" valign=\"top\">\n<p>fullname<\/p>\n<\/td>\n<td width=\"174\" valign=\"top\">\n<p>Path, filename and extension<\/p>\n<\/td>\n<td width=\"167\" valign=\"top\">\n<p>C:\\fso\\HSG-6-1-10.Doc<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"90\" valign=\"top\">\n<p>name<\/p>\n<\/td>\n<td width=\"174\" valign=\"top\">\n<p>Filename and extension<\/p>\n<\/td>\n<td width=\"167\" valign=\"top\">\n<p>HSG-6-1-10.Doc<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"90\" valign=\"top\">\n<p>basename<\/p>\n<\/td>\n<td width=\"174\" valign=\"top\">\n<p>Filename<\/p>\n<\/td>\n<td width=\"167\" valign=\"top\">\n<p>HSG-6-1-10<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"90\" valign=\"top\">\n<p>extension<\/p>\n<\/td>\n<td width=\"174\" valign=\"top\">\n<p>Extension<\/p>\n<\/td>\n<td width=\"167\" valign=\"top\">\n<p>.Doc<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The section of the script that retrieves the Office 2007 and later Microsoft Word documents (.docx extension) and the legacy Microsoft Word documents (.doc extension) is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">Get-ChildItem -Path $path -include *.doc,*.docx -Recurse | <br \/>ForEach-Object { <br \/>&#8220;Processing $($_.fullname)&#8221;<\/span><\/p>\n<p>When opening a document, the complete path to the file is required; therefore, the <b>fullname<\/b> property is used with the <b>open<\/b> method from the <b>documents<\/b> object. The returned <b>document<\/b> object is stored in the <b>$document<\/b> variable. This is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$document = $application.documents.open($_.fullname)<\/span> <\/p>\n<p>The <b>count<\/b> property from the <b>words<\/b> collection object of the <b>document<\/b> object is used to determine how many words are in the document. The <b>$intWords<\/b> variable keeps a running tally of all the words from all of the documents that have been currently processed. To do this, the <b>+=<\/b> operator is used. I love using the <b>+=<\/b> operator because it is much easier than the way that VBScript required, which was to use <b>i = i + wordCount<\/b>. Using the <b>+=<\/b> operator is illustrated here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">PS C:\\&gt; $i = 5 <br \/>PS C:\\&gt; $i <br \/>5 <br \/>PS C:\\&gt; $i += 5 <br \/>PS C:\\&gt; $i <br \/>10 <br \/>PS C:\\&gt;<\/span><\/p>\n<p>If you do not like using the <b>+=<\/b> operator, you can still use the VBScript way of incrementing a counter (I know this is not <i>really<\/i> just VBScript syntax and that in fact lots of other programming languages use this syntax. I am just calling it a VBScript way of doing things for convenience and to distinguish it from the <b>+=<\/b> operator). This is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">PS C:\\&gt; $i = 5 <br \/>PS C:\\&gt; $i = $i + 5 <br \/>PS C:\\&gt; $i <br \/>10 <br \/>PS C:\\&gt;<\/span><\/p>\n<p>The word count is stored in the <b>$intWords<\/b> variable, as shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$intWords += $document.words.count<\/span><\/p>\n<p>A running count of all the documents that have been processed in the script is stored in the <b>$intDocs<\/b> variable. If I love using the <b>+=<\/b> operator, I really love using the <b>++<\/b> operator. This operator will take the current value stored in a variable and increment it by one, and then store the value back in the variable. This is illustrated here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">PS C:\\&gt; $i = 5 <br \/>PS C:\\&gt; $i ++ <br \/>PS C:\\&gt; $i <br \/>6 <br \/>PS C:\\&gt;<\/span><\/p>\n<p>The <b>++<\/b> operator is the same as stating that i = i + 1. This is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">PS C:\\&gt; $i = 5 <br \/>PS C:\\&gt; $i = $i + 1 <br \/>PS C:\\&gt; $i <br \/>6 <br \/>PS C:\\&gt;<\/span><\/p>\n<p>The <b>++<\/b> operator is much more compact. Its use in the script is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$intDocs ++<\/span><\/p>\n<p>The <b>close<\/b> method from the <b>document<\/b> object is used to close the current document. To prevent cluttering the screen, the results are piped to the <b>Out-Null<\/b> cmdlet. This is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$document.close() | out-null<\/span><\/p>\n<p><span style=\"background-color: #f0f0f0\">}<\/span><\/p>\n<p>The <b>quit<\/b> method of the application object is called. Next, the <b>$application<\/b> variable is set to <b>$null<\/b>, and garbage collection is called. This is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">$application.quit() <br \/>$application = $null <br \/>[gc]::collect() <br \/>[gc]::WaitForPendingFinalizers()<\/span><\/p>\n<p>The number of documents and the number of words is displayed on the screen. This is shown here:<\/p>\n<p><span style=\"background-color: #f0f0f0\">&#8220;There are $intDocs documents in the $path folder. <br \/>They contain a total of $intWords words.&#8221;<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>AS, that is all there is to using Microsoft Word to count the number of words contained in DOC files. Microsoft Office Week will continue tomorrow. <\/p>\n<p>If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send e-mail to us at <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! I need to be able to use Windows PowerShell 2.0 to count the number of words in a bunch of Microsoft Word documents. All of the documents are stored in a specific folder, but there are a mixture of Microsoft Word 2010 and Microsoft Word 2007 documents and older document types [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[84,49,3,45],"class_list":["post-17991","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-word","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! I need to be able to use Windows PowerShell 2.0 to count the number of words in a bunch of Microsoft Word documents. All of the documents are stored in a specific folder, but there are a mixture of Microsoft Word 2010 and Microsoft Word 2007 documents and older document types [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/17991","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=17991"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/17991\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=17991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=17991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=17991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}