Back to Contents


Array Input

Summary:

See also: Arrays, Records, Result Sets, Programs, Windows, Forms, Display Array


Basics

The INPUT ARRAY instruction associates a program array of records with a screen-array defined in a form so that the user can update the list of records. The INPUT ARRAY statement activates the current form (the form that was most recently displayed or the form in the current window):

During the INPUT ARRAY execution, the user can edit or delete existing rows, insert new rows, and move inside the list of records. The user can insert new rows with the insert key, which is by default F1, or delete existing rows with the delete key, which is by default F2. The program controls the behavior of the instruction with control blocks:

To terminate the INPUT ARRAY execution, the user can validate (or cancel) the dialog to commit (or invalidate) the modifications made in the list of records:

When the statement completes execution, the form is de-activated. After the user terminates the input (for example, with the Accept key), the program must test the INT_FLAG variable to check if the dialog was validated (or canceled) and then can use the INSERT, DELETE, or UPDATE SQL statements to modify the appropriate database tables. The database can also be updated during the execution of the INPUT ARRAY statement.


INPUT ARRAY

Purpose:

The INPUT ARRAY supports data entry by users into a screen array and stores the entered data in an array of records.

Syntax:

INPUT ARRAY array
  [ WITHOUT DEFAULTS ]
  FROM screen-array.*  
 
[ HELP help-number ]
  [ ATTRIBUTE ( { display-attribute | control-attribute } [,...] ) ]
[

  { BEFORE INPUT
       dialog-statement-1
       [...]
  | AFTER INPUT
       dialog-statement-1
       [...]
  | AFTER DELETE
       dialog-statement-1
       [...]
  | BEFORE ROW
       dialog-statement-1
       [...]
  | AFTER ROW
       dialog-statement-1
       [...]
  | BEFORE FIELD field-list
       dialog-statement-1
       [...]
  | AFTER FIELD field-list
       dialog-statement-1
       [...]
  | ON ROW CHANGE
       dialog-statement-1
       [...]
  | ON CHANGE field-list
       dialog-statement-1
       [...]
  | ON IDLE idle-seconds
       dialog-statement-1
       [...]
  | ON ACTION action-name
       dialog-statement-1
       [...]
  | ON KEY ( key-name [,...] )
       dialog-statement-1
       [...]
  | BEFORE INSERT
       dialog-statement-2
       [...]
  | AFTER INSERT
       dialog-statement-2
       [...]
  | BEFORE DELETE
       dialog-statement-3
       [...]
  }
  [...]
END INPUT ]

where dialog-statement-1 is one of:

{ statement
| ACCEPT INPUT
| CONTINUE INPUT
| EXIT INPUT
| NEXT FIELD { CURRENT | NEXT | PREVIOUS | field-name }
}

and dialog-statement-2 is one of:

{ dialog-statement-1
| CANCEL INSERT
}

and dialog-statement-3 is one of:

{ dialog-statement-1
| CANCEL DELETE
}

where field-list is:

{ field-name
| table-name.*
| table-name.field-name
| screen-array[line].*
| screen-array[line].field-name
| screen-record.*
| screen-record.field-name
} [,...]

Notes:

  1. array is the array of records that will be filled by the INPUT ARRAY statement.
  2. help-number is an integer that allows you to associate a help message number with the instruction.
  3. field-name is the identifier of a field of the current form.
  4. table-name is the identifier of a database table of the current form.
  5. screen-record is the identifier of a screen record of the current form.
  6. screen-array is the screen array that will be used in the form.
  7. action-name identifies an action that can be executed by the user.
  8. field-name identifies a field used in the dialog instruction.
  9. idle-seconds is an integer expression that defines a number of seconds.
  10. key-name is a hot-key identifier (like F11 or Control-z).
  11. statement is any instruction supported by the language.

The following table shows the display-attributes supported by the INPUT ARRAY statement:

Attribute Description
BLACK, BLUE, CYAN, GREEN, MAGENTA, RED, WHITE, YELLOW
Console Only!
The color of the displayed data.
BOLD, DIM, INVISIBLE, NORMAL
Console Only!
The font attribute of the displayed data.
REVERSE, BLINK, UNDERLINE
Console Only!
The video attribute of the displayed data.

The following table shows the control-attributes supported by the INPUT ARRAY statement:

