{"id":64473,"date":"2007-07-12T00:43:00","date_gmt":"2007-07-12T00:43:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/07\/12\/how-can-i-ensure-that-a-user-enters-only-allowed-characters-in-a-text-box\/"},"modified":"2007-07-12T00:43:00","modified_gmt":"2007-07-12T00:43:00","slug":"how-can-i-ensure-that-a-user-enters-only-allowed-characters-in-a-text-box","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-ensure-that-a-user-enters-only-allowed-characters-in-a-text-box\/","title":{"rendered":"How Can I Ensure That a User Enters Only Allowed Characters in a Text Box?"},"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! I have an HTA which includes a text box where the user must enter a part number. Part numbers must consist of a certain set of characters; how can I determine if a user entered an invalid character in the part number text box?<BR><BR>&#8212; RR <\/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, RR. You know, with one exception, no one has ever accused the Scripting Guy who writes this column of being a genius. (The one exception, of course, is the Scripting Editor; she thinks that everything that this Scripting Guy does is just plain <I>perfect<\/I>.) <\/P>\n<TABLE class=\"dataTable\" id=\"E6C\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Ed<\/B><B>itor\u2019s Note:<\/B> The Scripting Guy who writes this column is obviously having one of his delusional episodes. Don\u2019t worry, it\u2019s not serious; they\u2019re mostly harmless and the Scripting Editor always manages to set him straight.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Still, the Scripting Editor aside, the Scripting Guy who writes this column will occasionally do something dumb. For example, it\u2019s time for yet another out-of-town baseball tournament, this one to be held in beautiful Walla Walla, WA (\u201cThe town so nice they named it twice!\u201d). Because of that, the Scripting Guy who writes this column is in a hurry to get today\u2019s column taken care of; that way he can hit the road as quickly as possible. That means that the smart thing for him to do would be to pick a question \u2013 and write a column about \u2013 a topic he already knows by heart, one that he can sit down and hammer out a script and accompanying article without even thinking about it.<\/P>\n<P>OK, not that he ever thinks too terribly hard about <I>any<\/I> column he writes. But you know what we mean.<\/P>\n<P>Instead, the Scripting Guy who writes this column picked a question that he knew <I>could<\/I> be solved, although he wasn\u2019t exactly sure how to go about solving it. Fortunately, with a little diligence and a little effort, along with the fact that he really needs to get going pretty soon, he was able to come up with the following solution:<\/P><PRE class=\"codeSample\">&lt;SCRIPT LANGUAGE=&#8221;VBScript&#8221;&gt;\n    Sub VerifyEntry\n        Set objRegEx = CreateObject(&#8220;VBScript.RegExp&#8221;)\n        objRegEx.Global = True   \n        objRegEx.Pattern = &#8220;[^ABCDEFG12345]&#8221;<\/p>\n<p>        strSearchString = TextBox1.Value<\/p>\n<p>        Set colMatches = objRegEx.Execute(strSearchString)  <\/p>\n<p>        If colMatches.Count &gt; 0 Then\n            Msgbox &#8220;You entered an invalid character.&#8221;\n            TextBox1.Focus\n        End If\n    End Sub\n&lt;\/SCRIPT&gt;<\/p>\n<p>&lt;body&gt;\n    &lt;input type=&#8221;text&#8221; name=&#8221;TextBox1&#8243; size=&#8221;50&#8243; onFocusOut=&#8221;VerifyEntry&#8221;&gt;&lt;p&gt;\n    &lt;input type=&#8221;text&#8221; name=&#8221;TextBox2&#8243; size=&#8221;50&#8243;&gt;\n&lt;\/body&gt;\n<\/PRE>\n<P>We have a few minutes before we have to go, so let\u2019s see if we can explain how this all works. To begin with, the body of our HTA consists solely of a pair of text boxes, text boxes that <I>look<\/I> identical, but actually have two key differences:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The names of the text boxes. The first text box (the one we care about) is named TextBox1. The second text box has an even catchier name: TextBox2. And, yes, now that you mention it, these two text boxes were named after the Scripting Guy\u2019s mom and dad. Seemed like a nice anniversary present, don\u2019t you think?<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The events attached to each text box. Textbox2 doesn\u2019t have any events attached to it; Textbox1, on the other hand, features the <B>onFocusOut<\/B> event. When you work with a control in an HTA or a Web page (for example, when you type something in a text box) that control is said to have the \u201cfocus.\u201d When you leave that control (for example, by clicking somewhere else or by pressing the TAB key) the control loses the focus. When the control loses focus, the onFocusOut event fires, and \u2013 in this case\u2014results in our HTA running the subroutine VerifyEntry.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<TABLE class=\"dataTable\" id=\"EHE\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. If none of that makes any sense to you that\u2019s either because the Scripting Guy who writes this column repeated each and every word (\u201cThe column so nice he wrote it twice!\u201d) or, more likely, because you aren\u2019t familiar with HTAs. How can you <I>become<\/I> familiar with HTAs? Why, by checking out the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/htas.mspx\"><B>HTA Developers Center<\/B><\/A>, of course.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>As you might expect, any excitement generated by this script will be generated by the VerifyEntry subroutine. In fact, the first thing we do inside this subroutine is <I>very<\/I> exciting: we create an instance of the <B>VBScript.RegExp<\/B> object. This, by the way, is a VBScript object that enables us to perform regular expression searches. <\/P>\n<TABLE class=\"dataTable\" id=\"EDF\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. What\u2019s that? You\u2019re not familiar with regular expression searches, either? Then you need to check out Dean Tsaltas\u2019 now-classic webcast <A href=\"http:\/\/www.microsoft.com\/events\/EventDetails.aspx?CMTYSvcSource=MSCOMMedia&amp;Params=%7eCMTYDataSvcParams%5e%7earg+Name%3d%22ID%22+Value%3d%221032271679%22%2f%5e%7earg+Name%3d%22ProviderID%22+Value%3d%22A6B43178-497C-4225-BA42-DF595171F04C%22%2f%5e%7earg+Name%3d%22lang%22+Value%3d%22en%22%2f%5e%7earg+Name%3d%22cr%22+Value%3d%22US%22%2f%5e%7esParams%5e%7e%2fsParams%5e%7e%2fCMTYDataSvcParams%5e\" target=\"_blank\"><B>String Theory for System Administrators<\/B><\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>After creating the regular expression object we next set the <B>Global<\/B> property to True; that ensures that the script will search the entire value typed into TextBox1. (Technically we don\u2019t need to search the entire value for this script. However, in most cases you <I>will<\/I> want to search the entire value; we added this line of code so you could see how to do that.) We then specify the <B>Pattern<\/B> we want to search for:<\/P><PRE class=\"codeSample\">objRegEx.Pattern = &#8220;[^ABCDEFG12345]&#8221;\n<\/PRE>\n<P>Regular expression syntax is always a bit goofy-looking (at best), so let\u2019s explain what we\u2019ve got here. We\u2019re assuming that RR only allows the following characters to be entered as a part number:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>A<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>B<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>D<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>E<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>F<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>G<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>1<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>2<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>3<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>4<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>5<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>By enclosing these characters in square braces we\u2019re able to specify the set of characters that we\u2019re looking for. Suppose we wanted to search for the characters X, Y, or Z? Then we\u2019d use this syntax:<\/P><PRE class=\"codeSample\">objRegEx.Pattern = &#8220;[XYZ]&#8221;\n<\/PRE>\n<P>Of course, in this case, we don\u2019t <I>want<\/I> to search for the characters in brackets; instead, we want to search for everything <I>except<\/I> the characters in brackets. Why? Well, suppose a user enters a part number of <I>AB325@<\/I>. We don\u2019t need to search for the characters A, B, 3, 2, or 5; it\u2019s perfectly legitimate for those characters to be included in the part number. Instead, we want to search for the @ sign, or for any other invalid character. That\u2019s why our pattern includes the <B>^<\/B> mark in front of the character set; that\u2019s regular expression syntax for, \u201cSearch for everything that <I>isn\u2019t<\/I> included in the character set.\u201d Want to search for X, Y, or Z? Then use this syntax:<\/P><PRE class=\"codeSample\">objRegEx.Pattern = &#8220;[XYZ]&#8221;\n<\/PRE>\n<P>Want to search for characters <I>other<\/I> than X, Y, or Z? Then use <I>this<\/I> syntax:<\/P><PRE class=\"codeSample\">objRegEx.Pattern = &#8220;[^XYZ]&#8221;\n<\/PRE>\n<P>Try the script a couple times and you\u2019ll see how this works.<\/P>\n<P>After defining the pattern we next need to identify the value we want to search. Because that value happens to be contained in the <B>Value<\/B> property of TextBox1 we use this line of code to assign the information typed into TextBox1 to a variable named strSearchString:<\/P><PRE class=\"codeSample\">strSearchString = TextBox1.Value\n<\/PRE>\n<P>From there we can call the <B>Execute<\/B> method and carry out our search: <\/P><PRE class=\"codeSample\">Set colMatches = objRegEx.Execute(strSearchString)\n<\/PRE>\n<P>As we noted a moment ago, what we\u2019re doing here is searching the variable strSearchString for any character that is <I>not<\/I> part of the specified character set. For each such match (that is, for each character that isn\u2019t part of the pattern) information about the match gets stored in the <B>Matches<\/B> collection (a collection we named colMatches). If all the characters in the string are valid characters then there won\u2019t <I>be<\/I> any matches; in that case the value of the <B>Count<\/B> property will be 0. If an invalid character <I>is<\/I> found, that means that the collection will include at least one item. Our next step is to check for that very thing by using this line of code:<\/P><PRE class=\"codeSample\">If colMatches.Count &gt; 0 Then\n<\/PRE>\n<P>If the Count is greater than 1 that means that we found at least one invalid character. In that case we execute these two lines of code:<\/P><PRE class=\"codeSample\">Msgbox &#8220;You entered an invalid character.&#8221;\nTextBox1.Focus\n<\/PRE>\n<P>In the first line we simply echo back a message box stating that an invalid character was entered. In the second line, we then set the focus back to TextBox1. That essentially forces the user to enter a valid part number before he or she can continue with data entry.<\/P>\n<P>That should do the trick. In the meantime, the Scripting Guy who writes this column is about to become the Scripting Guy who\u2019s driving to Walla Walla. (Although that seems a little pointless, considering the fact that the Walla Walla Corn Maze doesn\u2019t open until September 15<SUP>th<\/SUP>.) But don\u2019t worry: although he\u2019ll be out of town enjoying such attractions as the Nothing New antiques store (because new antiques are just never as much fun as old antiques) the Scripting Guy who writes this column will make sure that there\u2019s a new <I>Hey, Scripting Guy!<\/I> each and every day. Does that means that he\u2019s such a devoted and dedicated Microsoft employee that he\u2019s willing to work on his vacation? You bet that\u2019s what it means.<\/P>\n<P>Well, that and the fact that he\u2019s hoping to claim that these weren\u2019t actually vacation days after all. Hey, he <I>did<\/I> write a new column each and every day, didn\u2019t he? That sounds like work to us. (OK, true, it really <I>isn\u2019t<\/I> much work. But it <I>sounds <\/I>like work.)<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have an HTA which includes a text box where the user must enter a part number. Part numbers must consist of a certain set of characters; how can I determine if a user entered an invalid character in the part number text box?&#8212; RR Hey, RR. You know, with one exception, [&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,5,30],"class_list":["post-64473","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-scripting-techniques","tag-vbscript","tag-web-pages-and-htas"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have an HTA which includes a text box where the user must enter a part number. Part numbers must consist of a certain set of characters; how can I determine if a user entered an invalid character in the part number text box?&#8212; RR Hey, RR. You know, with one exception, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64473","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=64473"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64473\/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=64473"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=64473"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=64473"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}