{"id":493,"date":"2010-11-10T20:20:16","date_gmt":"2010-11-11T01:20:16","guid":{"rendered":"http:\/\/anvil-of-time.com\/wordpress\/?p=493"},"modified":"2021-03-10T18:04:49","modified_gmt":"2021-03-10T23:04:49","slug":"powerbuilder-formatting-and-validating-datetime-entries-in-a-datawindow","status":"publish","type":"post","link":"https:\/\/anvil-of-time.com\/powerbuilder\/powerbuilder-formatting-and-validating-datetime-entries-in-a-datawindow\/","title":{"rendered":"PowerBuilder &#8211; Formatting and Validating Date\/Time entries in a Datawindow"},"content":{"rendered":"<p>Using an editmask on a datawindow column to format a user&#8217;s input is pretty common practice for most applications. Done right it leads to a better user experience (no extra formatting characters to type) and can be visually appealing (all phone numbers formatted the same way for example). One really annoying behavior of an editmask appears when they are put on datetime fields and you need a way to validate that the user has entered a time and\/or a date.<\/p>\n<p>Since &#8217;00:00&#8242;, using hh:mm format, is a valid time, how do you ensure the user put in a value on a newly inserted row? Now if the time is the only column on the datawindow you can check the itemstatus of the new row to see if it is NewModified! but this would rarely be practical. Other issues with formats and EditMasks on datetime columns is they can sometimes show data you don&#8217;t want to be shown or invalid data can cause unexpected results.<\/p>\n<p>This solution involves using computed columns in the SQL statement making up the datawindow.<\/p>\n<p>SQL statement for Datawindow Object<\/p>\n<pre name=\"code\" class=\"SQL\">SELECT cht_cls_by\n, CONVERT(nvarchar(10), cht_cls_dt, 101) as cht_cls_date -- computed column\n, CONVERT(nvarchar(5), cht_cls_dt, 108) as cht_cls_time -- computed column\n, cas_int_id\n, cht_cls_dt\nFROM  CASE_HEADER<\/pre>\n<p>Results<\/p>\n<pre name=\"code\" class=\"VB\">cht_cls_by\tcht_cls_date\tcht_cls_time\tcas_int_id\tcht_cls_dt\nmbalent\t\t11\/01\/2010\t\t13:00\t\t\t4504\t\t2010-11-01 13:00:00.000\nnkennard\t10\/19\/2010\t\t10:30\t\t\t4505\t\t2010-10-19 10:30:57.600\nhcorey\t\t10\/20\/2010\t\t13:02\t\t\t4506\t\t2010-10-20 13:02:31.790\nNULL\t\tNULL\t\t\tNULL\t\t\t4507\t\tNULL\nNULL\t\tNULL\t\t\tNULL\t\t\t4508\t\tNULL\nNULL\t\tNULL\t\t\tNULL\t\t\t4509\t\tNULL<\/pre>\n<p>Now on the datawindow object itself you place the cht_cls_by, cht_cls_date, and cht_cls_time columns. In the update properties of the datawindow you select the cht_cls_by and the cht_cls_dt columns (and the id column too if you allow the inserting of rows).<\/p>\n<p>In the ItemChanged event put the following:<\/p>\n<pre name=\"code\" class=\"VB\">date ldt_date\n\nCHOOSE CASE dwo.name\n\tcase &#039;cht_cls_time&#039;\n\t\tIF IsTime(data) THEN\n\t\t\tpost event ue_post_itemchanged(dwo.Name, row, data)\n\t\tELSE\n\t\t\tMessagebox(&#039;Error&#039;, &quot;Please enter a valid time in &#039;hh:mm&#039; format.&quot;)\n\t\t\tRETURN 1\n\t\tEND IF\n\tcase &#039;cht_cls_date&#039;\n\t\tIf IsDate(data) THEN\n\t\t\tpost event ue_post_itemchanged(dwo.Name, row, data)\n\t\tELSE\n\t\t\tMessagebox(&#039;Error&#039;, &quot;Please enter a valid date.&quot;)\n\t\t\tRETURN 1\n\t\tEND IF\nEND CHOOSE<\/pre>\n<p>Create a user event on the datawindow called ue_post_itemchanged.<br \/>\nIt takes three parameters: as_name (string), al_row (long), as_data (string)<\/p>\n<pre name=\"code\" class=\"VB\">\/\/ posted from itemchanged to format time value correctly\n\/\/ and to update the datetime column with the time portion\ndate ld_date\ndatetime ldt_db_date\nstring ls_data_date\ntime lt_time\n\nCHOOSE CASE al_name\n\tCASE &#039;cht_cls_date&#039;\n\t\tldt_db_date = this.getitemdatetime(al_row,&#039;cht_cls_dt&#039;)\n\t\tIF IsNull(ldt_db_date) THEN\n\t\t\tldt_db_date = datetime(Today()) \/\/ no date, set to today (time is 00:00)\n\t\tEND IF\n\t\tlt_time = Time(ldt_db_date) \/\/ get current datetime value\t\n\t\tls_data_date = string(Date(al_data), &#039;mm\/dd\/yyyy&#039;) \/\/ set to standard format\n\t\tthis.setitem(al_row,&#039;cht_cls_date&#039;, ls_data_date) \/\/ put back to datawindow\n\t\tthis.setitem(al_row,&#039;cht_cls_dt&#039;, DateTime(Date(al_data),lt_time)) \/\/ put the time value on the datetime\n\tCASE &#039;cht_cls_time&#039;\n\t\tldt_db_date = this.getitemdatetime(al_row,&#039;cht_cls_dt&#039;)\n\t\tIF IsNull(ldt_db_date) THEN\n\t\t\tldt_db_date = datetime(Today()) \/\/ no date, set to today (time is 00:00)\n\t\tEND IF\n\t\tIF POS(al_data,&#039;:&#039;) &gt; 0 THEN\n\t\t\tal_data = Replace(al_data,Pos(al_data,&#039;:&#039;),1,&#039;&#039;) \/\/ strip off any colon \n\t\tEND IF\n\t\t \/\/ ensure value has four positions\n\t\tDO WHILE Len(al_data) &lt; 4\n\t\t\tIF Len(al_data) = 1 THEN\n\t\t\t\tal_data = &#039;0&#039; + al_data\n\t\t\tELSE\n\t\t\t\tal_data +=&#039;0&#039;\n\t\t\tEND IF\n\t\tLOOP\n\t\tal_data = Left(al_data,2) + &#039;:&#039; + Right(al_data, 2) \/\/ insert colon\n\t\tthis.setitem(al_row,&#039;cht_cls_time&#039;, al_data) \/\/ set the time value so it looks consistant\n\t\tthis.setitem(al_row,&#039;cht_cls_dt&#039;, DateTime(Date(ldt_db_date),Time(al_data))) \/\/ put the time value on the datetime\nEND CHOOSE<\/pre>\n<p>Finally in ItemError event put the following:<\/p>\n<pre name=\"code\" class=\"VB\">CHOOSE CASE dwo.name \n\tCASE &#039;cht_cls_time&#039;, &#039;cht_cls_date&#039;\n\t\tRETURN 2\nEND CHOOSE<\/pre>\n<p>You will also have to code a validation routine which will make sure data has been entered in each cht_cls_date and cht_cls_time columns for rows which have been modified. This would be called after accepttext but prior to updating the database.<\/p>\n<p>Example:<br \/>\n<a href=\"http:\/\/anvil-of-time.com\/wordpress\/wp-content\/uploads\/2010\/11\/Time-entry-example.png\"><img loading=\"lazy\" class=\"aligncenter wp-image-496 size-full\" title=\"Time entry example\" src=\"https:\/\/anvil-of-time.com\/wp-content\/uploads\/2010\/11\/Time-entry-example.png\" alt=\"\" width=\"391\" height=\"118\" srcset=\"https:\/\/anvil-of-time.com\/wp-content\/uploads\/2010\/11\/Time-entry-example.png 391w, https:\/\/anvil-of-time.com\/wp-content\/uploads\/2010\/11\/Time-entry-example-300x90.png 300w, https:\/\/anvil-of-time.com\/wp-content\/uploads\/2010\/11\/Time-entry-example-150x45.png 150w\" sizes=\"(max-width: 391px) 100vw, 391px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Using an editmask on a datawindow column to format a user&#8217;s input is pretty common practice for most applications. Done right it leads to a better user experience (no extra formatting characters to type) and can be visually appealing (all phone numbers formatted the same way for example). One really annoying behavior of an editmask&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,10],"tags":[21,12,16],"_links":{"self":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/493"}],"collection":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/comments?post=493"}],"version-history":[{"count":11,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/493\/revisions"}],"predecessor-version":[{"id":1884,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/493\/revisions\/1884"}],"wp:attachment":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/media?parent=493"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/categories?post=493"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/tags?post=493"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}