Attribute Description
APPEND ROW [ =bool] Defines if the user can append new rows at the end of the list. The bool parameter can be an integer literal or a program variable that evaluates to TRUE or FALSE.
COUNT = row-count Defines the number of data rows in the static array. The row-count can be an integer literal or a program variable. This is the equivalent of the SET_COUNT() built-in function.
DELETE ROW [ =bool] Defines if the user can delete rows. The bool parameter can be an integer literal or a program variable that evaluates to TRUE or FALSE.
FIELD ORDER FORM Indicates that the tabbing order of fields is defined by the TABINDEX attribute of form fields. When user moves columns, the front-end updates the tab indexes so that the tabbing order will follow the visual order.
HELP = help-number Defines the help number when help is invoked by the user, where help-number is an integer literal or a program variable.
INSERT ROW [ =bool] Defines if the user can insert new rows inside the list. The bool parameter can be an integer literal or a program variable that evaluates to TRUE or FALSE.
KEEP CURRENT ROW [=bool] Keeps current row highlighted after execution of the instruction.
MAXCOUNT = row-count Defines the maximum number of data rows that can be entered in the program array, where row-count can be an integer literal or a program variable.
UNBUFFERED [ =bool] Indicates that the dialog must be sensitive to program variable changes. The bool parameter can be an integer literal or a program variable.
WITHOUT DEFAULTS [=bool] Indicates if the data rows must be filled (FALSE) or not (TRUE) with the column default values defined in the form specification file or the database schema files. The bool parameter can be an integer literal or a program variable that evaluates to TRUE or FALSE.
CANCEL = bool Indicates if the default action 'cancel' should be added to the dialog. If not specified, the action is registered.
ACCEPT = bool Indicates if the default action 'accept' should be added to the dialog. If not specified, the action is registered.

Usage:

When the runtime system encounters an INPUT ARRAY statement, it does the following::

  1. Displays the program array values in the screen array fields.
  2. Selects the first screen record in the list.
  3. Waits for the user to initiate an action on the list (input, scrolling, validation or cancellation).

The INPUT ARRAY statement does not terminate until the user validates or cancels the dialog.

Warnings:

  1. You can only use the CANCEL INSERT keyword in the BEFORE INSERT or AFTER INSERT blocks.
  2. You can only use the CANCEL DELETE keyword in the BEFORE DELETE block.

Tips:

  1. If you want to input data from a reduced set of columns, you must define a second screen array, containing the limited list of form fields, in the form file. You can then use the second screen array in an INPUT ARRAY a FROM sa.* instruction.

Usage

Programming Steps 

The following steps describe how to use the INPUT ARRAY statement:

  1. Create a form specification file containing a screen array. The screen array identifies the presentation elements to be used by the runtime system to display the rows.
  2. Make sure that the program controls interruption handling with DEFER INTERRUPT, to manage the validation/cancellation of the interactive dialog.
  3. Define an array of records with the DEFINE instruction. The members of the program array must correspond to the elements of the screen array, by number and data types. 
  4. Open and display the form, using a OPEN WINDOW with the WITH FORM clause.
  5. If needed, fill the program array with data, for example with a result set cursor, counting the number of program records being filled with retrieved data.
  6. Use the INPUT ARRAY statement to handle data input. When using a static array, specifying the number of rows with the COUNT attribute in the ATTRIBUTE clause.
  7. Inside the INPUT ARRAY statement, control the behavior of the instruction with BEFORE INPUT, BEFORE INSERT, BEFORE DELETE, BEFORE ROW, BEFORE FIELD, AFTER INSERT, AFTER DELETE, AFTER FIELD, AFTER ROW, AFTER INPUT and ON KEY blocks.
  8. After the INPUT ARRAY statement, test the INT_FLAG pre-defined variable to check if the interactive dialog was canceled ( INT_FLAG = TRUE ) or validated ( INT_FLAG = FALSE ).
  9. Get the new number of rows with the ARR_COUNT() built-in function.
  10. If needed, get the current row with the ARR_CURR() built-in function.

Variable Binding

The INPUT ARRAY statement binds the screen array fields to the member records of the program array. The number of variables in each record of the program array must be the same as the number of fields in each screen record (that is, in a single row of the screen array). Each mapped variable must have the same data type or a compatible data type as the corresponding field.

