{"id":67213,"date":"2006-05-31T09:24:00","date_gmt":"2006-05-31T09:24:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/05\/31\/how-can-i-search-a-word-document-for-all-the-words-in-double-brackets\/"},"modified":"2006-05-31T09:24:00","modified_gmt":"2006-05-31T09:24:00","slug":"how-can-i-search-a-word-document-for-all-the-words-in-double-brackets","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-search-a-word-document-for-all-the-words-in-double-brackets\/","title":{"rendered":"How Can I Search a Word Document for All the Words in Double Brackets?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hey, Scripting Guy! How can I search a Word document for all the words in double brackets? For example, I need to find words like this: [[failed]]. I then need to save the words I find to a text file.<BR><BR>&#8212; PP<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, PP. You know, one thing that seems to be true of the Scripting Guys is a willingness to do something even when they have no idea what it is they\u2019re doing. Put new molding in the family room? Come on, you just saw some wood and nail it to the wall, right? New tile in the kitchen? Piece of cake. Search a Word document for words in square brackets? Hey, how hard could something like <I>that<\/I> be?<\/P>\n<P>In our defense, in most cases we come up with a finished product that looks reasonably good. New molding? Looks nice; just don\u2019t look in the garbage can and count the number of pieces that were cut in the wrong place. Kitchen floor? That looks great \u2026 as long as you don\u2019t take a look under the refrigerator, mind you. A script that searches a document for words in square brackets? As long as you\u2019re willing to overlook all the false starts we ran into, well, then it wasn\u2019t so bad after all:<\/P><PRE class=\"codeSample\">Set objWord = CreateObject(&#8220;Word.Application&#8221;)\nobjWord.Visible = True<\/p>\n<p>Set objDoc = objWord.Documents.Open(&#8220;C:\\Scripts\\Test.doc&#8221;)\nSet objSelection = objWord.Selection<\/p>\n<p>objSelection.Find.Forward = True\nobjSelection.Find.MatchWildcards = True\nobjSelection.Find.Text = &#8220;\\[\\[*\\]\\]&#8221;<\/p>\n<p>Do While True\n    objSelection.Find.Execute\n    If objSelection.Find.Found Then\n        strWord = objSelection.Text\n        strWord = Replace(strWord, &#8220;[[&#8220;, &#8220;&#8221;)\n        strWord = Replace(strWord, &#8220;]]&#8221;, &#8220;&#8221;)\n        Wscript.Echo strWord\n    Else\n        Exit Do\n    End If\nLoop\n<\/PRE>\n<P>Admittedly, parts of this script are a little odd-looking, most notably the line where we specify our search text. With that in mind, let\u2019s walk you through the code and see if we can explain how it works.<\/P>\n<TABLE id=\"E6C\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. That\u2019s a good point: we <I>do<\/I> walk through the code in each and every <I>Hey, Scripting Guy!<\/I> column, don\u2019t we? We just thought that <I>saying<\/I> we were going to do that would somehow make today\u2019s column sound special.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>The script starts out in fairly-straightforward fashion: we simply create an instance of the <B>Word.Application<\/B> object and then set the <B>Visible<\/B> property to True. That gives us a running instance of Word that we can see on screen. We use the <B>Open<\/B> method to open the file C:\\Scripts\\Test.doc, then create an instance of the Word <B>Selection<\/B> object.<\/P>\n<TABLE id=\"EBE\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. You\u2019re lost <I>already<\/I>? Don\u2019t worry about it: if you\u2019ve never written a script that interacts with Microsoft Word we wouldn\u2019t expect that first paragraph to make much sense. For more information on scripting Microsoft Word take a peek at our <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/officetips\/archive.mspx\"><B>Office Space Archive<\/B><\/A>. And, while you\u2019re there, you might want to check out <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/officetips\/may05\/tips0512.mspx\"><B>this article<\/B><\/A>, which explains how to find and replace text in a Word document.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>As it turns out, the Selection object (which, when created without any additional parameters, simply positions the cursor at the very beginning of the document) has a child object named <B>Find<\/B>. As you might expect, the Find object is used for finding text in a Word document. Before we can use the Find object, however, we need to configure three important properties, something we do here:<\/P><PRE class=\"codeSample\">objSelection.Find.Forward = True\nobjSelection.Find.MatchWildcards = True\nobjSelection.Find.Text = &#8220;\\[\\[*\\]\\]&#8221;\n<\/PRE>\n<P>The first two properties &#8211; <B>Forward <\/B>and<B> MatchWildcards<\/B> &#8211; are relatively easy to figure out. The <B>Forward<\/B> property, when True, tells the script to search the document from the current cursor position to the end of the document. We want to do that because the cursor is currently positioned at the start of the document. If the cursor was at the end of the document we\u2019d probably set the Forward property to False, which would cause us to search the document backwards, from the current cursor position to the beginning of the document. MatchWildcards? That\u2019s even easier: MacthWildcards simply tells the script that we\u2019re going to use a wildcard character in our search.<\/P>\n<P><I>Why<\/I> are we going to use a wildcard character in our search? Well, we\u2019re looking for anything that begins with a pair of square brackets (<B>[[<\/B>) and then ends with a pair of square brackets (<B>]]<\/B>). To do that we can use the asterisk to represent any character or set of characters. Looking for something that starts with two brackets, has some character or set of characters in the middle, and then ends with two brackets? Then you want to search for something like this:<\/P><PRE class=\"codeSample\">[[*]]\n<\/PRE>\n<P>Of course, what you want to do and what Word will let you do aren\u2019t always the same thing. For example, when it comes to doing a wildcard search, the bracket symbols are reserved characters. If you try using [[*]] in a wildcard search you\u2019ll get back an \u201cinvalid range\u201d error. <\/P>\n<TABLE id=\"EYF\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. This is true even if you aren\u2019t using a script. In Word click<B> Edit<\/B> and then click <B>Find<\/B>. When the Find and Replace dialog box appears, type<B> [[*]]<\/B> in the <B>Find what<\/B> box, then click <B>More<\/B> and select <B>Use wildcards<\/B>. Now click <B>Find Next<\/B> and see what happens.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Because the brackets are reserved characters, we need to \u201cescape\u201d them by preceding each character with a \\. That\u2019s why the value of the <B>Text<\/B> property (the text we want to search for) looks so odd:<\/P><PRE class=\"codeSample\">objSelection.Find.Text = &#8220;\\[\\[*\\]\\]&#8221;\n<\/PRE>\n<P>Believe it or not, that really <I>is<\/I> the text we\u2019re searching for; we simply had to precede each of the four bracket symbols with a \\. Strange but true.<\/P>\n<P>Now we\u2019re ready to start searching, a task we perform inside a Do While loop:<\/P><PRE class=\"codeSample\">Do While True\n    objSelection.Find.Execute\n    If objSelection.Find.Found Then\n        strWord = objSelection.Text\n        strWord = Replace(strWord, &#8220;[[&#8220;, &#8220;&#8221;)\n        strWord = Replace(strWord, &#8220;]]&#8221;, &#8220;&#8221;)\n        Wscript.Echo strWord\n    Else\n        Exit Do\n    End If\nLoop\n<\/PRE>\n<P>You might have noticed the syntax for the Do While loop: Do While True. In essence that means, \u201cContinue looping as long as True equals True.\u201d That sounds like a problem waiting to happen: with the possible exception of politics, doesn\u2019t True <I>always<\/I> equal True? And, if so, doesn\u2019t that mean this script will run forever without stopping? Yes, it does. <\/P>\n<P>Well, unless we add a line of code that we\u2019ll discuss in a moment. <\/P>\n<P>Inside the loop we start out by calling the <B>Execute<\/B> method; that causes the script to search our document for the first instance of the target text. The script begins searching and stops the first time it finds an instance of the text. On top of that, if the search is successful then the value of the <B>Found <\/B>property will be True. That\u2019s what we\u2019re checking here:<\/P><PRE class=\"codeSample\">If objSelection.Find.Found Then\n<\/PRE>\n<P>But what if we\u2019ve reached the end of the document and no instance of the target text can be found? In that case, the Found property will be False, and we use the <B>Exit Do<\/B> command to exit the Do While loop. That\u2019s how we manage to get out of our loop: True is still equal to True, but the Exit Do command will automatically take you out of the loop. Period.<\/P>\n<P>On the other hand, suppose we <I>do<\/I> find the target text? In that case, Word will automatically move the selection to the text that was just found. Because of that, we can get the value of the new selection just by checking the value of the Selection object\u2019s <B>Text<\/B> property:<\/P><PRE class=\"codeSample\">strWord = objSelection.Text\n<\/PRE>\n<P>What does that mean? Let\u2019s assume that Word has found this item:<\/P><PRE class=\"codeSample\">[[failed]]\n<\/PRE>\n<P>In that case, the word <B>[[failed]]<\/B> will (for our purposes) be highlighted, and the value of the Text property will be whatever happens to be highlighted. In other words, the Text property will equal this:<\/P><PRE class=\"codeSample\">[[failed]]\n<\/PRE>\n<P>Of course, ideally we\u2019d like to get rid of the surrounding brackets and pick out just the word <I>failed<\/I>. Fortunately that\u2019s easy to do. After storing the value of the Text property in the variable strWord we can use the VBScript <B>Replace<\/B> function to replace the four bracket symbols ([[ and ]]) with, well, nothing. That\u2019s what we do with these two lines of code:<\/P><PRE class=\"codeSample\">strWord = Replace(strWord, &#8220;[[&#8220;, &#8220;&#8221;)\nstrWord = Replace(strWord, &#8220;]]&#8221;, &#8220;&#8221;)\n<\/PRE>\n<P>To keep the script simple, we then do nothing more than echo back the value of strWord. Admittedly, PP, you wanted to write any words that were found to a text file. For more information on doing that, check out the <A href=\"http:\/\/null\/technet\/scriptcenter\/guide\/sas_scr_iikh.mspx\" target=\"_blank\"><B>Microsoft Windows 2000 Scripting Guide<\/B><\/A>. (And, of course, the <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/qanda\/textfiles.mspx\"><B>Hey, Scripting Guy! archive<\/B><\/A> has plenty of sample scripts that show you how to write data to a text file.)<\/P>\n<P>As we noted, the script will find the first instance of the target text and then stop. But what if there are more words enclosed in square brackets? We\u2019ve already thought of that: that\u2019s why we\u2019re using the Do While loop. After finding the first instance the script loops around, calls the Execute method and starts the whole process all over again. That continues until the script reaches the end of the document. At that point the Found property will be False, and we exit the loop.<\/P>\n<P>As for the Scripting Guys, with another challenge successfully tackled it\u2019s time to move on to the next project: putting a basketball court in the backyard. Have we ever actually <I>poured<\/I> concrete before? Do you even have to ask?<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I search a Word document for all the words in double brackets? For example, I need to find words like this: [[failed]]. I then need to save the words I find to a text file.&#8212; PP Hey, PP. You know, one thing that seems to be true of the Scripting [&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,5],"class_list":["post-67213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-word","tag-office","tag-scripting-guy","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I search a Word document for all the words in double brackets? For example, I need to find words like this: [[failed]]. I then need to save the words I find to a text file.&#8212; PP Hey, PP. You know, one thing that seems to be true of the Scripting [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67213","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=67213"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67213\/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=67213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=67213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=67213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}