The RPG Decimal subroutine provides an RPG solution for converting a
left adjusted character field (with or without decimal position or
separator characters) into a decimal field. Various validity
checking options exist.
The intent of the subroutine is to allow for a character field to be
prompted for or passed into a program that may contain either a
special value (such as *START) or a decimal value. The data will
probably be stored as a decimal value and user code must convert the
special values (such as converting to -1). The subroutine is used to
convert the character string to a decimal value.
The concept is similar to the function provided by the system command
prompter that allows special values in a decimal field. The SPCVAL
keyword allows a special value (such as *MAX) to be converted to a
unique decimal value (such as *START = -1).
The subroutine may also be used whenever left adjusted character data
must be converted to a decimal value.
A variety of validity checking is performed in the subroutine. Some
of the checking is standard (such as ensuring 15 or less valid
digits). Some validity checking is based on user options such as:
- Whether decimal positions exist (or are optional)
- Whether a zero value is valid
- A maximum and/or minimum number of digits
- A maximum and/or minimum value
- Whether a minus sign may exist (either before or after)
To use the subroutine, you must pass a required input field.
Optional values may also be passed to allow for additional validity
checking and to describe the data. When the subroutine ends, the
edited value is passed back in a right adjusted decimal field along
with the number of digits entered. An error field should be tested
after each use of the subroutine. If an error has occurred, error
text is provided in a field that is suitable to be displayed to an
end user.
A demonstration program exists that allows the special value *MAX to
be entered or a decimal value. Messages are returned. The decimal
value is checked as follows:
- The value must contain two decimal positions
- A minimum of 3 digits must be entered
- A maximum of 9 digits may be entered
- A maximum value of 8888888.88 may be entered
- A minus sign is not valid
Call the demonstration program (TAARPHBR) and pass it up to a 22 byte
character variable (you must use quotes) such as:
CALL TAARPHBR PARM('300.23')
or
CALL TAARPHBR PARM('*MAX')
You can try invalid values such as:
300 No decimal positions
.00 Less than minimum length
12345678.90 More than max length
3A0.23 Invalid data
-312.34 Minus sign not expected
8888888.89 Greater than maximum value
Using the subroutine
--------------------
To use the subroutine, first use CPYTAA:
CPYTAA TAAARCMBR(TAARPHBR)
By default, this will copy the source to member TAARPHBR in QATTRPG
in TAATOOL.
You can then use the copy/browse function of SEU to copy the code
into any of your programs. Follow the instructions within the code
for how to:
** Insert the code at the proper points within your program.
** Remove the demonstration code
** Add your own unique code
The fields used within the subroutine and for communication all begin
with the letters ZD to avoid conflicts with your field names.
For standard use, there is no reason to understand the logic of or to
modify the subroutine code. Only the fields passed to and from the
subroutine must be understood.
Required input field
--------------------
The character data should be passed left adjusted into the field
ZDWRKI which is defined as 22 bytes. The field should be padded
(with blanks). A typical calc spec would be:
C MOVELxxx ZDWRKI P Input work
By default, the field is assumed to:
- Have 0 decimal positions (decimal positions are not valid)
- Not allow a minus sign
- Allow up to 15 digits to be entered
- Allow a 0 value to be valid
- Not allow separator characters
To change the defaults, see the section on Input Options.
The input field cannot be all blank and cannot have leading blanks.
Return fields (after executing the subroutine)
----------------------------------------------
These fields are reset to zeros or blanks at the beginning of the
subroutine each time it is executed.
ZDDECA The answer in decimal (right adjusted). The field
is *DEC LEN(15 0). Any decimal position characters
or separator characters have been removed. If a
minus value was entered and a minus sign is valid,
the field will be negative.
ZDVLDD The number of digits in the answer. The field is
*DEC LEN(3 0). This includes any digits to the
right of the decimal position.
ZDVLDP The number of decimal positions in the answer. The
field is *DEC LEN(3 0). This value may be
meaningful if you have specified that the number of
decimal positions is optional.
ZDERRN The error number if any. The field is *CHAR LEN(2).
If a good value is returned, the field will be
blank.
If an error has occurred, the field will contain the
error number assigned to the error. Refer to the
ZDERRC and ZDERRT array data for the meaning of the
codes and text.
ZDETXT The error text if any. The field is *CHAR LEN(60).
If a good value is returned, the field will be
blank. If an error has occurred, the field contains
error text which is suitable to be displayed to an
end user. Refer to the ZDERRC and ZDERRT array data
for the meaning of the codes and text.
Input options (before executing the subroutine)
-----------------------------------------------
These fields are not reset by the subroutine. If you use the
subroutine for multiple user fields, you may need to vary the options
before each use of the subroutine.
ZDDECP The number of decimal positions to be entered. The
field is *DEC LEN(1 0). The default is zero which
means no decimals are valid.
For example, if a value such as 2 is entered, the
ZDWRKI value must have a decimal position character
and two digits to the right of the character.
If entering decimal positions is optional, use a -1
value. The return result field ZDVLDP will contain
the number of decimal positions found.
See the ZDDECC field to define the decimal position
character.
ZDALWM Whether a minus sign is allowed. The field is a
*CHAR LEN(4). The default is blank which means no
minus sign may exist (the ZDWRKI value is considered
positive).
A *YES may be entered to allow for a minus sign.
The minus sign may be to the left or right of the
value such as -300 or 300-.
Any value other than *YES is considered to be the
default.
ZDMAXL The maximum length in digits which may be entered.
The field is *DEC LEN(2 0). The subroutine has a
limit of 15 which acts as the default. A smaller
number may be specified.
If a specific number of digits is required, both the
maximum and minimum should be the same value.
If you move a character field of length 5 to ZDWRKI,
by definition the field cannot contain more than 5
digits. If it is a 5 digit field, but you only
allow an entry of 4 digits, you should specify
ZDMAXL.
ZDMINL The minimum length in digits which may be entered.
The field is *DEC LEN(2 0). The default is 0
meaning there is no minimum.
If you specify a value, there must be at least that
number of digits entered (including digits to the
right of the decimal position).
ZDALW0 Whether a zero value is valid. The field is *CHAR
LEN(3). The default is blank which means to allow
zero values. *NO may be specified to prevent zero
values.
Any value other than *NO is considered to be the
default.
ZDMAXV The maximum value that may be entered. The field is
*DEC LEN(15 0). The default is 0 meaning there is
no maximum value. After the input field is
converted to a decimal value, it is compared to the
maximum value (if one exists). The comparison
ignores any decimal positions.
For example, if the largest allowed value is 888.88,
enter a maximum of 88888.
If an error occurs, the text of the message is
'Greater than maximum value'. You can concatenate
up to 22 bytes of additional text to the message by
using the ZDMAXT field.
ZDMINV The minimum value that may be entered. The field is
*DEC LEN(15 0). The default is 0 meaning there is
no minimum value. After the input field is
converted to a decimal value, it is compared to the
minimum value (if one exists). The comparison
ignores any decimal positions.
For example, if the smallest allowed value is 1.01,
enter a minimum of 101.
If an error occurs, the text of the message is 'Less
than minimum value'. You can concatenate up to 22
bytes of additional text to the message by using the
ZDMINT field.
ZDMAXT The additional text to be concatenated to the
'Greater than maximum value' error message. The
field is *CHAR LEN(22). The default is blank
meaning there is no additional text. The intent of
the field is to allow you to tailor the text to
provide meaningful feedback. If the user must enter
a 2 decimal position field with separators that is
less than 888888, you could provide additional text
such as '8,888.88'.
ZDMINT The additional text to be concatenated to the 'Less
than minimum value' error message. The field is
*CHAR LEN(22). The default is blank meaning there
is no additional text. The intent of the field is
to allow you to tailor the text to provide
meaningful feedback. If the user must enter a 2
decimal position field that is less than 100, you
could provide additional text such as '1.00'.
ZDDECC The character to be used to denote the decimal
position. The field is *CHAR LEN(1). The default
is blank which means '.' (US notation). Any value
may be entered.
ZDALWS Whether to allow a separator character. The field
is *CHAR LEN(4). The default is blank which means
no separator characters are valid. *YES may be
entered to allow for a separator character as
defined by the ZDSEPC field.
Any value other than *YES is considered to be the
default.
ZDSEPC The character to be used to denote the separator
character. The field is *CHAR LEN(1). The default
is blank which means ',' (US notation). Any value
may be entered.
Separator characters are just ignored in the field.
If a value such as 3,23.00 is entered, the value is
considered valid and 32300 would be returned.
Typical application solutions
-----------------------------
Assume you have a decimal field in the data base and you want to
allow the end user to enter either one or more special values or a
number. The special values will be translated into specific numbers
for the field. For example, if all of the data should be positive
values, you can use either 0 or specific negative values (such as -1)
to represent the special values.
Or, if you want to allow a special value of *MAX, you could reserve
an all 9s value in the data and prevent the user from keying all 9s
by placing a maximum value on the field such as 99998.
Assume the field will also be used in a change mode where the current
number will be shown or the special value. Now your code must
translate the unique value in the data base to the special value
(such as -1 becomes *MAX). Actual values must be displayed left
justified.
If the field has no editing characters (such as a decimal point), you
can use the ZEDIT TAA Tool to edit the value. This provides the
ZEDITL subroutine which will strip off any leading zeros and left
adjust the value.
If the field has editing characters and you would like to display an
edited value, then the EDTVAR2 TAA Tool should be considered. It
allows you to input a decimal field and a normal RPG edit code. The
return value is left adjusted edited value which is ready to be
displayed.
The following code provides an example of how the subroutines for the
two tools EDTVAR2 and DECRPGSUBR would work together with a *MAX
special value that is converted to 0. The amount field in the data
base is named AMT. Note that both subroutines require additional
code that is not shown.
C* If 0, display *MAX (the display field is DSPVAL)
C AMT IFEQ 0 If 0
C MOVEL'*MAX' DSPVAL 22 P Display valu
C ENDIF If 0
C* If GT 0, display edited value left adjusted
C AMT IFGT 0 If GT 0
C MOVE AMT ZEINP Input field
C MOVE 'L' ZEEDTC Edit code
C MOVE '2' ZEDECP Nbr of decs
C EXSR ZEEDIT Edit subr
C MOVELZEODS DSPVAL P Edited value
C ENDIF If GT 0
C* Display the value and allow user to change
C*
C* After user has pressed Enter
C*
C DSPVAL IFEQ '*MAX' If *MAX
C Z-ADD0 AMT Use 0
C ENDIF If *MAX
C* If not *MAX, use RPG Dec Subr
C DSPVAL IFNE '*MAX' Not *MAX
C MOVELDSPVAL ZDWRKI P Input field
C Z-ADD2 ZDDECP Dec pos
C Z-ADD9999999 ZDMAXV Max value
C EXSR ZDDECS RPG Dec Subr
C ZDERRN IFNE *BLANKS Not blanks
C* User coding to re-display with error text from ZDETXT
C ENDIF Not blanks
C* Good value entered
C MOVE ZDDECA AMT DB field
C ENDIF Not *MAX
Restrictions
------------
See the previous details.
Prerequisites
-------------
None.
Implementation
--------------
None, the demonstration is ready to use. To use the subroutine in
your own application, follow the previous instructions.
Objects used by the tool
------------------------
Object Type Attribute Src member Src file
------ ---- --------- ---------- ----------
TAARPHBR *PGM RPG TAARPHBR QATTRPG
The TAARPHBR source is both a working program for use as a
demonstration as well as containing the subroutine and instructions
that should be copied into your program.
|