In the old interface mode, the size of the screen array (from the form specification file) determines the number of program records that the runtime system displays at one time on the screen. When using the standard graphical mode, the number of lines in the screen array defines the default number of lines that are displayed, but the user can resize the list view to see more records.

When using a static array, the initial number of rows is defined by the COUNT attribute and the size of the array determines how many rows can be inserted. When using a dynamic array, the initial number of rows is defined by the number of elements in the dynamic array (the COUNT attribute is ignored). The size of the input array is unlimited. In both cases, the maximum number of rows the user can enter can be defined with the MAXCOUNT attribute.

The record member variables of the program array are bound with the fields in the member records of a screen array, so the INPUT ARRAY instruction can manipulate values that the user enters in the screen array.

The FROM clause binds the screen records in the screen array to the program records of the program array. The form can include other fields that are not part of the specified screen array, but the number of member variables in each record of the program array must equal the number of fields in each row of the screen array. Each variable must be of the same (or a compatible) data type as the corresponding screen field. When the user enters data, the runtime system checks the entered value against the data type of the variable, not the data type of the screen field.

The variables of the record array are the interface to display data or to get the user input through the INPUT ARRAY instruction. Always use the variables if you want to change some field values programmatically. When using the UNBUFFERED attribute, the instruction is sensitive to program variable changes. If you need to display new data during the INPUT ARRAY execution, use the UNBUFFERED attribute and assign the values to the program array row; the runtime system will automatically display the values to the screen:

01 INPUT ARRAY p_items FROM s_items.* ATTRIBUTES(UNBUFFERED)
02    ON CHANGE code
03       IF p_items[arr_curr()].code = "A34" THEN
04          LET p_items[arr_curr()].desc = "Item A34"
05       END IF
06 END INPUT

The member variables of the records in a program array can be of any data type. If a variable is declared LIKE a SERIAL column, however, the runtime system does not allow the screen cursor to stop in the field. (Values in SERIAL columns are automatically generated by the database server, not by the runtime system.)

The default order in which the focus moves from field to field in the screen array is determined by the declared order of the corresponding member variables, in the array of the record definition. The program options instruction can also change the behavior of the INPUT ARRAY instruction, with the INPUT WRAP or FIELD ORDER options.

When the INPUT ARRAY instruction executes, it displays any column default values in the screen fields, unless you specify the WITHOUT DEFAULTS keywords. The column default values are specified in the form specification file with the DEFAULT attribute or in the database schema files.

Instruction Configuration

The ATTRIBUTE clause specifications override all default attributes and temporarily override any display attributes that the OPTIONS or the OPEN WINDOW statement specified for these fields. While the INPUT ARRAY statement is executing, the runtime system ignores the INVISIBLE attribute.

Using the FIELD ORDER FORM attribute: By default, the tabbing order is defined by the variable binding list in the instruction description. When the user moves columns around in a TABLE, the tabbing order may not correspond to the visual order of the columns. In this case you may want to freeze the table columns with the UNMOVABLECOLUMNS attribute. On the other hand, you can control the tabbing order by using the FIELD ORDER FORM attribute: When this attribute is used, the tabbing order is defined by the TABINDEX attribute of the form fields. If the form container is a TABLE, the front-end resets the tab indexes when the user moves columns around. This way, the visual column order always corresponds to the input tabbing order.

The HELP clause specifies the number of a help message to display if the user invokes the help while the focus is in any field used by the instruction. The predefined 'help' action is automatically created by the runtime system. You can bind action views to the 'help' action.

The COUNT attribute defines the number of valid rows in the program array to be  displayed as default rows. If you do not use the COUNT attribute, the runtime system cannot determine how much data to display, so the screen array remains empty. You can also use the SET_COUNT() built-in function, but it is supported for backward compatibility only. If you specify the COUNT attribute, the WITHOUT DEFAULTS option is not required because it is implicit.

The MAXCOUNT attribute defines the maximum number of rows that can be inserted in the program array. This attribute allows you to give an upper limit very easily. If MAXCOUNT is specified as zero, or greater than the size of the declared static array, the original array size is used as upper limit. When using a dynamic array, the user can enter an infinite number of rows, except if the MAXCOUNT attribute is set.

