Defines a variable for use in one or more procedures, a variable data member of a class for use in a single class or class hierarchy, or by other classes and procedures, or a variable data element for use within a single class-based method.
DEFINE {[[ NEW [ GLOBAL ]] SHARED ]| [ PRIVATE | PROTECTED | PUBLIC ] [ STATIC ][ SERIALIZABLE | NON-SERIALIZABLE ]} VARIABLE variable-name {{ AS primitive-type-name | AS [ CLASS ]{object-type-name} | LIKE field }[ EXTENT [constant]]} [ SERIALIZE-NAME serialize-name ] [ BGCOLOR expression] [ COLUMN-LABEL label] [ CONTEXT-HELP-ID expression] [ DCOLOR expression] [ DECIMALS n] [ DROP-TARGET ] [ FONT expression] [ FGCOLOR expression] [ FORMAT string] [ INITIAL { constant |{[ constant[ , constant]...]}}] [ LABEL string[ , string]...] [ MOUSE-POINTER expression] [ NO-UNDO ] [[ NOT ] CASE-SENSITIVE ] [ PFCOLOR expression] {[ view-as-phrase ]} {[ trigger-phrase ]} |
PRIVATE variable data members can be accessed by the defining class. An instance can access a private data member of another instance if both instances are from the same class. PROTECTED variable data members can be accessed by the defining class and any of its derived classes. An instance can access a protected data member of another instance that is at the same level or higher in the class hierarchy. PUBLIC variable data members can be accessed by:
Any piece of code can access a PUBLIC static variable data member. The default access mode is PRIVATE.
A variable defined with the STATIC option is a static data member of the class type for which it is defined and is scoped to the ABL session where it is referenced. ABL creates one copy of the specified class static variable on first reference to the class type, and ABL creates only one such copy for any number of instances of the class that you create. You can reference an accessible static variable data member in any piece of code.
Without the STATIC option, ABL creates an instance variable data member that is scoped to a single instance of the class where it is defined. ABL creates one copy of the specified instance variable for each such class instance that you create. You can reference any public instance variable in any procedure, or in any instance or static method defined inside or outside of the class where the instance variable is defined. Any static method can reference the public instance variable only using an object reference to a class instance that defines the variable as a data member. If the referencing static method is defined in the same class as the public instance variable, the class must instantiate itself in order to have access to an instance reference.
For more information on the mechanism for accessing variable data members of different access modes and scopes, see the reference entry for Class-based data member access.
Use the NON-SERIALIZABLE option to exclude a given variable from the serialization process via the Progress.IO.BinarySerializer or Progress.IO.JsonSerializer class. A variable marked as NON-SERIALIZABLE is assigned its initial value when the class is deserialized.
You can also use the NON-SERIALIZALBE option to make a class that otherwise would not be serializable because one or more of its members. (See the Parameter passing syntax entry for full details on what can and cannot be serialized.) For example, if a variable itself is a class-based object that is not serializable, adding the NON-SERIALIZABLE keyword to that variable will allow the class that contains it to be defined as SERIALIZABLE.
If variable-name is an ABL reserved keyword, you must include an access mode of PUBLIC, PROTECTED, or PRIVATE in its definition. You must also use the THIS-OBJECT system reference or Type-name syntax to access the variable data member. For more information on referencing variable data members, see the reference entry for Class-based data member access.
For more information on where and how to define data members in a class, see the CLASS statement reference entry.
CHARACTER | COM-HANDLE | DATE | DATETIME | DATETIME-TZ | DECIMAL | HANDLE | INT64 | INTEGER | LOGICAL | LONGCHAR | MEMPTR | RAW | RECID | ROWID |
For more information on these primitive types, see the Data types reference entry.
You cannot directly specify the type name of a .NET mapped object type (such as System.Int32). To define a variable that matches a .NET mapped type, you must define it as the corresponding ABL primitive type (primitive-type-name).
For more information on object references, see the Class-based object reference reference entry.
If field has help and validate options defined, the variable you are defining does not inherit those characteristics.
If you reference a database field in a LIKE option in a DEFINE VARIABLE statement, DEFINE TEMP-TABLE statement, DEFINE WORK-TABLE statement, or format phrase, the database containing the referenced field must be connected at compile time but not necessarily at run time. Therefore, use the LIKE option with caution.
The EXTENT is part of the variable data type. For more information, see the Type-name syntax reference entry.
An indeterminate array variable can be in one of two states: fixed or unfixed, meaning it either has a fixed dimension or it does not. An indeterminate array variable has an unfixed dimension when first defined. You can fix the dimension of an indeterminate array variable by:
Once fixed, ABL treats a fixed indeterminate array as a determinate array.
If you want to define a variable that is like an array variable or field, using the LIKE option, but you do not want the variable to be an array, you can use EXTENT 0 to indicate a non-array field.
If you are using the AS option and you do not use the EXTENT option (or you specify constant as 0), the variable is not an array variable. If you are using the LIKE field option and you do not use the EXTENT option, the variable uses the extent defined for the database field you name (if any).
r-collbl.p
DEFINE VARIABLE credit-percent AS INTEGER NO-UNDO COLUMN-LABEL "Enter !percentage!increase ". FOR EACH Customer: DISPLAY Customer.Name Customer.CreditLimit. SET credit-percent. Customer.CreditLimit = (Customer.CreditLimit * (credit-percent / 100)) + Customer.CreditLimit. DISPLAY Customer.CreditLimit @ new-credit LIKE Customer.CreditLimit LABEL "New max cred". END. |
If you want to use the exclamation point (!) as one of the characters in a column label, use two exclamation points (!!).
The AVM does not display column labels if you use the SIDE-LABELS or NO-LABELS options with the Frame phrase.
If you define a variable to be LIKE a field, and that field has a column label in the Data Dictionary, the variable inherits that column label.
If you use the LIKE option to name a field whose definition you want to use to define a variable, ABL uses the number of decimals in the field definition to determine how many decimal places to store for the variable.
The following example shows setting the DROP-TARGET option for a variable:
Data type | Default display format |
---|---|
BLOB1 | See footnote 1. |
CHARACTER | x(8) |
CLASS2 | N/A |
CLOB1 | See footnote 1. |
COM-HANDLE | >>>>>>9 |
DATE | 99/99/99 |
DATETIME | 99/99/9999 HH:MM:SS.SSS |
DATETIME-TZ | 99/99/9999 HH:MM:SS.SSS+HH:MM |
DECIMAL | ->>,>>9.99 |
HANDLE | >>>>>>9 |
INT64 | ->,>>>,>>9 |
INTEGER | ->,>>>,>>9 |
LOGICAL | yes/no |
LONGCHAR1 | See footnote 1. |
MEMPTR1 | See footnote 1. |
RAW1 | See footnote 1. |
RECID | >>>>>>9 |
ROWID1 | See footnote 1. |
See OpenEdge Getting Started: ABL Essentials for more information on data formatting.
If you use the LIKE field option and you do not use the FORMAT string option, the variable uses the format defined for the database field you name. You must enclose the string in quotes.
When you define an array variable, you can supply initial values for each element in the array. For example:
If you do not supply enough values to fill up the elements of the array, the AVM puts the last value you named into the remaining elements of the array. If you supply too many values, the AVM raises an error.
If you define a variable as an indeterminate array, and you supply initial values for elements in the array, the AVM fixes the number of elements in the array and treats the fixed indeterminate array as a determinate array. For example, the arrays defined by the following statements are equivalent:
DEFINE VARIABLE x AS INTEGER NO-UNDO EXTENT INITIAL [1,2,3]. DEFINE VARIABLE x1 AS INTEGER NO-UNDO EXTENT 3 INITIAL [1,2,3]. |
You can also use the EXTENT statement to fix the number of elements in an unfixed indeterminate array variable. For more information, see the EXTENT statement reference entry.
The following table lists the default initial values for the various variable data types.
Data type | Default initial value |
---|---|
CHARACTER | "" (an empty string) |
CLASS3, 4 | Unknown value (?) |
COM-HANDLE4 | Unknown value (?) |
DATE | Unknown value (?) (displays as blanks) |
DATETIME | Unknown value (?) |
DATETIME-TZ | Unknown value (?) |
DECIMAL | 0 |
HANDLE4 | Unknown value (?) |
INT64 | 0 |
INTEGER | 0 |
LOGICAL | no |
LONGCHAR | Unknown value (?) |
MEMPTR4 | A zero-length sequence of bytes |
RAW4 | A zero-length sequence of bytes |
RECID | Unknown value (?) |
ROWID4 | Unknown value (?) |
If you are using the LIKE field option and you do not use the INITIAL constant option, the variable uses the initial value of the field or variable. In the DEFINE SHARED VARIABLE statement, the INITIAL option has no effect. However, the DEFINE NEW SHARED VARIABLE, the DEFINE NEW SHARED TEMP-TABLE, and the DEFINE NEW WORK-TABLE statements work with the INITIAL option.
You can specify a label for each element in a determinate array variable. You cannot specify a label for elements in an indeterminate array variable.
In MS-Windows, you can designate a character within each label as a navigation mnemonic. Precede the character with an ampersand (&). When the variable is displayed with side labels, the mnemonic is underlined. The user can move focus to the variable by pressing ALT and the underlined letter. Navigation mnemonics operate only when you use side labels. If you specify more than one widget with the same mnemonic, the AVM transfers focus to each of these in tab order when you make a selection.
Ending a label with an ampersand might produce unwanted behavior. To include a literal ampersand within a label, specify a double ampersand (&&).
Specifying NO-UNDO for a variable is especially useful if you want to indicate an error condition as the value of the variable, perform an UNDO, and later take some action based on that error condition. If one variable is defined LIKE another that is NO-UNDO, the second variable will be NO-UNDO only if you specify NO-UNDO in the definition of the second variable.
VIEW-AS { combo-box-phrase | editor-phrase | FILL-IN [ NATIVE ] [size-phrase] [ TOOLTIP tooltip] | radio-set-phrase | selection-list-phrase | slider-phrase | TEXT [size-phrase] [ TOOLTIP tooltip] | TOGGLE-BOX [size-phrase] [ TOOLTIP tooltip] } |
For more information on view-as-phrase, see the VIEW-AS phrase reference entry.
TRIGGERS: { ON event-list[ ANYWHERE ] { trigger-block | PERSISTENT RUN proc-name [ IN handle] [ ( input-parameters ) ] } }... END [ TRIGGERS ] |
For more information on triggers, see the Trigger phrase reference entry.
The r-dfvar.p procedure defines two variables, del and nrecs to be shared with procedure r-dfvar2.p. The del variable passes information to r-dfvar2.p, while nrecs passes information back to r-dfvar.p from r-dfvar2.p.
r-dfvar.p
DEFINE NEW SHARED VARIABLE del AS LOGICAL NO-UNDO. DEFINE NEW SHARED VARIABLE nrecs AS INTEGER NO-UNDO. MESSAGE "Do you want to delete the orders being printed (y/n)?" UPDATE del. RUN r-dfvar2.p. IF del THEN MESSAGE nrecs "orders have been shipped and were deleted". ELSE MESSAGE nrecs "orders have been shipped". |
r-dfvar2.p
DEFINE SHARED VARIABLE del AS LOGICAL NO-UNDO. DEFINE SHARED VARIABLE nrecs AS INTEGER NO-UNDO. OUTPUT TO PRINTER. FOR EACH Order WHERE Order.ShipDate <> ?: nrecs = nrecs + 1. FOR EACH OrderLine OF Order: DISPLAY OrderLine.OrderNum OrderLine.LineNum OrderLine.Qty OrderLine.Price. IF del THEN DELETE OrderLine. END. IF del THEN DELETE Order. END. OUTPUT CLOSE. |
The following example is a startup procedure. It defines a new global variable with the initial value TRUE and uses that variable to determine whether to run an initialization procedure, r-init.p, that displays sign-on messages. Then the global variable first-time is set to FALSE. If you restart this procedure during the same session (pressed STOP), r-init.p does not run again.
The procedure also defines the variable selection for entering menu choices within this procedure:
r-dfvar3.p
DEFINE NEW GLOBAL SHARED VARIABLE first-time AS LOGICAL NO-UNDO INITIAL TRUE. DEFINE VARIABLE selection AS INTEGER NO-UNDO FORMAT "9" LABEL "Selection". IF first-time THEN DO: RUN r-init.p. first-time = FALSE. END. FORM " MAIN MENU " SKIP(1) "1 - Accounts Payable " SKIP "2 - Accounts Receivable" WITH CENTERED ROW 5 FRAME menu. REPEAT: VIEW FRAME menu. UPDATE selection AUTO-RETURN WITH FRAME sel CENTERED ROW 12 SIDE-LABELS. IF selection = 1 THEN DO: HIDE FRAME menu. HIDE FRAME sel. RUN apmenu.p. END. ELSE IF selection = 2 THEN DO: HIDE FRAME menu. HIDE FRAME sel. RUN armenu.p. END. ELSE DO: MESSAGE "Invalid selection. Try again". UNDO, RETRY. END. END. |
The following procedure finds the day of the week of a date the user enters. The procedure defines an array with seven elements and uses the INITIAL option to define the initial value of each element in the array.
r-dfvar4.p
DEFINE VARIABLE dow AS CHARACTER NO-UNDO FORMAT "x(9)" EXTENT 7 INITIAL ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]. DEFINE VARIABLE dob AS DATE NO-UNDO INITIAL TODAY. REPEAT WITH SIDE-LABELS 1 DOWN CENTERED ROW 10 TITLE "Date of Birth": DISPLAY SKIP(1). UPDATE dob LABEL "Enter date of birth". DISPLAY dow[WEEKDAY(dob)] LABEL "It was a". END. |
The following example defines a variable with a VIEW-AS phrase and a Trigger phrase:
r-defsel.p
DEFINE VARIABLE ix AS INTEGER NO-UNDO. DEFINE VARIABLE clubs AS CHARACTER NO-UNDO VIEW-AS SELECTION-LIST SIZE 20 BY 5 MULTIPLE SCROLLBAR-VERTICAL NO-DRAG LIST-ITEMS "One Iron", "Two Iron", "Three Iron", "Four Iron", "Five Iron", "Six Iron", "Seven Iron", "Eight Iron", "Nine Iron", "Pitching Wedge" LABEL "Golf Clubs Available" TRIGGERS: ON GO DO: IF SELF:SCREEN-VALUE <> "" THEN DO ix = 1 TO NUM-ENTRIES(SELF:SCREEN-VALUE) : DISPLAY ENTRY(ix, SELF:SCREEN-VALUE) FORMAT "X(16)" WITH FRAME clubs-sel CENTERED NUM-ENTRIES(SELF:SCREEN-VALUE) + 1 DOWN TITLE "Clubs Selected" USE-TEXT. DOWN 1 WITH FRAME clubs-sel. END. END. END TRIGGERS. ENABLE clubs WITH FRAME get-info TITLE "Select the Desired Club(s)". WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW. |
For examples of instance and static variable data member definitions, see the descriptions of r-CustObj.cls, r-CustObjStatic.cls, and r-CustObjAbstract.cls in the CLASS statement reference entry.
If a trigger or internal procedure of a persistent procedure executes an external subprocedure that defines a SHARED variable, the AVM includes the persistent procedure in the resolution of the corresponding NEW SHARED variable as though the procedure were on the procedure call stack.