home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / truegrid / disk1 / dbtable / dbtable.$ / XFORM1.BAS < prev   
Encoding:
BASIC Source File  |  1995-02-17  |  28.4 KB  |  897 lines

  1. ' ---------------------------------------------------------
  2. '       Copyright (C) 1993 Apex Software Corporation
  3. '
  4. ' You have a royalty-free right to use, modify, reproduce,
  5. ' and distribute the TrueGrid sample application files
  6. ' (and/or any modified version) in any way you find useful,
  7. ' provided that you agree that Apex Software Corporation
  8. ' has no warranty, obligations, or liability for any sample
  9. ' application files.
  10. ' ---------------------------------------------------------
  11.  
  12.  
  13. ' dBTable is a sample program to demonstrate how to use TrueGrid in
  14. ' "Callback mode."  I.e., the DataMode property of the grid is
  15. ' set to 1 (Callback).  In this mode, the grid is not connected
  16. ' to a database file.  Instead, data in the grid will be supplied and
  17. ' maintained by the programmer while the grid takes care of user
  18. ' interactions and data display.
  19. '
  20. ' dBTable allows user to enter a dBASE file structure in a table format.
  21. ' It is by no means a complete program.  It's sole purpose is to
  22. ' illustrate how to use TrueGrid in "Callback mode."
  23. '
  24. ' You do not need to understand dBASE nor its file structure to follow
  25. ' this sample program.  Just assume you are creating a program to allow
  26. ' users to enter information in a table format with the following
  27. ' specifications:
  28. '
  29. ' (1) Each row represents a field structure.
  30. ' (2) Maximum number of fields (or rows) allowed is 255.
  31. ' (3) The table has six columns (used to describe a field structure):
  32. '       col 1: Field number (range 1 to 255)
  33. '       col 2: Field name. 1 to 10 characters.  Allows only upper case
  34. '              letters, digits, and "_".  First character must be an
  35. '              upper case letter.
  36. '       col 3: Field type. 1 character.  Allows only "C", "N", "F", "D",
  37. '              "L", or "M" only.  (Stands for Character, Numeric, Float,
  38. '              Date, Logical and Memo field types, respectively.)
  39. '       col 4: Field width.  1 to 3 characters.  Contains digits only. The
  40. '              field width for Date, Logical and Memo fields are fixed at
  41. '              8, 1, and 10 characters, respectively.
  42. '       col 5: Field decimal width.  1 to 2 characters. Contains digits only.
  43. '              The field decimal width applies to Numeric and Float fields
  44. '              only.
  45. '       col 6: Field index flag.  "Y" if field is indexed, "N" otherwise.
  46. '
  47. '
  48. ' The routines in this sample program are commented in detail, so you should
  49. ' not have any problem following the code.  In this sample, you will learn:
  50. '
  51. ' (1) Use the Form _Load event (xForm1_load) to initialize the grid and
  52. '     internal arrays.
  53. ' (2) Use the Grid _Fetch event (xFieldTable_Fetch) to feed data to the grid.
  54. ' (3) Use the Grid _Update event (xFieldTable_Update) to get user updated
  55. '     data from the grid.
  56. ' (4) Use the Grid _KeyPress event (xFieldTable_KeyPress) to check and
  57. '     restrict user input.
  58. ' (5) Use the Grid _Validate event (xFieldTable_Validate) to check and
  59. '     validate user input
  60. ' (6) Use the Grid _ColumnChange event (xFieldTable_ColumnChange) to display
  61. '     context sensitive help for the user.
  62. ' (7) Use the Grid _Append (xFieldTable_Append) event to append additional
  63. '     rows to the table.
  64. '
  65. '
  66. ' Also, the 3-D look of the grid was achieved by setting the following grid
  67. ' properties at design time:
  68. '
  69. ' (1) HorzLines = 2-3D
  70. ' (2) HorzColor was chosen to be gray
  71. ' (3) VertLines = 2-3D
  72. ' (4) VertColor was chosen to be gray
  73.  
  74.  
  75. ' Array to store dBASE field structures
  76. Dim FieldNo(1 To 255)  As String                ' Field number
  77. Dim FieldName(1 To 255)  As String              ' Field name
  78. Dim FieldType(1 To 255)  As String              ' Field type
  79. Dim FieldWidth(1 To 255)  As String             ' Field width
  80. Dim FieldDec(1 To 255)  As String               ' Field decimal
  81. Dim FieldIndex(1 To 255)  As String             ' Field index flag
  82.  
  83. Dim NumFields As Integer                ' Number of fields defined by user
  84.                                         ' in the field table
  85.  
  86. ' Column number of field properties
  87. Const NO_COL = 1                  ' Column number for field number
  88. Const NAME_COL = 2                ' Column number for field name
  89. Const TYPE_COL = 3                ' Column number for field type
  90. Const WIDTH_COL = 4               ' Column number for field width
  91. Const DEC_COL = 5                 ' Column number for field decimal width
  92. Const INDEX_COL = 6               ' Column number for field index flag
  93.  
  94. ' Maximum number of characters allowed for columns or field properties.
  95. ' For a given column, user can enter no more than the number of characters
  96. ' specified below.
  97. Const NO_SZ = 3                   ' Field number
  98. Const NAME_SZ = 10                ' Field name
  99. Const TYPE_SZ = 1                 ' Field type
  100. Const WIDTH_SZ = 3                ' Field width
  101. Const DEC_SZ = 2                  ' Field decimal width
  102. Const INDEX_SZ = 1                ' Field index flag
  103.  
  104. ' Columns display widths (in characters).  Note that the display widths
  105. ' are bigger than the maximum number of characters allowed for the columns
  106. ' so that the table will look nice and will not be crowded.
  107. Const NO_WIDTH = 4
  108. Const NAME_WIDTH = 13
  109. Const TYPE_WIDTH = 5
  110. Const WIDTH_WIDTH = 6
  111. Const DEC_WIDTH = 4
  112. Const INDEX_WIDTH = 8
  113.  
  114. ' constant ASCII values used in the program
  115. Const A = 65
  116. Const Z = 90
  117. Const sA = 97
  118. Const sZ = 122
  119. Const A_a = 65 - 97
  120. Const Asc0 = 48
  121. Const Asc9 = 57
  122. Const Asc_ = 95
  123. Const C = 67
  124. Const N = 78
  125. Const F = 70
  126. Const D = 68
  127. Const L = 76
  128. Const M = 77
  129. Const Y = 89
  130. Const BackSpace = 8
  131.  
  132. Sub ClearFieldArray ()
  133.     Dim i As Integer
  134.  
  135.     ' Clear field table arrays.
  136.     For i = 1 To 255
  137.         ClearFieldRow i
  138.     Next i
  139.  
  140.     NumFields = 0
  141.     Form1.FieldTable.Rows = 0
  142. End Sub
  143.  
  144. Sub ClearFieldRow (Row As Integer)
  145.     FieldName(Row) = ""
  146.     FieldType(Row) = ""
  147.     FieldWidth(Row) = ""
  148.     FieldDec(Row) = ""
  149.     FieldIndex(Row) = ""
  150. End Sub
  151.  
  152. Sub InitFieldTable ()
  153.     Dim i As Integer
  154.  
  155.     ' Define Field number array
  156.     For i = 1 To 255
  157.         FieldNo(i) = Mid$(Str$(i), 2)
  158.     Next i
  159.  
  160.     ' Clear field table arrays
  161.     ClearFieldArray
  162.  
  163.     ' Define column heading text.  This can be done in code at runtime
  164.     ' or in the Layout Editor during design time.
  165.     Form1.FieldTable.ColumnName(NO_COL) = "No."
  166.     Form1.FieldTable.ColumnName(NAME_COL) = "Field Name"
  167.     Form1.FieldTable.ColumnName(TYPE_COL) = "Type"
  168.     Form1.FieldTable.ColumnName(WIDTH_COL) = "Width"
  169.     Form1.FieldTable.ColumnName(DEC_COL) = "Dec"
  170.     Form1.FieldTable.ColumnName(INDEX_COL) = "Indexed"
  171.  
  172.     ' Maximum number of characters allowed for columns.  For a given
  173.     ' column, user can enter no more than the number of characters
  174.     ' specified below.
  175.     Form1.FieldTable.ColumnSize(NO_COL) = NO_SZ
  176.     Form1.FieldTable.ColumnSize(NAME_COL) = NAME_SZ
  177.     Form1.FieldTable.ColumnSize(TYPE_COL) = TYPE_SZ
  178.     Form1.FieldTable.ColumnSize(WIDTH_COL) = WIDTH_SZ
  179.     Form1.FieldTable.ColumnSize(DEC_COL) = DEC_SZ
  180.     Form1.FieldTable.ColumnSize(INDEX_COL) = INDEX_SZ
  181.  
  182.     ' Columns display widths (in characters).  Note that the display
  183.     ' widths are bigger than ColumnSize(s) so that the table will look
  184.     ' nice and will not be crowded.
  185.     Form1.FieldTable.ColumnWidth(NO_COL) = NO_WIDTH
  186.     Form1.FieldTable.ColumnWidth(NAME_COL) = NAME_WIDTH
  187.     Form1.FieldTable.ColumnWidth(TYPE_COL) = TYPE_WIDTH
  188.     Form1.FieldTable.ColumnWidth(WIDTH_COL) = WIDTH_WIDTH
  189.     Form1.FieldTable.ColumnWidth(DEC_COL) = DEC_WIDTH
  190.     Form1.FieldTable.ColumnWidth(INDEX_COL) = INDEX_WIDTH
  191.  
  192.     ' Column styles.  Specify left, center, or right justified.  Also
  193.     ' specifies if a column is readonly (i.e., user cannot edit that
  194.     ' column).
  195.     Form1.FieldTable.ColumnStyle(NO_COL) = GRS_LEFT + GRS_READONLY
  196.     Form1.FieldTable.ColumnStyle(NAME_COL) = GRS_LEFT
  197.     Form1.FieldTable.ColumnStyle(TYPE_COL) = GRS_LEFT
  198.     Form1.FieldTable.ColumnStyle(WIDTH_COL) = GRS_RIGHT
  199.     Form1.FieldTable.ColumnStyle(DEC_COL) = GRS_RIGHT
  200.     Form1.FieldTable.ColumnStyle(INDEX_COL) = GRS_LEFT
  201.  
  202.     ' Can user move and resize columns?  We set it to False, you can
  203.     ' set it to True to experiment.
  204.     Form1.FieldTable.Configurable = False
  205.  
  206.     ' Display column heading text?
  207.     Form1.FieldTable.Headings = True
  208.  
  209.     ' Start with 1 rows in the table.
  210.     Form1.FieldTable.Rows = 1
  211.  
  212.     ' Initialize current cell position.  Note that column 1 is the field
  213.     ' number, so we start at column 2 for user to enter the field name.
  214.     Form1.FieldTable.RowIndex = 1
  215.     Form1.FieldTable.ColumnIndex = 2
  216. End Sub
  217.  
  218. Function IsDigit (KeyAscii As Integer)
  219.     If KeyAscii < Asc0 Or KeyAscii > Asc9 Then
  220.         IsDigit = False
  221.     Else
  222.         IsDigit = True
  223.     End If
  224. End Function
  225.  
  226. Function IsDLM (FieldType As Integer) As Integer
  227. '
  228. ' Check if FieldType character is "D (Date)", "L (Logical)" or "M (Memo)"
  229. '
  230.     If FieldType = D Or FieldType = L Or FieldType = M Then
  231.         IsDLM = True
  232.     Else
  233.         IsDLM = False
  234.     End If
  235. End Function
  236.  
  237. Function IsLM (FieldType As Integer) As Integer
  238. '
  239. ' Check if FieldType character is "L (Logical)" or "M (Memo)"
  240. '
  241.     If FieldType = L Or FieldType = M Then
  242.         IsLM = True
  243.     Else
  244.         IsLM = False
  245.     End If
  246. End Function
  247.  
  248. Function IsNF (FieldType As Integer) As Integer
  249. '
  250. ' Check if FieldType character is "N (Numeric)" or "F (Float)".
  251. '
  252.     If FieldType = N Or FieldType = F Then
  253.         IsNF = True
  254.     Else
  255.         IsNF = False
  256.     End If
  257. End Function
  258.  
  259. Function IsUpperLetter (KeyAscii As Integer)
  260.     If KeyAscii < A Or KeyAscii > Z Then
  261.         IsUpperLetter = False
  262.     Else
  263.         IsUpperLetter = True
  264.     End If
  265. End Function
  266.  
  267. Function IsValidFieldDec (Row As Integer, Value As String) As Integer
  268. '
  269. ' This function checks if the FieldDec value in the current cell is
  270. ' valid.
  271. '
  272.     Dim w As Integer
  273.     Dim D As Integer
  274.     Dim t As Integer
  275.  
  276.     t = Asc(FieldType(Row))
  277.  
  278.     '
  279.     ' Need to check FieldDec only if it is a numeric field
  280.     '
  281.     If IsNF(t) = False Then
  282.         IsValidFieldDec = True
  283.         Exit Function
  284.     End If
  285.  
  286.     '
  287.     ' If empty, print it as 0
  288.     '
  289.     If Value = "" Then
  290.         Value = "0"
  291.         IsValidFieldDec = True
  292.         Exit Function
  293.     End If
  294.  
  295.     '
  296.     ' Make sure there is enough room for decimal digits
  297.     '
  298.     w = Val(FieldWidth(Row))
  299.     D = Val(Value)
  300.     If D <> 0 And (w - D) < 2 Then
  301.         MsgBox "(Width - Dec) must be greater than 1.", 48, "Error"
  302.         IsValidFieldDec = False
  303.         Exit Function
  304.     End If
  305.  
  306.     ' Eliminate leading 0
  307.     Value = Mid$(Str$(D), 2)
  308.  
  309.     IsValidFieldDec = True
  310. End Function
  311.  
  312. Function IsValidFieldName (Row As Integer, Value As String) As Integer
  313. '
  314. ' This function makes sure FieldName starts with an upper case letter
  315. ' and there is no duplicate FieldName in the table
  316. '
  317.     Dim i As Integer
  318.     Dim rsh As Integer
  319.  
  320.     '
  321.     ' Make sure FieldName is not empty
  322.     '
  323.     If Value = "" Then
  324.         MsgBox "Field name not defined.", 48, "Error"
  325.         IsValidFieldName = False
  326.         Exit Function
  327.     End If
  328.  
  329.     '
  330.     ' Make sure 1 st FieldName character is an upper case letter
  331.     '
  332.     If IsUpperLetter(Asc(Value)) = False Then
  333.         MsgBox "First field name character must be a letter.", 48, "Error"
  334.         IsValidFieldName = False
  335.         Exit Function
  336.     End If
  337.  
  338.     '
  339.     ' Make sure there is no duplicate FieldName in the table
  340.     '
  341.     For i = 1 To Form1.FieldTable.Rows
  342.         If Row <> i And Value = FieldName(i) Then
  343.             MsgBox "Duplicate field name: " + Value, 48, "Error"
  344.             IsValidFieldName = False
  345.             Exit Function
  346.         End If
  347.     Next i
  348.  
  349.     '
  350.     ' Assume no other cell values (other than the current cell) has
  351.     ' been changed changed by the programmer.
  352.     '
  353.     rsh = False
  354.  
  355.     '
  356.     ' Fill in some default values
  357.     '
  358.     If FieldDec(Row) = "" Then
  359.         FieldDec(Row) = "0"     ' Set FieldDec to 0
  360.         rsh = True              ' To flag other cell value has changed
  361.     End If
  362.  
  363.     If FieldIndex(Row) = "" Then
  364.         FieldIndex(Row) = "N"   ' Set FieldIndex to "N"
  365.         rsh = True              ' To flag other cell value has changed
  366.     End If
  367.  
  368.     '
  369.     ' To refresh row if programmer has changed values in other cells.
  370.     ' The grid knows user has made changes in the current cell, but it
  371.     ' cannot know that the programmer has changed values in other cells,
  372.     ' so the programmer has to call RefreshRow to force the grid to
  373.     ' refresh the row so that all new cell values will be displayed.
  374.     '
  375.     ' Note that the programmer changes cell values by updating its
  376.     ' internal storage and then tell the grid to update the display.
  377.     '
  378.     If rsh Then Form1.FieldTable.RefreshRow = Row
  379.  
  380.     IsValidFieldName = True
  381. End Function
  382.  
  383. Function IsValidFieldNameChar (KeyAscii As Integer) As Integer
  384. '
  385. ' This function checks if KeyAscii is a valid field name character.
  386. ' A valid field name character must be either an upper case letter,
  387. ' a digit, or "_".
  388. '
  389.     IsValidFieldNameChar = True
  390.  
  391.     If IsUpperLetter(KeyAscii) = False Then
  392.         If IsDigit(KeyAscii) = False Then
  393.             If KeyAscii <> Asc_ Then
  394.                 IsValidFieldNameChar = False
  395.             End If
  396.         End If
  397.     End If
  398.  
  399. End Function
  400.  
  401. Function IsValidFieldType (Row As Integer, Value As String) As Integer
  402. '
  403. ' This function checks if the FieldType value in the current cell is
  404. ' valid.  Depending on the FieldType, it also fills in some default
  405. ' values in other cells.
  406. '
  407.  
  408.     IsValidFieldType = False
  409.  
  410.     '
  411.     ' Check if field is empty
  412.     '
  413.     If Value = "" Then
  414.         MsgBox "Field type not defined.", 48, "Error"
  415.         Exit Function
  416.     End If
  417.  
  418.     '
  419.     ' Fill in some default values
  420.     '
  421.     Select Case Asc(Value)
  422.         Case C
  423.             '
  424.             ' A character field does not have decimal field width
  425.             '
  426.             FieldDec(Row) = "0"
  427.         Case N, F
  428.             '
  429.             ' Default decimal field width is 0
  430.             '
  431.             If FieldDec(Row) = "" Then
  432.                 FieldDec(Row) = "0"
  433.             End If
  434.         Case D
  435.             '
  436.             ' A date field has a fixed length of 8
  437.             '
  438.             FieldWidth(Row) = "8"
  439.             FieldDec(Row) = "0"
  440.         Case L
  441.             '
  442.             ' A logical field has a fixed length of 1 and it cannot
  443.             ' be indexed
  444.             '
  445.             FieldWidth(Row) = "1"
  446.             FieldDec(Row) = "0"
  447.             FieldIndex(Row) = "N"
  448.         Case M
  449.             '
  450.             ' A memo field has a fixed length of 10 and it cannot
  451.             ' be indexed
  452.             '
  453.             FieldWidth(Row) = "10"
  454.             FieldDec(Row) = "0"
  455.             FieldIndex(Row) = "N"
  456.     End Select
  457.  
  458.     ' Refresh current row
  459.     '
  460.     ' The grid knows user has made changes in the current cell, but it
  461.     ' cannot know that the programmer has changed values in other cells,
  462.     ' so the programmer has to call RefreshRow to force the grid to
  463.     ' refresh the row so that all new cell values will be displayed.
  464.     '
  465.     ' Note that the programmer changes cell values by updating its
  466.     ' internal storage and then tell the grid to update the display.
  467.     '
  468.     Form1.FieldTable.RefreshRow = Row
  469.  
  470.     IsValidFieldType = True
  471. End Function
  472.  
  473. Function IsValidFieldTypeChar (KeyAscii As Integer)
  474. '
  475. ' This function checks if KeyAscii is a valid field type character.
  476. ' A valid field type character must be "C", "N", "F", "D", "L", or "M"
  477. ' only.  (Stands for Character, Numeric, Float, Date, Logical and Memo
  478. ' types, respectively.)
  479. '
  480.     IsValidFieldTypeChar = True
  481.  
  482.     If KeyAscii <> C And KeyAscii <> N And KeyAscii <> F Then
  483.         If KeyAscii <> D And KeyAscii <> L And KeyAscii <> M Then
  484.             IsValidFieldTypeChar = FLASE
  485.         End If
  486.     End If
  487. End Function
  488.  
  489. Function IsValidFieldWidth (Row As Integer, Value As String) As Integer
  490. '
  491. ' This function checks if the FieldWidth value in the current cell is
  492. ' valid.
  493. '
  494.  
  495.     Dim w As Integer
  496.     Dim D As Integer
  497.     Dim t As Integer
  498.  
  499.     '
  500.     ' Check if field is empty
  501.     '
  502.     If Value = "" Then
  503.         MsgBox "Field width no defined.", 48, "Error"
  504.         IsValidFieldWidth = False
  505.         Exit Function
  506.     End If
  507.  
  508.     t = Asc(FieldType(Row))
  509.     w = Val(Value)
  510.  
  511.     Select Case t
  512.         Case C
  513.             '
  514.             ' Character field must be between 1 to 254 characters
  515.             '
  516.             If w = 0 Or w > 254 Then
  517.                 MsgBox "Character field width must be between 1 and 254.", 48, "Error"
  518.                 IsValidFieldWidth = False
  519.                 Exit Function
  520.             End If
  521.  
  522.         Case N, F
  523.             '
  524.             ' Numeric fields must be between 1 to 20 digits
  525.             '
  526.             If w = 0 Or w > 20 Then
  527.                 MsgBox "Numeric field width must be between 1 and 20.", 48, "Error"
  528.                 IsValidFieldWidth = False
  529.                 Exit Function
  530.             End If
  531.  
  532.             '
  533.             ' There must be enough room for decimal digits
  534.             '
  535.             D = Val(FieldDec(Row))
  536.  
  537.             If D <> 0 And (w - D) < 2 Then
  538.                 MsgBox "(Width - Dec) must be greater than 1.", 48, "Error"
  539.                 IsValidFieldWidth = False
  540.                 Exit Function
  541.             End If
  542.  
  543.         Case Else               ' DLM
  544.             '
  545.             ' No checking needed fo Date, Logical and Memo fields
  546.             '
  547.             IsValidFieldWidth = True
  548.             Exit Function
  549.  
  550.     End Select
  551.  
  552.     ' Eliminate leading 0
  553.     Value = Mid$(Str$(w), 2)
  554.  
  555.     IsValidFieldWidth = True
  556. End Function
  557.  
  558. Sub ToUpper (KeyAscii As Integer)
  559.     If KeyAscii >= sA And KeyAscii <= sZ Then
  560.         KeyAscii = KeyAscii + A_a
  561.     End If
  562. End Sub
  563.  
  564. Sub xFieldTable_Append ()
  565. '
  566. ' The _Append event is activated when the user press the down arrow key
  567. ' at the last row of the table.  This Sub then adds a new row to the field
  568. ' table.
  569. '
  570.     '
  571.     ' Do nothing if not a last row in the table
  572.     '
  573.     If Form1.FieldTable.RowIndex <> Form1.FieldTable.Rows Then
  574.         Exit Sub
  575.     End If
  576.  
  577.     '
  578.     ' Cannot have more than 255 rows
  579.     '
  580.     If Form1.FieldTable.Rows = 255 Then
  581.         Exit Sub
  582.     End If
  583.  
  584.     '
  585.     ' Add a new row and poistion to the FieldName column
  586.     '
  587.     Form1.FieldTable.Rows = Form1.FieldTable.Rows + 1
  588.     Form1.FieldTable.RowIndex = Form1.FieldTable.Rows
  589.     Form1.FieldTable.ColumnIndex = 2
  590. End Sub
  591.  
  592. Sub xFieldTable_ColumnChange ()
  593. '
  594. ' This Sub displays a different help string when the user is at different
  595. ' table column.  This is to make the program user friendly by assisting
  596. ' the user during the data entry process.
  597. '
  598.     Dim t As String
  599.  
  600.     '
  601.     ' If at table heading, prompt should be empty
  602.     '
  603.     If Form1.FieldTable.RowIndex = 0 Then
  604.         Form1.ColumnPrompt.Caption = ""
  605.         Exit Sub
  606.     End If
  607.  
  608.     t = FieldType(Form1.FieldTable.RowIndex)
  609.  
  610.     Select Case Form1.FieldTable.ColumnIndex
  611.         Case NAME_COL           ' FieldName column
  612.             Form1.ColumnPrompt.Caption = "Enter field name"
  613.  
  614.         Case TYPE_COL           ' FieldType column
  615.             Form1.ColumnPrompt.Caption = "C=Character, N=Numeric, F=Float" + Chr$(13) + "D=Date, L=Logical, M=Memo"
  616.  
  617.         Case WIDTH_COL          ' FieldWidth column
  618.             If t = "D" Or t = "L" Or t = "M" Then
  619.                 Form1.ColumnPrompt.Caption = "Cannot Change Field Width"
  620.             Else
  621.                 Form1.ColumnPrompt.Caption = "Enter Field Width"
  622.             End If
  623.  
  624.         Case DEC_COL            ' FieldDec column
  625.             If t = "C" Or t = "D" Or t = "L" Or t = "M" Then
  626.                 Form1.ColumnPrompt.Caption = "Cannot Change Decimal Width"
  627.             Else
  628.                 Form1.ColumnPrompt.Caption = "Enter Field Decimal Width"
  629.             End If
  630.  
  631.         Case INDEX_COL          ' FieldIndex column
  632.             If t = "L" Or t = "M" Then
  633.                 Form1.ColumnPrompt.Caption = "Cannot be indexed"
  634.             Else
  635.                 Form1.ColumnPrompt.Caption = "Y=Indexed, N=Not Indexed"
  636.             End If
  637.     End Select
  638. End Sub
  639.  
  640. Sub xFieldTable_Fetch (Row As Long, Col As Integer, Value As String)
  641. '
  642. ' Whenever the grid needs to display data, it will ask the programmer
  643. ' for the appropriate data to display via the _Fetch event.  The
  644. ' programmer cannot make any assumption as to when the grid will ask
  645. ' for data.  Also, the programmer cannot make the assumption that if
  646. ' data for a certain row/col is asked once, the grid will not ask for
  647. ' it again.  In short, it's the programmer's responsibility to store
  648. ' and maintain the data, and it's the grid's responsibility to display
  649. ' them properly.
  650. ' This technique will free the programmer from worrying when and how to
  651. ' display data in the grid. For example, if the user drags a window to
  652. ' (partially) covers the gird and later remove the window, the grid will
  653. ' be responsible to know about it and refresh the data in the grid.  The
  654. ' programmer needs only to maintain the data.  (In this case, data is
  655. ' stored in 6 arrays, one array per column.)
  656. '
  657.     Select Case Col
  658.         Case NO_COL
  659.             Value = FieldNo(Row)
  660.         Case NAME_COL
  661.             Value = FieldName(Row)
  662.         Case TYPE_COL
  663.             Value = FieldType(Row)
  664.         Case WIDTH_COL
  665.             Value = FieldWidth(Row)
  666.         Case DEC_COL
  667.             Value = FieldDec(Row)
  668.         Case INDEX_COL
  669.             Value = FieldIndex(Row)
  670.     End Select
  671. End Sub
  672.  
  673. Sub xFieldTable_KeyPress (KeyAscii As Integer)
  674. '
  675. ' This routine illustrates a few techniques to check, modify, and retrict
  676. ' user input.  The goal is to assist user to enter valid values thus making
  677. ' the program more user friendly.
  678. '
  679.     Dim isbs As Integer
  680.  
  681.     ' Convert all key to upper case.
  682.     ToUpper KeyAscii
  683.  
  684.     r = Form1.FieldTable.RowIndex
  685.  
  686.     '
  687.     ' No checking needed if at table heading
  688.     '
  689.     If r = 0 Then
  690.         Exit Sub
  691.     End If
  692.  
  693.     ' Check if key is BackSpace
  694.     If KeyAscii = BackSpace Then
  695.         isbs = True
  696.     Else
  697.         isbs = False
  698.     End If
  699.  
  700.     Select Case Form1.FieldTable.ColumnIndex
  701.         Case NAME_COL           ' FieldName column
  702.             '
  703.             ' Do not allow user input if it is not BackSpace or a valid
  704.             ' field name character
  705.             '
  706.             If isbs = False And IsValidFieldNameChar(KeyAscii) = False Then
  707.                 KeyAscii = 0    ' Cancel user input
  708.                 Exit Sub
  709.             End If
  710.  
  711.         Case TYPE_COL           ' FieldType column
  712.             If FieldName(r) = "" Then
  713.                 '
  714.                 ' Do not allow user input if field name is not yet defined
  715.                 '
  716.                 KeyAscii = 0
  717.                 Exit Sub
  718.             ElseIf isbs = False And IsValidFieldTypeChar(KeyAscii) = False Then
  719.                 '
  720.                 ' Do not allow user input if it is not BackSpace or a valid
  721.                 ' field type
  722.                 '
  723.                 KeyAscii = 0
  724.                 Exit Sub
  725.             End If
  726.  
  727.         Case WIDTH_COL          ' FieldWidth column
  728.             If FieldType(r) = "" Then
  729.                 '
  730.                 ' Do not allow user input if field type is not yet defined
  731.                 '
  732.                 KeyAscii = 0
  733.                 Exit Sub
  734.             ElseIf IsDLM(Asc(FieldType(r))) = True Then
  735.                 '
  736.                 ' No input allowed if FieldType is "D (Date)", "L (Logical)"
  737.                 ' or "M (Memo)".  FieldWidth for this fields are fixed and
  738.                 ' are defined in the _Validate event.
  739.                 '
  740.                 KeyAscii = 0
  741.                 Exit Sub
  742.             ElseIf isbs = False And IsDigit(KeyAscii) = False Then
  743.                 '
  744.                 ' Only BackSpace and digits are allowed.
  745.                 '
  746.                 KeyAscii = 0
  747.                 Exit Sub
  748.             End If
  749.  
  750.         Case DEC_COL            ' FieldDec column
  751.             If FieldWidth(r) = "" Then
  752.                 '
  753.                 ' Do not allow user input if field width is not yet defined
  754.                 '
  755.                 KeyAscii = 0
  756.                 Exit Sub
  757.             ElseIf IsNF(Asc(FieldType(r))) = False Then
  758.                 '
  759.                 ' No input allowed if field type is not "N (Numeric)" or
  760.                 ' "F (Float)"  (Only numeric fields can have a non-zero
  761.                 ' field decimal value.)
  762.                 '
  763.                 KeyAscii = 0
  764.                 Exit Sub
  765.             ElseIf isbs = False And IsDigit(KeyAscii) = False Then
  766.                 '
  767.                 ' Only BackSpace and digits are allowed.
  768.                 '
  769.                 KeyAscii = 0
  770.                 Exit Sub
  771.             End If
  772.  
  773.         Case INDEX_COL          ' FieldIndex column
  774.             If FieldWidth(r) = "" Then
  775.                 '
  776.                 ' Do not allow user input if field width is not yet defined
  777.                 '
  778.                 KeyAscii = 0
  779.                 Exit Sub
  780.             ElseIf IsLM(Asc(FieldType(r))) = True Then
  781.                 '
  782.                 ' No input allowed if field type is not "L (Logical)" or
  783.                 ' "M (Memo)"  (Index is not allowed for Logical and Memo
  784.                 ' fields.
  785.                 '
  786.                 KeyAscii = 0
  787.                 Exit Sub
  788.             ElseIf isbs = False And KeyAscii <> N And KeyAscii <> Y Then
  789.                 '
  790.                 ' Only BackSpace, "N (No)" or "Y (Yes)" are allowed.
  791.                 KeyAscii = 0
  792.                 Exit Sub
  793.             End If
  794.  
  795.     End Select
  796.  
  797. End Sub
  798.  
  799. Sub xFieldTable_Update (Row As Long, Col As Integer, Value As String)
  800. '
  801. ' After the user has finished editing data in a cell and the data has
  802. ' been validated by the programmer via the _Validate event, the grid
  803. ' will then notify the programmer the cell now has a new value via
  804. ' this _Update event.  In this event, the programmer uses the value
  805. ' supplied by the grid to update the data he/she is reponsible for
  806. ' storing and maintaining.  In this case, the field table arrays are
  807. ' updated by the new value supplied by the gird.  Note that we don't
  808. ' need to update the FieldNo array because the FieldNo column is
  809. ' readonly.
  810. '
  811.     Select Case Col
  812.         Case NAME_COL
  813.             FieldName(Row) = Value
  814.         Case TYPE_COL
  815.             FieldType(Row) = Value
  816.         Case WIDTH_COL
  817.             FieldWidth(Row) = Value
  818.         Case DEC_COL
  819.             FieldDec(Row) = Value
  820.         Case INDEX_COL
  821.             FieldIndex(Row) = Value
  822.     End Select
  823. End Sub
  824.  
  825. Sub xFieldTable_Validate (Row As Long, Col As Integer, Value As String, Cancel As Integer)
  826. '
  827. ' Before moving to another grid cell, this routine let the programmer
  828. ' examine the value in the current cell.  If the value entered is invalid,
  829. ' programmer can display a message, then set Cancel to True to prohibit
  830. ' the user moving on to another cell.  The _Validate and _KeyPress events
  831. ' together provide a very easy way for programmers to check, restrict and
  832. ' validate user inputs in TrueGrid.
  833. '
  834.     Dim r As Integer
  835.  
  836.     '
  837.     ' If empty row, no validation needed
  838.     '
  839.     If Value = "" And FieldName(Row) = "" Then
  840.         Exit Sub
  841.     End If
  842.  
  843.     r = CInt(Row)
  844.     
  845.     Select Case Col
  846.         Case NAME_COL          ' FieldName
  847.             '
  848.             ' Check if FieldName is valid
  849.             '
  850.             If IsValidFieldName(r, Value) = False Then
  851.                 Cancel = True
  852.             End If
  853.  
  854.         Case TYPE_COL          ' FieldType
  855.             '
  856.             ' Check if FieldType is valid
  857.             '
  858.             If IsValidFieldType(r, Value) = False Then
  859.                 Cancel = True
  860.             End If
  861.  
  862.         Case WIDTH_COL          ' FieldWidth
  863.             '
  864.             ' Check if FieldWidth is valid
  865.             '
  866.             If IsValidFieldWidth(r, Value) = False Then
  867.                 Cancel = True
  868.             End If
  869.  
  870.         Case DEC_COL          ' FieldDec
  871.             '
  872.             ' Check if FieldDec is valid
  873.             '
  874.             If IsValidFieldDec(r, Value) = False Then
  875.                 Cancel = True
  876.             End If
  877.  
  878.         Case INDEX_COL          ' FieldIndex
  879.             '
  880.             ' If field is empty, default it to "N"
  881.             '
  882.             If Value = "" Then
  883.                 Value = "N"
  884.             End If
  885.     End Select
  886. End Sub
  887.  
  888. Sub xForm1_Load ()
  889. '
  890. ' During Form_Load, the ColumnPrompt (Label) Caption, the field
  891. ' structure array and the table properties are initialized.
  892. '
  893.     Form1.ColumnPrompt.Caption = ""
  894.     InitFieldTable
  895. End Sub
  896.  
  897.