Using the INSERT ROW attribute, you can define with a Boolean value whether the user is allowed to insert new rows in the middle of the list. However, even if INSERT ROW is FALSE, the user can still append rows at the end of the list. Use the APPEND ROW attribute to disallow the user from appending rows.

Using the DELETE ROW attribute, you can define with a Boolean value whether the user is allowed to delete rows (TRUE) or not (FALSE).

Depending on the list container used in the form, the current row may be highlighted during the execution of the dialog, and cleared when the instruction ends. You can change this default behavior by using the KEEP CURRENT ROW attribute, to force the runtime system to keep the current row highlighted. 

Default Actions

When an INPUT ARRAY instruction executes, the runtime system creates a set of default actions. See the control block execution order to understand what control blocks are executed when a specific action is fired.

The following table lists the default actions created for this dialog:

Default action Control Block execution order
accept Validates the INPUT ARRAY dialog (validates fields)
Creation can be avoided with ACCEPT attribute.
cancel Cancels the INPUT ARRAY dialog (no validation, int_flag is set)
Creation can be avoided with CANCEL attribute.
close By default, cancels the INPUT ARRAY dialog (no validation, int_flag is set)
Default action view is hidden. See Windows closed by the user.
insert Inserts a new row before current row.
Creation can be avoided with INSERT ROW attribute.
append Appends a new row at the end of the list.
Creation can be avoided with APPEND ROW attribute.
delete Deletes the current row.
Creation can be avoided with DELETE ROW attribute.
help Shows the help topic defined by the HELP clause.
Only created when a HELP clause is defined.
nextrow Moves to the next row in a list displayed in one row of fields.
Only created if INPUT ARRAY used with a screen record having only one row.
prevrow Moves to the previous row in a list displayed in one row of fields.
Only created if INPUT ARRAY used with a screen record having only one row.

The accept and cancel default actions can be avoided with the ACCEPT and CANCEL dialog control attributes:

01  DISPLAY ARRAY arr TO sr.* ATTRIBUTES( CANCEL=FALSE, ... )
02       ...

Control Blocks

The BEFORE INPUT block is executed one time, before the runtime system gives control to the user. You can implement initialization in this block.

The AFTER INPUT block is executed one time, after the user has validated or canceled the dialog, and before the runtime system executes the instruction that appears just after the INPUT ARRAY block. You typically implement dialog finalization in this block. The AFTER INPUT block is not executed if EXIT INPUT executes.

The BEFORE ROW block is executed each time the user moves to another row, after the destination row is made the current one. When called in this block, the ARR_CURR() function returns the index of the current row.

An ON ROW CHANGE block is executed when the user moves to another row after modifications have been done in the current row. You can, for example, code database modifications (UPDATE) in this block. This block is executed before the AFTER ROW block if defined. When called in this block, the ARR_CURR() function returns the index of the current row where values have been changed.

01 INPUT ARRAY p_items FROM s_items.*
02    ON ROW CHANGE
03       UPDATE items SET
04               items.code = items[arr_curr()].code,
05               items.description = items[arr_curr()].description,
06               items.price = items[arr_curr()].price,
07               items.updatedate  = TODAY
08              WHERE items.num = items[arr_curr()].num
09 END INPUT

The AFTER ROW block is executed each time the user moves to another row,  before the current row is left. When called in this block, the ARR_CURR() function returns the index of the current row.

A BEFORE FIELD block is executed each time the cursor enters into the specified field, when moving the focus from field to field in the same row, or when moving to another row.

An ON CHANGE block is executed when the value changes in the specified field for RadioGroup, ComboBox and CheckBox views, when the cursor leaves the specified field and the value was changed by the user since the field got the focus. If both an ON CHANGE block and AFTER FIELD block are defined for a field, the ON CHANGE block is executed before the AFTER FIELD block.

An AFTER FIELD block is executed each time the cursor leaves the specified field, when moving the focus from field to field in the same row, or when moving to another row.

The BEFORE INSERT block is executed each time the user inserts a new row, before the new row is created and made the current one. You can cancel the operation with the CANCEL INSERT instruction.

The AFTER INSERT block is executed each time the user inserts a new row, after the new row is created. In this block, you typically initialize some fields with dynamic default values.

