{"id":67693,"date":"2006-03-23T15:52:00","date_gmt":"2006-03-23T15:52:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/03\/23\/how-can-i-write-a-script-that-will-open-a-text-file-and-shuffle-the-words-found-in-that-file\/"},"modified":"2006-03-23T15:52:00","modified_gmt":"2006-03-23T15:52:00","slug":"how-can-i-write-a-script-that-will-open-a-text-file-and-shuffle-the-words-found-in-that-file","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-write-a-script-that-will-open-a-text-file-and-shuffle-the-words-found-in-that-file\/","title":{"rendered":"How Can I Write a Script That Will Open a Text File and Shuffle the Words Found in That File?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey, Scripting Guy! My daughter has a flash-card style program that gets its list of words from a text file. How can I write a script that will open that file and automatically shuffle the list of words?<BR><BR>&#8212; SN<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, SN. You know, for the most part we try to keep this column focused on practical system administration tasks: we tell you how to set default printers, how to disable services, and how to map network drives. Every now and then, however, we like to tackle a question that just sounds interesting, regardless of how useful the end result might be. Do system administrators routinely need to shuffle a list of words in a text file? Probably not. But, hey, all work and no play makes Jack a dull boy, right? <\/P>\n<P>Actually, Jack\u2019s kind of dull even when he <I>does<\/I> play. But that\u2019s a different story.<\/P>\n<P>With that in mind, let\u2019s take a look at a script that can shuffle the words in a text file. Like we said, this might not be the most practical of tasks, but it <I>is<\/I> a bit of a challenge, and it does require us to use a few interesting little scripting techniques. And you never know when techniques like those might come in handy.<\/P>\n<P>To begin with, let\u2019s assume you have a text file that looks something like this, with all the words in alphabetical order:<\/P><PRE class=\"codeSample\">Apple\nBanana\nCarrot\nDog\nFish\nElephant\nGiraffe\nHorse\n<\/PRE>\n<P>How can we shuffle these words around? By using a script just like this one:<\/P><PRE class=\"codeSample\">Const ForReading = 1\nConst ForWriting = 2<\/p>\n<p>Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)\nSet objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)<\/p>\n<p>Set objFile = objFSO.OpenTextFile(&#8220;c:\\scripts\\words.txt&#8221;, ForReading)<\/p>\n<p>i = -1<\/p>\n<p>Do Until objFile.AtEndOfStream\n    strLine = objFile.Readline\n    objDictionary.Add strLine, strLine   \n    i = i + 1\nLoop<\/p>\n<p>objFile.Close<\/p>\n<p>Dim arrWords()\nRedim arrWords(i)\nintWordsLeft = i<\/p>\n<p>z = 0<\/p>\n<p>Do While intWordsLeft &gt;= 0\n    Randomize\n    rndWord = Int((intWordsLeft &#8211; 0 + 1) * Rnd + 0)\n    intWordsLeft = intWordsLeft &#8211; 1\n    colItems = objDictionary.Items\n    strText = colItems(rndWord)\n    arrWords(z) = strText\n    z = z + 1\n    objDictionary.Remove(strText)\nLoop<\/p>\n<p>Set objFile = objFSO.OpenTextFile(&#8220;c:\\scripts\\words.txt&#8221;, ForWriting)<\/p>\n<p>For Each strItem in arrWords\n    objFile.WriteLine strItem\nNext<\/p>\n<p>objFile.Close\n<\/PRE>\n<P>Well of <I>course<\/I> it\u2019s crazy-looking; it\u2019s a crazy task (at least for system administrators). But, believe it or not, there\u2019s some logic here, and we\u2019ll walk you through that logic, step-by-step.<\/P>\n<P>The first part of the script is actually pretty easy. We define a pair of constants &#8211; ForReading and ForWriting &#8211; that we\u2019ll use when working with the text file. We then create a pair of objects: <B>Scripting.Dictionary<\/B> and <B>Scripting.FileSystemObject<\/B>. We\u2019ll use the Dictionary object as a temporary storehouse for the words we read in from the text file; we\u2019ll use the FileSystemObject to actually interact with that text file.<\/P>\n<P>Following that we use the <B>OpenTextFile<\/B> method to open the file C:\\Scripts\\Words.txt for reading. (Note the use of the constant ForReading.) Next we create a counter variable named i and set the value to -1; we\u2019re going to use this variable to keep track of the number of words in the file. Why do we start with i equal to -1 rather than 0? Well, we\u2019re going to use i to set up an array, and because the first item in an array is always 0 (rather than 1) we need to start off at -1. When we read in our first word i will be set to 0, and &#8211; weird as it sounds &#8211; an array with a size of 0 means that there\u2019s one item in that array.<\/P>\n<P>Hey, we just report the news, we don\u2019t make it up.<\/P>\n<P>That brings us to this block of code:<\/P><PRE class=\"codeSample\">Do Until objFile.AtEndOfStream\n    strLine = objFile.Readline\n    objDictionary.Add strLine, strLine   \n    i = i + 1\nLoop\n<\/PRE>\n<P>What we\u2019re doing here is reading the file line-by-line. For each line (and thus each word) in the file, we assign the value to a variable named strLine; we then use the <B>Add<\/B> method to add this value to our Dictionary object, in turn incrementing the value of i by 1. When we finish reading the file, all our words will be stored in the Dictionary object, and i will be equal to 7, which just happens to be the number of words in the file minus 1. (Why? Because an array with 8 items in it has an array size of 7.)<\/P>\n<P>Don\u2019t worry; this will all make sense at the end.<\/P>\n<P>We hope.<\/P>\n<P>After closing the file we initialize an array named arrWords, setting it to size i (representing the number of words in the text file minus 1). We also assign the value of i to a variable named intWordsLeft, which will let us know how many words remain to be shuffled. Finally, we set the value of variable z to 0; we\u2019ll use z to populate an array with the shuffled words. Basically what we\u2019re going to do is randomly grab a word from the Dictionary and then add that word to the array. Because the words are taken out of the Dictionary in random order, that will result in them being \u201cshuffled\u201d (stored in a different order) in the array.<\/P>\n<P>Now comes the fun part. We set up a Do loop that runs until we\u2019ve used up all the words in the Dictionary object. We then use these two lines of code to randomly pick a number between 0 and the number of items in the Dictionary object (or at least the actual number of items minus 1, because the first item in the Dictionary objects is also item 0):<\/P><PRE class=\"codeSample\">Ranndomize\nrndWord = Int((intWordsLeft &#8211; 0 + 1) * Rnd + 0)\n<\/PRE>\n<P>After that we decrement the value of intWordsLeft by 1; that\u2019s to keep track of the fact that we now have one less word to work with than we did before.<\/P>\n<P>So what do we need this random number for? Well, what we\u2019re going to do now is use this value to randomly grab a word from the Dictionary. We do that by creating a collection of Dictionary items and then storing the value of the randomly-selected item number in a variable named strText:<\/P><PRE class=\"codeSample\">colItems = objDictionary.Items\nstrText = colItems(rndWord)\n<\/PRE>\n<P>In other words, <I>Banana<\/I> is currently item 1 in our Dictionary. Suppose we got a 1 when we generated a random number. That means we\u2019ll grab the value of item 1 out of the Dictionary; in turn, that means that the word <I>Banana<\/I> gets stored in the variable strText. <\/P>\n<P>Does that make sense? Once we have randomly extracted a word from our Dictionary we need to store that value somewhere. To do that we use the array arrWords, simply making strText the first item in the array:<\/P><PRE class=\"codeSample\">Words(z) = strText\n<\/PRE>\n<P>How do we know this should be the first item? Because we\u2019re assigning the value to item z, and item z is equal to 0. After doing that, we immediately increment z by 1, meaning z will be equal to 1. That means that, the next time through the loop, we\u2019ll assign the retrieved value to the second item in the array.<\/P>\n<P>Having used the word <I>Banana<\/I> our next step is to remove that word from the Dictionary; otherwise we could end up using it a second time. To remove this word we simply call the Dictionary object\u2019s <B>Remove<\/B> method, passing the variable strText as the item to be removed:<\/P><PRE class=\"codeSample\">objDictionary.Remove(strText)\n<\/PRE>\n<P>When all is said and done, the array arrWords will consist of a shuffled list of words taken from the text file:<\/P><PRE class=\"codeSample\">Banana\nElephant\nGiraffe\nApple\nFish\nCarrot\nHorse\nDog\n<\/PRE>\n<P>Nice, huh? All we do then is reopen the file Words.txt (this time for writing), and replace the existing contents with the shuffled list arrWords:<\/P><PRE class=\"codeSample\">Set objFile = objFSO.OpenTextFile(&#8220;c:\\scripts\\words.txt&#8221;, ForWriting)<\/p>\n<p>For Each strItem in arrWords\n    objFile.WriteLine strItem\nNext<\/p>\n<p>objFile.Close\n<\/PRE>\n<P>The next time your daughter (or anyone\u2019s daughter, for that matter) runs the educational program, she\u2019ll be presented with the words in random fashion.<\/P>\n<P>Incidentally, there\u2019s no truth to the rumor that we tested this script on the text of this column. The words in a <I>Hey, Scripting Guy!<\/I> column aren\u2019t chosen randomly; each word is the result of hours of painstaking research and craftsmanship.<\/P>\n<P>In fact, it\u2019s only after we do all that careful craftsmanship that our <I>editor<\/I> randomly shuffles all the words. You\u2019d be amazed how good this column is before it gets edited! <I>(Editor\u2019s Note: You <\/I>would<I> amazed be. use wouldn\u2019t But word the I \u201cgood.\u201d)<\/I><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! My daughter has a flash-card style program that gets its list of words from a text file. How can I write a script that will open that file and automatically shuffle the list of words?&#8212; SN Hey, SN. You know, for the most part we try to keep this column focused on [&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":[3,4,14,5],"class_list":["post-67693","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-scripting-techniques","tag-text-files","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! My daughter has a flash-card style program that gets its list of words from a text file. How can I write a script that will open that file and automatically shuffle the list of words?&#8212; SN Hey, SN. You know, for the most part we try to keep this column focused on [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67693","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=67693"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67693\/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=67693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=67693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=67693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}