CDS038

Print Records

Last Revised: 09/15/17

CDS038 is a very powerful Dynamo Tool used to print reports to printers (or other output devices), create tab delimited text files, and create files that can be used as input on subsequent calls to CDS038.

The capabilities of CDS038 are best realized when printing to a PCL compatible printer, such as a laser or inkjet.  On these printers, CDS038 will perform font reduction, automatically rotate to landscape, and supports landscape on legal size paper, in order to place as many fields on the same line as possible.

CDS038 is designed for printed output.  See CDS037 for similar features that is designed for display output including scrolling up and down.  See CDW038 for HTML output.  CDS038 creates tab delimited files with a .xls extension when printing to printer ID PFIL.  These files can be opened with a spreadsheet application such as Microsoft Excel.  You can also create these spreadsheet files in Dynaweb.  See example below.

Calling Format:

CALL "CDS038", Y$, Y5$, Y5A$, Y6$, Y6, L, P, S038$, FILENAME$, { KNUM, KEYBEGIN$, KEYEND$, DISP$, WHERE$, SORTBY$, MODE$, LIMIT, SUBHEAD$ }

All fields after FILENAME$ are optional.

CDS038 Arguments
Y$ Standard task control variable and is used to print the company name at the center of the top line of each page.
Y5$ Report title to be centered on the second line of each page.  Normally passed to application from Menu Processor.
Y5A$ Optional report sub-title to be centered below the report title.
Y6$ Standard printer control record returned by the printer selection routine (CDS084).  If Y6$ is passed to CDS038 as null, then CDS038 will call CDS084 to open the printer.  In this case the Y6.MSG$ will be displayed by CDS038.  On PCL compatible printers that support scalable fonts, CDS038 will automatically select the characters per inch required for the report. It will also automatically select landscape printing when the number of columns required for portrait printing exceeds 136 columns. This permits up to 210 columns to print using 20 characters per inch in landscape mode.
Y6 No longer used. It has been replaced by Y6.CH, which is the channel number of the printer or output device.
L No longer used. It has been replaced by Y6.L, which is the number of lines left to print on the page.
P No longer used. It has been replaced by Y6.P which is the last page number printed.
S038$ S038$ contains optional parameters. You may pass a null string to use all default values, or a string literal, or retrieve the template for S038$ with CALL "CDS041",CDS038,S038$ and set any of the parameters you require that differ from the default value.
S038.NOTIFY$will notify operator if set to Y and no records are determined to be printed. Default is Y.
S038.PRINTCOUNT$will print the number of records printed at the end of the output if set to Y. Default is N.
S038.KEEPOPEN$
blank, N, or EPrinter device is closed using CDS094 at end of report.  User is offered option to view report if output is PDF or text file.
ePrinter device is closed using CDS094 at end of report.  User is not offer option to view report if output is PDF or text file.
YKeep printer open at end of job.  Useful if additional printing or calls to CDS038 are required to same printer.
S038.COLHEAD$
ValueNormal ReportCreating tab delimited spreadsheet compatible files
blank or NNormal - column headings based on column titles are printed at the top of each page.Column headings will be field names.  Repeating fields will include index in square brackets, i.e., SALES[9].
YPrint column heading at start of job, typically used when multiple CDS038 calls are issued to the same printed report and column headings are required even if not at top of page.  Column headings will be the column titles, and not the field names.
SSuppress all column headings.First row will contain first row of data and not field names nor titles.
EPrint column headings before each record.  This might be desired when printing a heading/detail type report where the column headings for the heading rows print before each heading record.  The detail section is printed by the S038.EXTRTN$ program which also calls CDS038 to print the detail section.Column headings will be field names, but repeating fields will be designated with and underscore followed by the index, instead of using square brackets, i.e., SALES_9.  This is useful when importing into other databases, such as MySQL, that do not support repeating fields.
S038.WORKFILE$
blank or NOutput will be directed to printer or other output device as specified by printer control variable Y6$ (Default).
YStores all output in an SKY file and ignore DISP$ column headings and row/column numbers. The file will be created in the tmp directory with a name based on the program that called CDS038. A template will be created (in memory only) to describe the output file. This file name is returned to the calling program in the printer control variable Y6$. When the program returns to the menu, the data file will be erased. This option is useful when it is desired to select records based on fields that do not exist in the primary data file. The first step would be to call CDS038 using the primary data file with all external fields specified and pass this parameter as Y. Then call CDS038 again, selecting records from the temporary file just created.
PPermanent - Similar to the Y option, except that the file is created in the same directory as FILENAME$ using a numeric suffix to the original file name.  A template file is also defined on the disk, and the file is not erased upon return to the menu.
S038.BLANKS_Bindicates the number of blank lines to print after each record. If there is an external routine, indicated below, then these blank lines print before the external routine.
S038.EXTRTN$can contain a program name which is called by CDS038 after each record is printed. This may be needed when additional printing is required that cannot be done by CDS038. The ENTER list for the called routine is Y$,Y5$,Y5A$,Y6$,REC$ where Y$ thru Y6$ are the same variables described above, and REC$ is the templated data from the primary data file. Note that the external routine must decrement Y6.L for every line printed. CDS094 should be called for new page logic since it resets Y6.L and increments Y6.P. Note the previous ENTER list that included Y6, L, and P is no longer supported.
S038.BLANKS_Ablank lines to print after external routine is called.
S038.BLANKS_EORblank lines to print at the end of the report. This is useful when multiple calls to CDS038 are made to produce a report and blanks are needed between calls.
S038.LEGAL$OK to use legal sized paper (Y/N). When set to Y, CDS038 will format the columns assuming legal size (14") paper is used if the columns to be printed require landscape mode and printing at the greatest characters per inch of the printer does not fit on standard 11" paper.
S038.FORMAT$
blankUse normal formatting as described in DISP$.
PPrint each record on a separate page.
1Print one field per row, one record per page.  This option ignores any row and column options within DISP$.
CSimilar to blank, except print lines are combined into a single line when possible.  This is useful when a report normally takes multiple print lines, but should be combined onto a single line when there is only one non-blank character per print column.
TCDS038 creates tab delimited files, suitable for opening with a spreadsheet application, when the printer selected is "PFIL".  In order to create a formatted text file instead of a tab delimited file, pass S038.FORMAT$ as "T".
NWhen creating a tab delimited file, setting this parameter to N will not trim leading and trailing blank characters, nor replace non-printable characters with blanks.
S038.PROGRESS$If W then Web based progress indicator is displayed to prevent browser from timing out.
S038.RPTHEAD$
blankPrint standard page headings
NSuppress printing of documentation control number, date, time, and page number.  Useful on financial statements or other reports where headings are not desired.
TUsed to indicate that first print line as described in DISP$ should print centered on the top of the page, instead of in the body of the report.  Subsequent DISP$ rows print in the normal position.  Note that when using this option Y5A$ is ignored. 
S038.BLANKS_ARHNumber of blank lines to print after report heading.
S038.UNIQUEFLDSUsed when creating a work file (S038.WORKFILE$="Y") to modify the field name of all fields in the work file to include the file name.  This is needed when a field name in the primary file, is the same as a field name in a related file.  For example, if a work file is created using DISP$ of "NAME|CM03.NAME" the work file field names will be WORK.NAME$ and WORK.CM03__NAME$.
S038.AUTODUP$Set to N if you want to disable the new default behavior that prints all fields with a B in the DISP$ options (segment 5) field when an earlier field in DISP$ also with a B in the DISP$ options segment differs from the line above.  Best understood in this example.
S038.MARGINAssigned by CDS038 when it indents the report to allow for room for three hole notebook paper.  Used by the calling application should it need to print additional information on the report, i.e., PRINT (Y6.CH)@(S038.MARGIN),S553.RANGEDISP$
S038.RECORDSSet by CDS038 to the number of records in the primary file that were processed.  This is useful when calling program logic needs to know if any records were printed.
FILENAME$ The file name of the primary data file.  The file can be type MKY, SKY, or DIR and requires a template.  FILENAME$ will be opened using either OPEN or SELECT.  If WHERE$, SORTBY$, or MODE$ is specified, then SELECT will be used and KNUM, KEYBEGIN$, and KEYEND$ will be ignored.
KNUM The KNUM of the file to be used.  Ignored if WHERE$, SORTBY$, or MODE$ is used or if the file type is not MKY.
KEYBEGIN$ Indicates the starting characters of the first key when printing a range of records in FILENAME$.
KEYEND$ Indicates the last key of the range.  If KEYEND$ is null, then it will be assumed to be the same as KEYBEGIN$.
DISP$ If DISP$ is null, not passed, or the field name is *, then all fields in the record will be output, excluding any field that begins with the word "UNUSED" or "FS". Fields named FSn are often used to designate field separators at the end of a multi-segment IOLIST type field, in order to insure new records created with the template have fields padded to the proper length.  Note that the * wildcard may also be used to include all fields in a related file or external routine.  For example a DISP$ of "*|XXIM01.*|WO020.*" would include all fields in the primary data file, followed by all fields in related file XXIM01, and then all fields provided by the external routine WO020.

The fields within DISP$ are separated by the pipe (|) symbol. The optional segments within each field are separated by the backslash (\).  If all segments in a field are specified, the format of each field would be FILE.FIELD[INDEX]\Title\Mask\Col,Row\Options\Where\Sort|.

You may skip over fields not needed using the separator character as in "NAME\\\\B".

Segment 1
Field Name
If the field is contained within FILENAME$, then only the field name is required as in NAME.

If the field is a repeating field, then you may include the index as in AMT[3].  You may also use the ALL index as in AMT[ALL] to include all elements of a repeating field.

If the field is contained in a related file, then specify the file name in template format: XXCM01.NAME.

If the field is provided by a called program, specify the program name in template format: PGMNAME.VALUE.  For example, if a program named AP101 computes a balance, and has a template associated with the program, you can specify AP101.BALANCE in segment 1.  The ENTER list on AP101 must be Y$,REC$,AP101$ where REC$ is the input record from FILENAME$, and AP101$ is the templated string that is populated by the AP101 program.  In some cases the called routine performs logic to further condition printing of the primary record.  If the called routine exits with an error, as in EXIT 99 for example, the primary record will be excluded from the report.  The called program requires a Data Dictionary entry.  The location of the program will determine the company used to access the Data Dictionary.  For example, if a program is DY/AP101, then the DY Data Dictionary will be used to obtain the template for AP101.

There are also some special fields that may be used to print a sequential counter, underlines, compute gross margin, compute percent change, etc.  See special fields section below.

Segment 2
Title

The Best Practice is not to specify anything in Segment 2.  In that case, CDS038 will use the title from the template, which originated in the Data Dictionary.  If the template does not contain a title, then the field name itself will be used for the column title and will be converted to mixed case.

The Title prints as a column heading on the report.

An entry in Segment 2 is required only when you want to override the default title.

When the field name is used to create the column title, field names that end in NO are replaced with the # character, so ITEMNO becomes Item#,and CUSTNO becomes Cust#.

To print no column heading, this segment should contain a single blank character.

The title for repeating fields will include the index in square brackets, as in SELECTCODE[3].

When using the [ALL] option with a field that has 12 elements, you may specify a title in DISP$ of Mth to use the three letter month abbreviations, or Month to use the full name months in the title.

Note when printing to a file, which can be opened with a spreadsheet, the default title is the field name and not the title from the template/data dictionary.  This is done so that the first row of data in the file contains valid field names.  You may override the data in the first row by specifying a title in Segment 2.

Segment 3
Mask
Only needed when you want to override the default mask.  Mask apply to numeric fields, dates, times, and strings.  Note that CDS038 assumes a date field whenever the word DATE is found somewhere in the field name.  See the options segment below for another way to designate a DATE type of field.  The mask can be in the N7.2 format as well to provide a floating decimal point.  String variables can be truncated using a mask such as XXXXXX which would only print the first 6 characters of a string field.

The default mask is derived from either the data dictionary or the template 'omask' user field in the template.

Numeric masks can be typical masks such as ###,###.00CR, -#,###,##0 or floating decimal masks in the format N7.2 which will assume a field width of 7 characters with up to 2 decimal positions.

Date and time masks can be any format supported by the BBx DATE() function such as "%Dl, %Ml %D, %Yl" or "%Mz/%Dz/%Yl" or "%hz:%mz %p".  Note that CDS038 assumes that a field is a date if it is a numeric field in U(3) or N(7) format, and the field name contains the word DATE.  You may also notify CDS038 that a field is a date by using the d option in Segment 5.  CDS038 assumes a field contains a time in the same format has the BBx TIM system variable, if the template field is type B, and the field name contains the word TIME.  You may also notify CDS038 that a field is a time by using the t option in Segment 5.

String Masks are similar to those used in the STR() BBx function, but can also be used to truncate the field to print only the first X characters.  For example, a mask of XXXX will only print the first four characters of the field.

CDS038 will not stop the report with an error if a field does not fit in its mask.  Instead, it will attempt to place the data unmasked into the space available for the field.  If this cannot be done then the field will appear as all asterisk (*) symbols.

For string variables, segment 3 can also be used for a sub-string expression, instead of a mask.  For example, the mask segment could contain (1,10) or (5,10) or (5).

Segment 4
Position
Normally CDS038 places each field to the right of the previous field with a single space separator.  When the line fills up, it will continue placing fields on the next line.  You can override this behavior by including positioning information in this optional segment.

If you want to place a field at a particular column and row, then you can specify COLUMN,ROW in segment 4.  The leftmost column is 0, and the top row is 0.  For example, a DISP$ of "DESC1\Description\50,0" will cause the ITEMNO field to be displayed at column 50 on the top line of output.  Note, then when you use the positioning segment, be careful not to print multiple fields in the same place on the report.

You may specify a row with a null column such as ",2" to indicate the current column at row 2.

You may also specify a field name instead of the column, which is used to place one field below another, as in "DESC2\ \\DESC1,1".  This will place DESC2 on the second line below the field named DESC1.  The field name may optionally include the file name or external routine name, and the array index.  DESC1, DIS123.LSTRECDAT, PRICE[5], and DIS123.PRICE[5] are all valid field names to determine print column.

CDS038 processes DISP$ in order, so the sequence that the fields appear in DISP$ are significant.  If DISP$ contains "ITEMNO|DESC1\Description|DESC2\ \\DESC1,1|QTY|COST" then QTY and COST will appear to the right of DESC1 on the first line.  Fields without positioning expressions will be placed after the last field placed on the same line.  You can override this behavior and have fields without positioning expressions placed after the current field by using a negative indicator before the ROW.  For example if DISP$ contains "ITEMNO|DESC1\Description|DESC2\ \\DESC1,-1|QTY|COST" then QTY and COST will be on the second line to the right of DESC2.

Note that whether the position option is used or not, any detail line that is completely blank will not be printed.  This means that if DESC2 is printed on a line by itself below DESC1, and DESC2 is null or all blank, the blank line will not be printed.

Segment 5
Options
This segment can contain one or more of the codes described below in any sequence.
CodeUseDescription
TTotalIf the Option segment contains a T, and the field is numeric, and output is not to a file, then this field will be totaled. Subtotals may also be printed when using a SORTBY clause.  If the field is too large for the mask, then as many digits of the unmasked total will print as fit. If no mask is specified, as in an N5 format, then the total field will be all * symbols, if the total does not fit in the column.
SSub-TotalPrint sub-totals, but not totals.  This may be needed when there is already a summary section of the data that includes totals.
BBlank FieldIndicates that this field should not be printed if it the same as the record previously printed on the same page.  For example, on a listing of sales orders by customer, you may want to suppress the customer name on all but the first order for the customer.  Note that CDS038 will reprint fields coded with a B on the first line of each page.
O
(Letter)
OmitThis column will not print, but can used and totaled for _GM, _GM%, _CHG% and _%PCT calculations.  Be sure to include the T option as well so that the column can be totaled for use in the calculations.
dDate FieldIndicates that this is a date field and should be converted to a julian date and presented using a DATE() mask. The mask of MM/DD/YY will be used if not specified. This option is assumed if the field name includes the word DATE and the template field is either U(3) or N(7).  The date may be in any format supported by CDS055 including MM/DD/YY, YYMMDD, julian in N(7) or U(3) format, or Microsoft Excel format, etc.
tTime FieldIndicates that this is a time field in the hour and fractional hour format like the BBx TIM system variable, and should be presented using a mask provided with the DATE() function mask. The mask of HH:MM xM will be used if not specified. This option is assumed if the field name includes the word TIME and the template field is type B.  Time fields require a range of 0 (12:00am) to 23.99999 (11:59pm).  Elapsed time that exceeds 24 hours is indicated by a mask such as %HH:%mz, %HHH:%mz, %HHHH:%mz where the number of H's indicate the number of digits in the hour to display.
bBlank ColumnIndicates the blank column that follows this field should be suppressed, and the next field printed immediately to the right of the previous field. This is useful when combining multiple codes to reduce the columns needed for the report.
zZeroUse for numeric fields to show as blank if the field is zero.
sSkipIndicates that the primary record should be skipped when there are no secondary records meeting the conditions specified by the WHERE clause in segment 6.  If the option letter s is not present, and there are no secondary records meeting the WHERE clause conditions, then the primary record will print and all fields in the secondary record will be left blank.
0
(Number)
Bypass Sub-Total TextNormally the fields that the Sub-Total are based on will be re-printed on the Subtotal line.  For example, if subtotaling by customer#, the customer# will print on the subtotal line.  Placing a 0 (zero) in the options section of the customer# field will suppress the printing of the customer# on the subtotal line.
1-9Print Sub-Total TextIn some cases it is desirable to print additional text on the subtotal line.  For example, when printing subtotals by customer#, the customer# will print on the subtotal line.  To print the customer name on the subtotal line, include the subtotal level number in the options segment.  The first subtotal level is 1.
Segment 6
WHERE
The contents of segment 6 depend on the field type in segment 1.
Segment 1Usage
File nameThis segment is used when there are multiple records from a related file to be printed.  It should contain the WHERE clause used by the SELECT verb to retrieve related records.  If more than one field is to be retrieved from the same file, only the first field in DISP$ for that related file needs this segment.  Any data provided in subsequent fields for the same file will be ignored.  For example, to include all warehouse records for an item and show the warehouse code and quantity on hand,
FILENAME$="XXIM01", DISP$="ITEMNO|DESC1|XXUM21.WHS\\\\\XXUM21.ITEMNO$=IM01.ITEMNO$|XXUM21.QOH".

Versions of CDS038 prior to 9/20/03 require you to use REC. to refer to the fields in the main file, and EXT. to refer to fields in the related file as in:
DISP$= "ITEMNO|DESC1|XXUM21.WHS\\\\\EXT.ITEMNO$=REC.ITEMNO$|XXUM21.QOH"

Although CDS038 continues to support the REC. and EXT. format, the program is more readable when using the actual string field names. You may have multiple related files with WHERE clauses in the same DISP$ string.  But refer to each of them with the same EXT. prefix. Use option letter s described above to skip the primary record when there are no records that meet the conditions of this WHERE clause.
Program nameWhen using externally called programs, normally the primary record is passed as input to the called routine.  This segment can be used to instruct CDS038 to pass one of the related file records to the called routine instead.  Place the file name of the record to be passed in this field, i.e., XXUM21 or UM21.
Segment 7
SORTBY
Segment 7 can contain a SORTBY expression for external file SELECT for segment 6.  This sortby expression has the same characteristics as the main SORTBY$ expression, except that no subtotal /S option may be used.
Segment 8
MODE
Segment 8 can contain a MODE expression for the external file SELECT for segments 6 and 7.  The mode expression has the same characteristics as the main MODE$ parameter described below.  The most popular use is the debug=tmp/selectinfo.txt option to determine if bbx is using an optimized KNUM or reading through the entire external data file.
WHERE$

Use of a WHERE$, SORTBY$, or MODE$ causes CDS038 to use the SELECT verb to open FILENAME$.  The WHERE$ clause can only refer to fields contained within the record.  For example, to include records in file XXCM01 where the SLSMANNO$ field is "123" WHERE$ should be set to "CM01.SLSMANNO$=""123""".  Note that the REC. format required earlier is still supported, i.e., WHERE$="REC.SLSMANNO$=""123""".  Note the need for the pair of quotation marks, when assigning the where clause to a string variable.  Since the program editor can paste field names, the preferred format is CM01. instead of REC.

When a field in the WHERE$ clause refers to a U(), I(), or fixed length N() field within the primary record, use the string representation of the field for best performance.  For example, use "AP23.PMTNO$=AP22.PMTNO$" instead of "AP23.PMTNO=AP22.PMTNO".  As dates are typically stored in U(3) fields, "REC.DATE$>BIN(JUL(2009,10,17),3)" will produce much faster results than "REC.DATE>2455112" if the DATE field is contained with a key segment that will enable bbx to process a part of the file instead of the entire file. 

SORTBY$ Passing a SORTBY$ clause to CDS038 will cause CDS038 to use the SELECT verb to open FILENAME$.  The SORTBY$ clause will sort the data before printing on the report.  You can specify a single field as in CM01.ALPHASORT$ or a combination of fields as in CM01.SLSMANNO$+CM01.ALPHASORT$.

If a field is variable length, then use FILL() with BBx, or PAD() with BBj to extend the field to its maximum size.  For example CM01.NAME$+FILL(30-LEN(CM01.NAME$)).

To sort numeric data, use the ADJN() function as in ADJN(SO60.SALES).  To sort numeric data highest to lowest, negate the numeric field as in ADJN(-SO60.SALES).

SORTBY$ also permits sorting by fields not contained within the primary file FILENAME$.  For example, you are printing customer contact information from file CM03, but want to sort alphabetically using the alpha sort field contained in the customer master file CM01.  Pass FILENAME$="XXCM03", DISP$="CUSTNO|XXCM01.NAME|NAME" and SORTBY$="CM01.ALPHASORT".

The SORTBY$ clause is also used to control subtotals.  Subtotals are requested by placing a /S after each segment of the key where subtotals are desired.  For example, to subtotal by customer within salesman SORTBY$ could contain "REC.SLSMANNO$/S+REC.CUSTNO$/S+REC.SONO$"  Any numeric field that is marked with a T in the options segment of DISP$ will be subtotaled (and totaled). 

A blank line is printed after subtotals are printed. You can have the blank line printed even if no subtotals are required by coding the SORTBY$ clause with the appropriate /S indicator, but not specifying a T in the "Options" segment of any of the fields in the DISP$ clause.

You can also request a new page after printing subtotals by including a P after the /S subtotal indicator as in: REC.SLSMANNO$/SP+ADJN(REC.SALES)

There are some circumstances where you only want sub-totals to print when there are more than 1 line item in the group. You enable this option using a 1 after the /S. With this option, the subtotal and blank line that follows is eliminated when there is only one line item in the group.

Note that subtotals are not yet supported once a function such as NOT() or FILL() or ADJN() or any other supported function is encountered in the SORTBY expression.

MODE$ MODE$ is passed to the SELECT verb.  The most popular use is for creating a log file describing the optimization logic used by SELECT.  To enable this option, pass MODE$ as "debug=tmp/cds038.txt", and a text file will be created with optimization data.  You can review the optimization data to determine how BBx chooses the bests KNUM to use.  You have some options to override the default behavior of BBx by passing "opt=nowhere", "opt=nosort", or "opt=none".  Refer to the BBx documentation for the SELECT verb for additional details.
LIMIT If you only want to include a part of the record set, then pass LIMIT to the number of records desired.  This can be useful in a test environment, or in ranking reports when something like the top 100 customer or items are desired and not the entire list.
SUBHEAD$ an optional heading line that will print at the left margin in bold with one blank line following. This option is useful when multiple CDS038 calls are used to print different details on the same page, and some separator heading is desired.

CDS038 also supports special field names.  These special field names always begin with an underscore (_).  These special fields may be printed on a report, but are excluded when the output to file parameter, S038.WORKFILE$="Y".  They are excluded since there is no true unique field name for these special fields.

CDS038 Special Field Names used in DISP$
_RANK will print the current record number, starting with 1.  It does not reset at subtotals.
_FILL a special field name, most often used to print underlines on a report for handwritten entries.  The size and character to be used are specified using parentheses in the field name in the format: _FILL(size,char) where size is the number of characters, and char is the character to fill with.  For example, to print 10 underlines, the field name would be _FILL(10,_), or to print 6 asterisks would be _FILL(6,*).  The column title should be specified in DISP$ when using _FILL since there is no template to retrieve the column title from.
_GM% can be used to compute gross margin percentage give sales and cost.  If no parameters following _GM% are provided, then CDS038 will assume the sales and cost fields used for the calculation immediately precede the _GM% column. To override this behavior, you may specify the sales and cost fields using _GM%(SALESFLD,COSTFLD) where SALESFLD and COSTFLD refer to the sales and cost field numbers as referenced within DISP$. The first field listed in DISP$ is field number 1, the second 2, etc. Using our example fields SALESFLD as field 1 and COSTFLD as field 2 this field would be _GM%(1,2). Note that both the sales and cost fields must be to the left of the _GM% field in DISP$. Omitted fields (contain an O in the options segment of DISP$) are counted and can be used in the calculation.

The default mask for _GM% is -##.0% if not passed in DISP$.

The default column heading will be GM% if not passed in DISP$.

_GM% can be totaled and subtotaled which causes the calculation to be performed on the appropriate sales and cost amounts, as opposed to adding up the gross margin percentages as would be done with a typical numeric total.

_GM

used to compute Gross Margin (Sales minus Cost). If no parameters following _GM are provided, then CDS038 will assume the sales and cost fields used for the calculation immediately precede the _GM column.  To override this behavior, you may specify the sales and cost fields using _GM(SALESFLD,COSTFLD) where SALESFLD and COSTFLD refer to the sales and cost field numbers as referenced within DISP$. The first field listed in DISP$ is field number 1, the second 2, etc. Using our example fields SALESFLD as field 1 and COSTFLD as field 2 this field would be _GM(1,2). Note that both the sales and cost fields must be to the left of the _GM field in DISP$. Omitted fields (contain an O in the options segment of DISP$) are counted and can be used in the calculation.

The default mask for _GM is -#,###,###.00 if not passed in DISP$.

The default column heading will be Margin if not passed in DISP$.

_GM can be totaled and subtotaled.

_CHG%

can be used to compute the percent change of two amounts.  If no parameters are provided, the TOVAL and FROMVAL will be assumed to be the two columns immediately to the left of the _CHG%.  To override this behavior, specify the values used using _CHG%(TOVAL,FROMVAL) where TOVAL is the more recent value, and FROMVAL is the previous value to which the percent change will be calculated.  The first field listed in DISP$ is field number 1, the second 2, etc.  Note that both the TOVAL and FROMVAL fields must be to the left of the _CHG% field in DISP$.  Omitted fields (contain an O in the options segment of DISP$) are counted and can be used in the calculation.

The default mask for _CHG% is -###.0% if not passed in DISP$.

The default column heading will be %Chg if not passed in DISP$.

_CHG% can be totaled and subtotaled which causes the calculation to be performed on the appropriate to and from values, as opposed to adding up the percent changes as would be done with a typical numeric total.

_PCT%

can be used to compute the percentage of one number to another.  If no parameters are provided, the BIGNO and SMALLNO will be assumed to be the two columns immediately to the left of the _PCT%.  To override this behavior, specify the values used using _PCT%(BIGNO,SMALLNO) where BIGNO is the 100% value, and SMALLNO is the value of the percentage to be computed.  PCT%=100*SMALLNO/BIGNO.  The first field listed in DISP$ is field number 1, the second 2, etc.  Note that both the BIGNO and SMALLNO fields must be to the left of the _PCT% field in DISP$.  Omitted fields (contain an O in the options segment of DISP$) are counted and can be used in the calculation.

The default mask for _PCT% is -###.0% if not passed in DISP$.

The default column heading will be % if not passed in DISP$.

_PCT% can be totaled and subtotaled which causes the calculation to be performed on the appropriate to and from values, as opposed to adding up the percent changes as would be done with a typical numeric total.

Example of use of S038.AUTODUP$
The presence of a "B" in the DISP$ options segment normally prevents the printing of a field if is the same as the previous line printed.  In the following example, the item number and description is only printed once and not repeated for each record.  In this example, both the Item# and the Description have a "B" in the DISP$ options segment.

Item#     Description        TransDate  Qty
SH40310   Foreign Car Horn   11/01/04     1
                             11/15/04    15
                             12/01/04     6

The current version of CDS038 will ignore the "B" option and print the field, even if it is the same, when any field already processed in DISP$ with a "B" option differs.  In this example, the Item# changed, so the Description prints even though it is the same as the previous item.

Item#     Description        TransDate  Qty
SH40310   Foreign Car Horn   11/01/04     1
                             11/15/04    15
                             12/01/04     6
SH40320   Foreign Car Horn   10/15/04     2
                             12/10/04     4

Should you require the original logic, that strictly follows the "B" option where a field will not print if it is the same as the previous record, then set S038.AUTODUP$="N".

Item#     Description        TransDate  Qty
SH40310   Foreign Car Horn   11/01/04     1
                             11/15/04    15
                             12/01/04     6
SH40320                      10/15/04     2
                             12/10/04     4

Example using Called Program
The B in the Options slot after IM521.PCT and IM521.DESC suppresses the re-printing of the same information, except at the top of a new page.
0100 REM "IM520 - 01/31/08 Product Class Listing
0110 SETERR 8000; SETESC 8000
0120 LET FILENAME$="XXUM27"
0130 LET DISP$="IM521.PCT\\\\B|IM521.DESC\\\\B|PCL|DESC|PCLRENT|PCLUSED"
0140 CALL "CDS038",Y$,Y5$,Y5A$,Y6$,Y6,L,P,S038$,FILENAME$,KNO, KEYBEGIN$,KEYEND$,DISP$,WHERE$,SORTBY$,MODE$,LIMITVAL,SUBHEAD$
0150 GOTO EOJ
Program IM521 is used to obtain the Product Category record.  The template for IM521$ is the same as that of the Product Category record UK26$.
0100 REM "IM521 - 01/31/08 Return Product Category Record
0110 SETESC 8000; SETERR 8000
0120 ENTER Y$,UM27$,IM521$
0130 CALL "SW001","XXUK26",0,UM27.PCL$(1,1),IM521$,SW001$
0140 EXIT
Click for example output
Example creating a tab delimited spreadsheet file
0100 REM "Example

0110 CALL "CDS041","CDS084",S084$,"YY"; REM "Get template for CDS084 parameters
0120 LET S084.MODE$="N",S084.NAME$="PFIL"; REM "No entries, output to text file
0130 CALL "CDS084",Y$,Y5$,U0,S084$,Y6,Y6$; REM "Define output file
0140 CALL "CDS038",Y$,Y5$,Y5A$,Y6$,Y6,L,P,S038$,"CDSM01",0,"","","LOGINID|NAME"; REM "Send tab delimited data to file
0150 CALL "CDS094",Y6$,"E"; REM "Close the print channel/spreadsheet file and open spreadsheet application (if possible)

Same as above example, but run from Dynaweb
0100 REM "Example

0110 CALL "CDS041","CDS084",S084$,"YY"; REM "Get template for CDS084 parameters
0120 LET S084.MODE$="N",S084.NAME$="PFIL"; REM "No entries, output to text file
0130 CALL "CDS084",Y$,Y5$,U0,S084$,Y6,Y6$; REM "Define output file

0140 CALL "CDS041","CDS038",S038$,"YY"; REM "Get template for CDS038

0150 LET S038.KEEPOPEN$="Y"; REM "Need to keep printer channel open so that Y6.FILEOUT contains the .xls file name
0160 CALL "CDS038",Y$,Y5$,Y5A$,Y6$,Y6,L,P,S038$,"CDSM01",0,"","","LOGINID|NAME"; REM "Send tab delimited data to file

0170 LET TMP$="",TMP$=STBL("$bodyopt",ERR=0180); REM "Retrieve existing body tag options (if any)
0180 LET TMP$=STBL("$bodyopt",TMP$+" onload=""window.open('"+Y6.FILEOUT$(POS("/
tmp/"=Y6.FILEOUT$))+"','','location=no,menubar=no,resizable=no,status=no,
height=100,width=500,titlebar=no,toolbar=no')"""); REM "Download or Open the spreadsheet file when the next page is sent to the browser
0190 CALL "CDS094",Y6$,"e"; REM "Close the print channel/spreadsheet file, but do not launch application

0200 LET HTML$="Requested spreadsheet has been generated."; REM "This could be a menu or whatever page you want to display after the spreadsheet file has been created.

0210 RUN "CDW999"; REM "Send HTML$ to browser

Notes
  1. This requires that the tmp folder below the web server's Document Root folder be linked to the Dynamo Tools tmp folder.
    Example to create this link: ln -s /u/CDI/tmp /var/www/html/tmp
  2. If using security enhanced linux (SElinux), the security context of the tmp folder should be set to httpd_sys_content_t.  Example:
    semanage fcontext -f -d -a -t httpd_sys_content_t /u/CDI/tmp
    restorecon -v /u/CDI/tmp
  3. Some browsers block pop-up windows by default, but can typically be configured to allow pop-ups from selected web sites.
  4. Although the spreadsheet file can be downloaded to the workstation, the process varies somewhat by broswer.  In some cases the spreadsheet file is automatically downloaded.  Other browsers ask to Open or Save.  Other browsers open an empty window with a notification that the file has been downloaded.