Warning: When the you append a new row at the end of the list, then you move to another row or you validate the dialog, the AFTER INSERT block is only executed if at least one field was edited. If not data entry is detected, the dialog automatically removes the new appended row and thus does not trigger the AFTER INSERT block.

The BEFORE DELETE block is executed each time the user deletes a row, before the row is removed from the list. You can cancel the operation with the CANCEL DELETE instruction. For example, you may cancel the row deletion if a database error occurs when you try to delete the row from the table:

01 ...
02    BEFORE DELETE
03       WHENEVER ERROR CONTINUE
04       DELETE FROM customer WHERE custno = arr[arr_curr()].custno
05       WHENEVER ERROR STOP
06       IF SQLCA.SQLCODE<>0 VALUES
07          ERROR SQLERRMESSAGE
08          CANCEL DELETE
09       END IF
10 ...

The AFTER DELETE block is executed each time the user deletes a row, after the row has been deleted from the list.

Control Block Execution Order

The following table shows the order in which the runtime system executes the control blocks in the INPUT ARRAY instruction, according to the user action:

User action Control Block execution order
Entering the dialog
  1. BEFORE INPUT
  2. BEFORE ROW
  3. BEFORE FIELD
Moving to a different row
  1. AFTER FIELD (for field A in the current row)
  2. [AFTER INSERT] (if a new row was created)
  3. [ON ROW CHANGE] (if values have changed in current row)
  4. AFTER ROW (for the current)
  5. BEFORE ROW (the new row)
  6. BEFORE FIELD (for field B in the new row)
Moving from field A to field B in the same row
  1. [ON CHANGE] (for field A, if value has changed)
  2. AFTER FIELD (for field A)
  3. BEFORE FIELD (for field B)
Deleting a row
  1. BEFORE DELETE (the row to be deleted)
  2. AFTER DELETE (the deleted row)
  3. AFTER ROW (the deleted row)
  4. BEFORE ROW (the new current row)
  5. BEFORE FIELD
Inserting a new row between rows
  1. AFTER FIELD
  2. [AFTER INSERT] (if a new row was created)
  3. [ON ROW CHANGE] (if values have changed)
  4. AFTER ROW (the previous row)
  5. BEFORE INSERT
  6. BEFORE FIELD
Appending a new row at the end
  1. AFTER FIELD
  2. [AFTER INSERT] (if a new row was created)
  3. [ON ROW CHANGE] (if values have changed)
  4. AFTER ROW (the previous row)
  5. BEFORE ROW (the new current row)
  6. BEFORE INSERT
  7. BEFORE FIELD
Validating the dialog
  1. [ON CHANGE]
  2. AFTER FIELD
  3. [AFTER INSERT] (if a new row was created)
  4. [ON ROW CHANGE] (if values have changed)
  5. AFTER ROW
  6. AFTER INPUT
Canceling the dialog
  1. AFTER ROW
  2. AFTER INPUT

Interaction Blocks

The ON IDLE idle-seconds clause defines a set of instructions that must be executed after idle-seconds of inactivity. For example, this can be used to quit the dialog after the user has not interacted with the program for a specified period of time. The parameter idle-seconds must be an integer expression. If it evaluates to zero, the timeout is disabled. 

01 ...
02    ON IDLE 10
03       IF ask_question("Do you want to leave the dialog?") THEN
04          EXIT INPUT
05       END IF
06 ...

You can use ON ACTION blocks to execute a sequence of instructions when the user raises a specific action. This is the preferred solution compared to ON KEY blocks, because ON ACTION blocks use abstract names to control user interaction.

01 ...
02    ON ACTION zoom
03       CALL zoom_customers() RETURNING st, cust_id, cust_name
04       ...

For backward compatibility, you can use ON KEY blocks to execute a sequence of instructions when the user presses a specific key. The following key names are accepted by the compiler:

Key Name Description
ACCEPT The validation key.
INTERRUPT The interruption key.
ESC or ESCAPE The ESC key (not recommended, use ACCEPT instead).
TAB The TAB key (not recommended).
Control-char A control key where char can be any character except A, D, H, I, J, K, L, M, R, or X.
F1 through F255 A function key.
DELETE The key used to delete a new row in an array.
INSERT The key used to insert a new row in an array.
HELP The help key.
LEFT The left arrow key.
RIGHT The right arrow key.
DOWN The down arrow key.
UP The up arrow key.
PREVIOUS or PREVPAGE  The previous page key.
NEXT or NEXTPAGE  The next page key.

