Must be formatted correctly for the operating system being used. For Windows either a fully qualified name in the format <drive>:\<path>\<file>.<suffix> may be used, or a shortened form such as <file>.<suffix>. The shortened form will replace or create the file in the current directory.
The <suffix> value DAT is conventionally used for permanent data files and TMP for temporary files. If the file exists it is opened and all existing data is erased. If the file does not exist it is created and then opened.
Some character values may corrupt the output file if they are inserted into the output data. This option specifies what should happen if an invalid character is encountered. The set of invalid characters that are scanned for varies by requested output format as follows:
Note: Only Alpha, Char, String, BLOB, CLOB fields are scanned for invalid characters.
The supported invalid character handling options are:
This option is only required when the system is configured to use a comma (,) as the decimal point delimiter. By default, output numeric fields will use the comma but this may not be appropriate when other products will not accept the comma. This option may be used to force this Built-In Function to use the full stop/period character (.).
The other use for this parameter is the special 'R' (Remove) option that may be used when creating files for input to applications that use fixed record formats and "implied (by position)" decimal points.
The 'R' option can only be used with file formats 'C' and 'D'.
The Close Output File option prevents the Built-In Function from closing the output file when it has completed execution.
In normal use, a working list is loaded with data and passed to this Built-In Function. The list is read, written to the disk file, and then the disk file is closed. Subsequent use of this Built-In Function with the same file name will replace the existing file (and its data) with a new set of data.
By using the "do not close" option, much more complex processing may be performed such as in the following example.
To avoid using huge working lists which require a large amount of allocated memory, the following code will create any number of records in the output file even though the list being used is efficiently sized with just 100 entries. The list is acting like an output buffer for the application.
def_list #list fields(....) listcount(#count)
select fields(...) from_file(...)
if (#count = 100)
use TRANSFORM_LIST #list (with "do not
use TRANSFORM_LIST #list (with "close" option)
def_list #head fields(....) type(*working) entrys(1)
def_list #line fields(....) listcount(#count) type(*working) entrys(100)
select fields(...) from_file(orders)
inz_list #head num_entrys(1)
use TRANSFORM_LIST #head (with "do not close" option)
select fields(...) from_file(lines) with_key(...)
if (#count = 100)
use TRANSFORM_LIST #line (with "do not
use TRANSFORM_LIST #line (with "do not close"
use TRANSFORM_LIST #line (an empty list with "close"
Some tips for using this option, and for using this Built-In Function are:
With the introduction of RDMLX working list, which may contain up to 1000 fields, 2G (2147483647) entries with an entry length of up to 2Gb (2147483647 bytes ), in most of the cases you will not need the Appendage Lists. How ever if RDMLX appendage lists are used, the same rules as for RDML lists are applied (apart from the above). Note that when the primary working list is an RDMLX list, an appendage list cannot be used.
Up to 10 appendage working lists may be specified when invoking this Built-In Function. This Built-In Function uses a driving loop that can be represented like this:
-> do for each entry in the "primary" working list (ie: argument 1)
| map details of primary list entry "n" to output buffer
| -> do for each appendage working list that has been specified.
| | get a matching entry "n" from the appendage list.
| | -- if entry "n" can be found
| | | -- test the case of the entry's "appendage option"
| | | |----> when = A, Append this entry to the current record.
| | | |----> when = N, Write the existing buffer, ends the current record with a New Line
| | | | character . Clear the output buffer and map this entry into it to start a new | | | | record.
| | | |----> when = O, Omit (ie: skip) this list entry.
| | | |----> otherwise: Issue a fatal error and kill the function.
| | | -- endcase
| | -- endif
| -- enddo
| if the buffer is not empty, write output record from buffer.
Note the "appendage option". Any working list that is used as an appendage list must have an alphanumeric 1 field as its first defined field. This alphanumeric 1 field is the "appendage option" and indicates how the entry should be handled. The currently supported values are:
Append this entry to the output buffer being built.
Write the existing buffer and make a new one with this entry.
Omit this entry from the output stream.
The appendage option field is not really part of the list. Its value is tested, but it is not output to the output buffer, so it has no bearing in record layout and/or length calculations even though it is actually part of the working list definition.
So far the use of "appendage lists" may not be apparent. However, by using appendage lists you can solve the following problem:
The following example covers the "A" (append) option. However the "N" (new) and "O" (omit) appendage options can be effectively used to create "variable record files" in an efficient manner.
def_list #plist fields(....) type(*working)
def_list #alist1 fields(#aoption .....) type(*working)
change #aoption 'A'
select fields(...) from_file(....)
fetch fields(...) from_file(...)
fetch fields(...) from_file(...)
fetch fields(...) from_file(...)
use TRANSFORM_LIST #plist (with appendage list #alist1)
Consider some sort of "transaction" output file that you must create for input to an existing mainframe application system.
Every customer must have a type "HDR" header record. There may be a type "ADR" address update record and there may be a type "BIL" billing record. Very old fashioned, but still very common.
By defining a primary list for the HDR data and two appendage lists for the ADR and BIL data (with appendage option fields) a "stream" of mixed format and optional records like this can be created by just one invocation of this Built-In Function. In this case the appendage options O (omit) and N (new) would be used.
If however, you wanted to create multiple BIL records for a single HDR record you would have to use the "do not close" option. See the reference in the Close Output File Option for more details of how this could be achieved.
The following table indicates the types of errors that you can trap at the RDML level with an "ER" return code (User Trap) and those that will cause a complete failure of your application (System Error). System errors invoke Visual LANSA full error handling and cause the entire X_RUN "session" to end. They cannot normally be trapped at the RDML level.
It is very strongly recommended that you avoid building complex error handling schemes into your applications. Use a very simple trap like this at all levels of your application.
if (#retcode *ne OK)
abort msgtxt('Failed to .............................')
Let the standard error handling Built-In Function to every generated application take care of the problem. Situations have arisen where user defined error handling logic has become so complex as to consume 40 - 50% of all RDML code (with no obvious benefit to the application). Do not fall into this trap.
The Julian Day Count is a uniform count of days from the past (-4712 January 1, 12 hours UTC (Universal Coordinated Time - the modern equivalent of Greenwich Mean Time) (Julian proleptic Calendar) = 4713 BCE January 1, 12 hours GMT (Julian proleptic Calendar) = 4714 BCE November 24, 12 hours GMT (Gregorian proleptic Calendar)). At this point, the Julian Day Number is 0.
The Julian Day Count is not related to the Julian Calendar introduced by Julius Caesar.
There are several algorithms of calculating the Julian Day Number. Although they are very similar to each other, the results may be different. The algorithm used by this Built-In Function calculates the Julian Day Number of any date given on the Gregorian Calendar. The Julian Day Number calculated will be for 0 hours, GMT, on that date.
1. Express the date as Y M D, where Y is the year, M is the month number (Jan = 1, Feb = 2, etc.), and D is the day in the month.
2. If the month is January or February, subtract 1 from the year to get a new Y, and add 12 to the month to get a new M. (Thus, we are thinking of January and February as being the 13th and 14th month of the previous year).
3. Dropping the fractional part of all results of all multiplications and divisions, let
A = Y/100
B = A/4
C = 2-A+B
E = 365.25x(Y+4716)
F = 30.6001x(M+1)
This is the Julian Day Number for the beginning of the date in question at 0 hours, UTC.
The following calculation is used to convert a Julian Day Number to a Gregorian date, assuming that it is for 0 hours, UTC. Drop the fractional part of all multiplicatons and divisions.
Note: This method will not give dates accurately on the Gregorian Proleptic Calendar, that is, the calendar you get by extending the Gregorian calendar backwards to years earlier than 1582 using the Gregorian leap year rules. In particular, this method fails if Y<400.
Z = JD
W = (Z - 1867216.25)/36524.25
X = W/4
A = Z+1+W-X
B = A+1524
C = (B-122.1)/365.25
D = 365.25xC
E = (B-D)/30.6001
F = 30.6001xE
Day of month = B-D-F
Month = E-1 or E-13 (must get number less than or equal to 12)
Year = C-4715 (if Month is January or February) or C-4716 (otherwise).