Subject Re: ENTRYFIELD
From Ronnie MacGregor <No_Sp@m.Thanks>
Date Sun, 9 Jun 2019 20:44:37 +0100
Newsgroups dbase.getting-started

In article <rknVHXuHVHA.1864@ip-AC1E04A7>, mustan31@hotmail.com says...

> Can we set for this ENTRYFIELD its value type
> based on test chosen programatically.

No doubt you can, but beware of unintended results if you change the
entryfield's datatype when there is data already in the field (untested).

But I think what you are really asking is how to programatically determine the
type of the data that the user has entered. This may never be foolproof, but if
you know what to expect you might very well get acceptable results 99% of the
time.

We have a Patient search form which has a single entryfield into which you can
type a bit of a name, a bit of given name and family name, a date, a date of
birth, partial dates, NHS ID, Practice Patient Reference number, and the
resultant rowset is produced by first determinig the data type.

The following code will hopefully give you some ideas.

   //
===========================================================================
   //
===========================================================================


   function DetermineDataType(vTarget)

      // Initialise return value
      local cDataType
      cDataType = ""
      
      // Initialise RegEx
      local oRegEx
      oRegEx = new OleAutoClient("VBScript.RegExp")
      oRegEx.global = true
      oRegEx.ignoreCase = true

      // debug
      ? chr(13)
      ? "Determine data Type Fired"

      /*

              Data Types
         ==========
         Empty
         Invalid
         IndexNo
         FullDate
         PartDate
         TwoName
         OneName
         FullCHI
         PartCHI

      */


      // ===============
      // Deal with Empty
      // ===============

      /*

      If the search string is empty we need to empty results grid

      */

      // Deal with empty search string
      if len(ltrim(trim(vTarget))) == 0
         form.EF_SEARCH.value := ""
         return "Empty"
      endif


      // ==================
      // Deal with Index_No
      // ==================

      /*

      If we find the two Practice identifier Characters followed by at least
      one, and up to five digits, then we have an Index_No

      */

      // Test for Two Specific Alpha Characters plus 1 to 5 digits
      // ^[A-Z]{2}\d{1,5}
      // ^HL\d{1,5}
      oRegEx.pattern = "^" + form.PracticeID + "\d{1,5}$"
      if oRegEx.test((vTarget)) == true
         // Morph vTarget to strip Practice ID Characters
         vTarget := substr(vTarget, 3)
         if val(vTarget) < form.PxRowCount
            ? "We have an Index No"
            return "IndexNo"
         else
            ? "Invalid Index No"
            return "Invalid"
         endif
      endif // vTarget is an Index No


      // ================
      // Deal with CHI No
      // ================

      /*

      If we find three CHI identifier Characters followed by at least
      one, and up to 10 digits, then we have an CHI Number

      */

      // Test for Three Specific Alpha Characters plus 1 to 10 digits
      // ^CHI\d{1,10}
      oRegEx.pattern = "^CHI\d{1,10}"
      if oRegEx.test((vTarget)) == true
         ? "We have an CHI No"
         // Morph vTarget to strip CHI ID Characters
         vTarget := substr(vTarget, 4)
         if len(vTarget) < 10 // Part CHI
            ? "   Part CHI"
            return "PartCHI"
         elseif len(vTarget) == 10 // Full CHI
            ? "   Full CHI"
            return "FullCHI"
         endif
      endif // vTarget is an CHI No


      // ===============
      // Deal with Dates
      // ===============

      /*

      If we find both a numerical digit and a date separator character
      then our search string is most probably a date.

      Deal with the possibility of a single digit day or
      month having been entered.

      */

      // Test for basic date elements "n/" or "n-"
      oRegEx.pattern = "[\d][-/]"  

      if oRegEx.test((vTarget)) == true

         ? "We have basic date elements present"

         // Test for alphas
         // ============================

         oRegEx.pattern = '[a-zA-Z`!"\$%\^&\*\(\)_\+=' + ";:'@#~\\\|,\<\.