Control Instructions

The CONTINUE INPUT instruction continues the execution of the INPUT ARRAY instruction, skipping all statements appearing after this instruction. For example, use this instruction to give control back to the interactive dialog after testing for a special situation where the user must continue to input the list of records.

You can use the EXIT INPUT to terminate the INPUT ARRAY instruction and resume the program execution at the instruction following the INPUT ARRAY block.

The ACCEPT INPUT instruction validates the INPUT instruction and exits the INPUT instruction if no error is raised. The AFTER FIELD, ON CHANGE, etc. control blocks will be executed. Statements after the ACCEPT INPUT will not be executed: the statement acts like a CONTINUE {INPUT|CONSTRUCT}.

Insertion can be canceled, by using the CANCEL INSERT instruction, but this instruction is only allowed in the BEFORE INSERT or AFTER INSERT blocks. Using this instruction in a different place will generate a compilation error. You can for example cancel a row insertion if a database error occurs when you try to insert the row in a table, in the AFTER INSERT block:

01 ...
02    AFTER INSERT
03       WHENEVER ERROR CONTINUE
04       INSERT INTO customer VALUES ( arr[arr_curr()].* )
05       WHENEVER ERROR STOP
06       IF SQLCA.SQLCODE<>0 VALUES
07          ERROR SQLERRMESSAGE
08          CANCEL INSERT
09       END IF
10 ...

Deletion can be canceled, by using the CANCEL DELETE instruction, but this instruction is only allowed in the BEFORE DELETE block. Using this instruction in a different place will generate a compilation error.

The NEXT FIELD field-name instruction gives the focus to the specified field. You typically use this instruction to control field input dynamically, in BEFORE FIELD or AFTER FIELD blocks. Abstract field identification is supported with the CURRENT, NEXT and PREVIOUS keywords. These keywords represent respectively the current, next and previous fields, corresponding to variables as defined in the input binding list (with the FROM or BY NAME clause).

For backward compatibility, the CLEAR field-list instruction is provided  to clear a specific field or all fields in a line of the screen array. You can specify the screen array as described in the following table:

CLEAR instruction Result
CLEAR field-name Clears the specified field in the current line of the screen array.
CLEAR screen-array.* Clears all fields in the current line of the screen array.
CLEAR screen-array[n].* Clears all fields in  line n of the screen array.
CLEAR screen-array[n].field-name Clears the specified field in line n of the screen array.

Warning: When using the UNBUFFERED attribute, it is not recommended that you use the CLEAR instruction; always use program variables to set field values to NULL.

Control Class

Inside the dialog instruction, the predefined keyword DIALOG represents the current dialog object. It can be used to execute methods provided in the dialog built-in class.

For example, you can enable or disable an action with the setActionAction() dialog method, or you can also hide and show the default action view with the setActionHidden() method: 

01 ...
02    BEFORE INPUT
03       CALL DIALOG.setActionActive("zoom",FALSE)
04    AFTER FIELD field1
05       CALL DIALOG.setActionHidden("zoom",1)
06 ...

The method setFieldActive() can be used to enable or disable a field during the dialog. This instruction takes an integer expression as argument.

01 ...
02    ON CHANGE custname
03       CALL DIALOG.setFieldActive( "custaddr", (rec.custname IS NOT NULL) )
04 ...

Control Functions

The language provides several built-in functions and operators to use in an INPUT ARRAY statement. You can use the following built-in functions to keep track of the relative states of the current row, the program array, and the screen array, or to access the field buffers and keystroke buffers: ARR_CURR(), ARR_COUNT(), FGL_SET_ARR_CURR(), SET_COUNT(), FIELD_TOUCHED(), GET_FLDBUF(), INFIELD(), FGL_DIALOG_GETFIELDNAME(), FGL_DIALOG_GETBUFFER().


Examples

Example 1: Basic INPUT ARRAY

Form definition file:

