Data is processed in all computer programs. Data is to be seen as information bound to characters. These statements make it clear once again that we are still dealing with electronic data processing (EDP) at present! Today, this is done at a high level in terms of the algorithms, programming languages and computers used. No comparison to the beginnings in computer science, which the author experienced in the computer center at the TH Magdeburg and in the computer science lectures of Dr. Stuchlik from 1967-1971.
The data to be processed
This chapter focuses on the component 'Textbox'. Note that a text box in the TextBox.Text property returns a string (data type String) when you read input from a TextBox. You must decide whether you want to remove the text from a text box or not.
for further use.
Irrespective of your decision for the specific application, you as a program developer should ensure that only valid character strings are forwarded to the program as (valid) data from a TextBox in order to prevent runtime errors! A runtime error in the program flow occurs, for example, if a string is entered in a TextBox that cannot be converted into a natural number, which is expected there, or a file that does not exist in the specified directory is accessed in a procedure. A large number of such errors can be intercepted, displayed or processed in appropriate error handling routines by defensive programming. In all cases, protection of the programme has priority!
Before embarking on the rather arduous path of validating entries from a text box, you should check whether there are alternatives to the TextBox and its specializations in order to be able to make secure entries!
These alternatives - in the context of the tasks to be solved - include the following components:
The following components are not alternatives because you must always check the entries before you can continue to process valid data:
If none of the above-mentioned alternative components are considered for your Gambas project, you must design, implement and test your own concepts for validating entries from a TextBox (InputBox, MaskBox, ValueBox, HistoryBox and ButtonBox). A tried and tested approach consists of
Often the character scanner is omitted as a pre-check and only the return value from the text box or its specializations is examined. Note that the return value is from a TextBox, MaskBox or HistoryBox of type String and from type Date from a DateBox.
The following tasks are to be processed to check entries from a TextBox or its specializations in order to provide valid data:
(A1) Save that in a program only valid date values in the (English) format tt.mm.jjjj can be processed further! (A2) Develop suitable procedures to check entries from the following components:
Public dDatum As Date ... Public Sub DateChooser1_Activate() dDatum = DateChooser1.Value DateBox1.Value = dDatum End ' DateChooser1_Activate()
If you are using a MaskBox or DateBox or ValueBox (Date type), you must check the entries yourself before you can save an entered date in the variable dDate and process it further or display an error message:
Figure 16.6.2.1.1: Secure entries from a TextBox or its specializations
In the Date-TextBox the function IsDate () is used for checking the date in the German format dd. mm.yyyyy. However, this function includes the current system language in its test. Therefore, a date in the German format can only be recognized as such if the system language is set to German, otherwise the program will always return an input error in spite of correct date input.
The used solution idea consists of
first save the character string from the TextBox in the local variable sEnter (line 24), remove all blanks at the beginning and end of the string (line 25) and reduce all duplicate blanks in the character string to a single space if they exist (lines 27 to 29); and then split the character string with the split function into 3 parts (line 32), using the space character as a separator. All 3 parts are stored as elements in a string array aMatrix.
This idea can be adapted for many tasks with other separators. The source code for all four partial solutions is completely specified and commented on:
[1] Public dDatum As Date [2] Public sMAC As String [3] Public sMessage As String [4] Public sIPAdresse As String [5] [6] Public Sub Form_Open() [7] FMain.Center() [8] FMain.Resizable = False [9] ' Mode constants are in the DateChooser class and not in DateBox class! [10] DateBox1.Mode = DateChooser.DateOnly [11] ' DateBox1.Value = Now ' Then no data check would be necessary! [12] DateBox1.ReadOnly = True [13] ValueBoxIP.Type = ValueBoxIP.IPAddress [14] MaskBoxMAC.Mask = "[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9] \ [a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]" [15] End ' Form_Open() [16] [17] Public Sub txtDate_Activate() [18] Dim aMatrix As String[] [19] Dim aMonate As String[] [20] Dim sMonat, sEingabe, sDatum As String [21] [22] aMonate = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", \ "September", "Oktober", "November", "Dezember"] [23] [24] sEingabe = txtDate.Text [25] sEingabe = Trim(sEingabe) [26] [27] While InStr(sEingabe, " ") [28] sEingabe = Replace$(sEingabe, " ", " ") [29] Wend [30] txtDate.Text = sEingabe [31] [32] aMatrix = Split(sEingabe, " ") [33] [34] If aMatrix.Count <> 3 Then [35] Message.Error("Input error") [36] Return [37] Endif ' aMatrix.Count <> 3 ? [38] [39] If aMonate.Exist(aMatrix[1]) Then [40] sMonat = Str(aMonate.Find(aMatrix[1]) + 1) [41] Else [42] Message.Error("Input error") [43] Return [44] Endif ' aMonate.Exist(aMatrix[1]) ? [45] [46] sDatum = aMatrix[0] & sMonat & "." & aMatrix[2] [47] [48] If IsDate(sDatum) Then [49] dDatum = Val(sDatum) [50] DateBox1.Value = dDatum ' For control only [51] Else [52] Message.Error("Input error") [53] Return [54] Endif ' IsDate(sDatum) [55] End ' txtDate_Activate()
Comment:
Lines 34-37 check whether exactly 3 elements were stored in array aMatrix. In the event of an error, an error message is output, and the system checks whether the month name was written correctly in lines 39-44; if an error occurs, a corresponding message is output. If the test is positive, the variable sMonth in line 46 is used to specify a date string in the format tt.mm.jjjj. Finally, the function IsDate(…) checks whether the character string sDate can be interpreted as a valid German date - otherwise there is a suitable message.
“The MAC address (Media Access Control Address) is the hardware address of each individual network adapter that serves as the unique identifier of the device in a computer network.” can be found under the link: http://de.wikipedia.org/wiki/MAC-Adresse. A MAC address is a 48-bit data word or a 6-byte data word. The 6 bytes are hexadecimal and are separated by 5 colons. An adapted solution idea is implemented as in the subtask A. 2.1. By using the set MAC mask it is guaranteed that only allowed characters[0-9a-fA-F] are accepted by the MaskBox. All other characters are ignored. Therefore, lines 10 to 13 and a character scanner in lines 15 to 20 could also be omitted here. The mask with spaces and colons will not be displayed until you activate the box with a single click. The source code in line 22 only ensures that the entered letters are displayed in the MAC address as uppercase letters - pure display cosmetics.
[1] Public Sub MaskBoxMAC_Activate() [2] ' Datentyp von MaskBoxMAC.Text ist String [3] Dim aMatrix As String[] [4] Dim sEingabe, sElement As String [5] [6] sEingabe = MaskBoxMAC.Text [7] sEingabe = Trim(sEingabe) [8] aMatrix = Split(sEingabe, ":") [9] [10] If aMatrix.Count <> 6 Then [11] Message.Error("Input error_1") [12] Return [13] Endif ' aMatrix.Count <> 6 ? ' Can be omitted here because a mask is used [14] [15] For Each sElement In aMatrix [16] If Left(sElement) Not Like "[abcdefABCDEF0123456789]" Or \ Right(sElement) Not Like "[abcdefABCDEF0123456789]" Then [17] 'If Left(sElement) Not Like "[a-fA-F0-9]" Or Right(sElement) Not Like "[a-fA-F0-9]" Then [18] Message.Error("Input error_2") [19] Return [20] Endif ' Character not in input alphabet? [21] Next ' sElement [22] sMAC = Upper(sEingabe) [23] MaskBoxMAC.Text = sMAC [24] End ' MaskBoxDate_Activate()
A DateBox is a specialized MaskBox. By specifying the property DateBox. Mode you can select either a date (Mode = 0) or a time (Mode = 2) or a timestamp with date and time (Mode = 1). The mode constants are currently only available in the DateChooser class and not in the DateBox class - what to expect. You must set the mode so:
DateBox1.Mode = 0 DateBox1.Mode = DateChooser.DateOnly ' Alternative
A click on the small button on the right opens a date selection dialog, from which you can select a valid date that is then displayed with the corresponding date mask. If you set the DateBox. readonly property to True, you can no longer change this displayed date.
If you do not initialize the DateBox with a (valid) date, you must check the entries in the DateBox in this way:
Public Sub DateBox1_Activate() ' TypeOf(DateBox1.Value) = 8 => Data type: Date If Not IsDate(Str(DateBox1.Value)) Then sMessage = "The entry is not a correct date!" ' DateBox1.Value is NULL! Message.Error(sMessage) Return Else dDatum = DateBox1.Value Endif ' Not IsDate(Str(DateBox1.Value)) ? End ' DateBox1_Activate() Public Sub DateBox1_DblClick() DateBox1_Activate() End ' DateBox1_DblClick()
With the following lines in the procedure Form_Open() a check is omitted. However, you can then no longer enter a date yourself and must use the date selection dialog box - but you will then receive valid date data:
DateBox1.Mode = DateChooser.DateOnly DateBox1.Value = Now DateBox1.ReadOnly = True
The entry of IP addresses into a Value-Box as a specialized MaskBox works without any problems with the specification of the type in the procedure Form_Open():
ValueBoxIP.Type = ValueBoxIP.IPAddress
However, you have to check the IP address you have entered, because the default mask only allows digits at the allowed places in the 4 digit blocks as input characters - but these can only be used at any position in the range from 0 to 9. 192.189.100.1 as well as 192.189.245.202 are accepted as inputs! The validation of valid data is based on proven approaches:
Public Sub ValueBoxIP_DblClick() ' Datentyp von ValueBoxIP.Value ist String Dim aMatrix As String[] Dim iCount As Integer aMatrix = Split(ValueBoxIP.Value, ".") For iCount = 0 To aMatrix.Max If Val(aMatrix[iCount]) < 0 Or Val(aMatrix[iCount]) > 255 Then sMessage = "Die IP-Adresse ist im " & (icount + 1) & ". Block fehlerhaft (" & aMatrix[iCount] & ") !" Message.Error(sMessage) Return Endif Next ' iCount sIPAdresse = ValueBoxIP.Value End ' ValueBoxIP_DblClick()
After entering an IP address, the check is carried out by double-clicking on the ValueBox. Note that you can change the cursor position in the ValueBox with the arrow keys < or >!
Note:
Please note the explanations in chapter → 19.6.5 Checking the syntax of character strings, because the new MATCH operator (from Gambas 3.4.2) in the component gb.pcre (Perl Compatible Regular Expression) simplifies the checking of character strings considerably.