\>?]"  
         if oRegEx.test((vTarget)) == true
            ? "   Invalid Date (contains Alphas or Specials)"
            return "Invalid"
         endif

         // Get Parts
         oStr = new rmRegExpString( )
         oStr.String = vTarget
         aParts = oStr.split("[-/]/gi")

         // debug ///////////////////////////
         //for i=1 to aParts.size  
         //   ? aParts[i]                
         //next                                

         // Reconstruct vTarget to eliminate :
         //    Single digit day
         //    Single Digit month
         //    The separator "/"
         local d
         d = str(val(aParts[1]), 2, 0, "0") + "/"
         if aParts.size > 1
            d += str(val(aParts[2]), 2, 0, "0") + "/"
         endif
         if aParts.size > 2
            d += aParts[3]
         endif

         // vTarget was passed as an object reference, so we can update the
         // reformatted value in the calling funtion
         vTarget = d
         form.SearchTarget = (d)

         // Test for too many characters
         // ============================

         if len(vTarget) > 10
            ? "   Invalid Date"
            return "Invalid"
         endif

         // Test for FullDate or PartDate
         // =============================

         /*

         mm/dd/yyyy
         ==========

         "\b(1[0-2]|0?[1-9])[-/](0?[1-9]|[12][0-9]|3[01])[-/]((19|20)\d{2})"


         \b    Starts with a word boundary

         (1[0-2]|0?[1-9])
               First submatch: a 1 followed by a 0, 1, or 2 or
               an optional 0 followed by a digit between 1 and 9.

         [-/]  A dash or a slash

         (0?[1-9]|[12][0-9]|3[01])
               The second submatch for the day: There are three possibilities.
               1. An optional 0 followed by a digit between 1 and 9.
               2. A 1 or a 2 "[12]" followed   by a digit between 0 and 9
               3. A 3 followed by a 0 or a 1 "[01]"

         [-/]  Same as above, a dash or a slash.

         ((19|20)\d{2})
               The year. A 19 or a 20 "(19|20)" followed by exactly two
               digits"\d{2}"



         dd/mm/yyyy
         ==========

         "\b(0?[1-9]|[12][0-9]|3[01])[-/](1[0-2]|0?[1-9])[-/]((18|19|20)\d{2})"

         \b    Starts with a word boundary

         (0?[1-9]|[12][0-9]|3[01])
               First submatch: There are three possibilities.
               1. An optional 0 followed by a digit between 1 and 9.
               2. A 1 or a 2 "[12]" followed   by a digit between 0 and 9
               3. A 3 followed by a 0 or a 1 "[01]"

         [-/]  A dash or a slash

         (1[0-2]|0?[1-9])
               The second submatch : a 1 followed by a 0, 1, or 2 or
               an optional 0 followed by a digit between 1 and 9.

         [-/]  Same as above, a dash or a slash.

         ((18|19|20)\d{2})
               The year. A 19 or a 20 "(19|20)" followed by exactly two
               digits"\d{2}"


         */

         local bIsFullDate
         bIsFullDate = null
         oRegEx.pattern = "\b(0?[1-9]|[12][0-9]|3[01])[-/](1[0-2]|0?[1-9])[-/]
((18|19|20)\d{2})"
         bIsFullDate = oRegEx.test(vTarget)
         if bIsFullDate == true
            ? "   FullDate"
            return "FullDate"
         else
            ? "   PartDate"
            return "PartDate"
         endif

      endif // vTarget contains basic date elements


      // =================
      // Deal with Numbers
      // =================

      /*

      If we find numerical digits only then our search string is most probably
      a Px Index_No or a CHI number.

      */

      // Test for numeric digits only "^[0-9]*$"
      oRegEx.pattern = "^[0-9]*$"
      if oRegEx.test((vTarget)) == true
         // debug ///////////////////////////
         ? "We have numeric elements present"
         if val(vTarget) <= form.PxRowCount // Assume Px Index_No
            ? "   Assume Index_No"
            return "IndexNo"
         elseif len(vTarget) < 10 // Part CHI
            ? "   Part CHI"
            return "PartCHI"
         elseif len(vTarget) == 10 // Full CHI
            ? "   Full CHI"
            return "FullCHI"
         else
            ? "   Invalid Number"
            return "Invalid"
         endif
      endif // vTarget contains numeric elements only



      // =================
      // Deal with Strings
      // =================

      /*

      If we find Alpha Characters plus " ",/,- then our search string is most
      probably a name.

      *** This method may fail with accented characters. ***

      */

      // Test for Alpha Characters plus " ",/,-
      oRegEx.pattern = "^[a-zA-Z\s'-]*$"
      if oRegEx.test((vTarget)) == true
         ? "We have name elements present"
         oRegEx.pattern = "\b.*\s.*\b" // Find a space between words
         if oRegEx.test((vTarget)) == true
            ? "   Two Name"
            return "TwoName"          
         else
            ? "   One Name"
            return "OneName"
         endif
      endif // vTarget contains name elements


      // If we get to here, then we have not detected a valid data type
      // so return invalid.
      ? "Unmatched Data Type" /////////////////////////////////////

      return "Invalid"


   //
===========================================================================
   //
===========================================================================




--
Ronnie MacGregor
Scotland

Ronnie at
dBASEdeveloper
dot co dot uk

www.dBASEdeveloper.co.uk