01 DATABASE stores
02
03 LAYOUT
04 TABLE
05 {
06 id        Name          LastName
07 [f001    ][f002        ][f003        ]
08 [f001    ][f002        ][f003        ]
09 [f001    ][f002        ][f003        ]
10 [f001    ][f002        ][f003        ]
11 [f001    ][f002        ][f003        ]
12 [f001    ][f002        ][f003        ]
13 } 
14 END
15 END
16 
17 TABLES
18   customer
19 END
20 
21 ATTRIBUTES
22   f001 = customer.customer_num ;
23   f002 = customer.fname ;
24   f003 = customer.lname ;
25 END
26 
27 INSTRUCTIONS
28   SCREEN RECORD sr_cust[6](
29     customer.customer_num,
30     customer.fname,
31     customer.lname);
32 END

Program source code:

01 MAIN
02 
03     DEFINE custarr ARRAY[500] OF RECORD
04             id INTEGER,
05             first_name CHAR(30),
06             last_name CHAR(30)
07     END RECORD
08     DEFINE counter INTEGER
09 
10     DEFER INTERRUPT
11     DEFER QUIT
12 
13     OPEN WINDOW w1 WITH FORM "FormFile"
14 
15     LET INT_FLAG = FALSE
16     INPUT ARRAY custarr WITHOUT DEFAULTS FROM sr_cust.*
17 
18     IF INT_FLAG = FALSE THEN
19         FOR counter = 1 TO arr_count() 
20             DISPLAY custarr[counter].*
21         END FOR
22     END IF
23
24     CLOSE WINDOW w1
25
26 END MAIN

Example 2: INPUT ARRAY using default values

The form definition file is the same as in example 1.

01 MAIN
02 
03     DEFINE allow_insert INTEGER
04     DEFINE size INTEGER
05     DEFINE counter INTEGER
06     DEFINE custarr ARRAY[500] OF RECORD
07             id INTEGER,
08             first_name CHAR(30),
09             last_name CHAR(30)
10     END RECORD
11
12     DEFER INTERRUPT
13     DEFER QUIT
14 
15     LET custarr[1].id = 1
16     LET custarr[1].first_name = "John"
17     LET custarr[1].last_name = "SMITH"
18     LET custarr[2].id = 2
19     LET custarr[2].first_name = "Mike"
20     LET custarr[2].last_name = "STONE"
21
22     LET size = 2
23     LET allow_insert = TRUE
24 
25     OPEN WINDOW w1 WITH FORM "FormFile"
26 
27     LET INT_FLAG = FALSE
28     INPUT ARRAY custarr WITHOUT DEFAULTS FROM sr_cust.*
29         ATTRIBUTE (COUNT=size, MAXCOUNT=50, UNBUFFERED, INSERT ROW=allow_insert)
30         BEFORE INPUT
31           MESSAGE "Editing the customer table"
32         BEFORE INSERT  
33           IF arr_curr()=4 THEN
34              CANCEL INSERT
35           END IF 
36         BEFORE FIELD fname
37           MESSAGE "Enter First Name"
38         BEFORE FIELD lname
39           MESSAGE "Enter Last Name"
40         AFTER FIELD lname
41           IF custarr[arr_curr()].lname IS NULL THEN
42              LET custarr[arr_curr()].fname = NULL
43           END IF
44     END INPUT
45
46     IF INT_FLAG = FALSE THEN
47         FOR counter = 1 TO arr_count() 
48             DISPLAY custarr[counter].*
49         END FOR
50     END IF
51
52     CLOSE WINDOW w1
53
54 END MAIN

Example 3: INPUT ARRAY using a dynamic array

The form definition file is the same as in example 1.

01 MAIN
02     DEFINE counter INTEGER
03     DEFINE custarr DYNAMIC ARRAY OF RECORD
04             id INTEGER,
05             first_name CHAR(30),
06             last_name CHAR(30)
07     END RECORD
08     DEFER INTERRUPT
09     DEFER QUIT
10     FOR counter = 1 TO 500 
11       LET custarr[1].id = counter
12       LET custarr[1].first_name = "ff"||counter
13       LET custarr[1].last_name = "NNN"||counter
14     END FOR
15     OPEN WINDOW w1 WITH FORM "FormFile"
16     INPUT ARRAY custarr WITHOUT DEFAULTS FROM sr_cust.*
17         ATTRIBUTE ( UNBUFFERED )
18         ON ROW CHANGE
19           MESSAGE "Row #"||arr_curr()||" has been updated."
20     END INPUT
21     CLOSE WINDOW w1
22 END MAIN