Using Symbolic Fields for Formatting
Published By | Date | Version | Knowledge Level | Keywords |
---|---|---|---|---|
Revelation Technologies | 08 MAY 1990 | 2.X | EXPERT | FORMATTING, OUTPUT, R/LIST, RLIST, SYMBOLIC |
Under normal circumstances R/LIST displays a record across a page. Each field of the record is a column in the report. If the data in the field contains multivalues, subvalues, or text-mark-delimited data, the column displays a line for each value, subvalue, or line in the text field. Figure 1 shows a simple report that illustrates this output.
This one-record-per-row and one-field-per-column output is easy to create and it is easy for a reader to comprehend. However, there are many times when you may require more complex report formatting. You may be tempted to turn immediately to a more sophisticated report formatting tool such as Merge.
Before abandoning R/LIST, however, you might try using a symbolic field to format your data. By doing so you retain R/LIST's ease of use and flexibility while creating reports that you might not even recognize as having been generated with R/LIST.
Basics of Formatting with Symbolic Fields
The trick to formatting with symbolic fields is that rather than displaying a series of fields as you would normally in R/LIST (example: LIST CUSTOMERS NAME ADDRESS CITY), you consolidate the data to be formatted into a single field (example: LIST CUSTOMERS LABEL_INFO). This single field is a symbolic. The layout of the field its formatting is determined by the formula.
A simple example will illustrate the point. Suppose that you want to create a report in which the information about a customer is displayed in a mailing label format. Define a field that is symbolic and multivalued. Enter a formula like this one:
LABEL ='' LABEL := {FNAME}: :{LNAME} : @VM LABEL := {ADDRESS} : @VM LABEL := {CITY}:, :{ST}: :{ZIP} @ANS = LABEL
The formula extracts the data from the fields FNAME, LNAME, ADDRESS (which is multivalued), CITY, ST, and ZIP, and puts them together in a format that looks like a label. All spacing and punctuation is built in as literal text.
Each line of the label is terminated with a value mark (@VM). R/LIST always prints each value of a multivalued field on a separate line in the column. In effect, you will have created a symbolic multivalued field. Instead of containing, say, a multivalued list of phone numbers, though, it contains a multivalued address.
The output of this field might look like this:
Mary Smith 3633 - 136th Pl SE Suite 200 Bellevue, WA 98006
Formatting Dictionary Records
Since the release of Advanced Revelation 2.0, several users have pointed out that the printer output for the LISTDICT command has changed. To illustrate the range of formatting options available, a symbolic field was created that emulated the output of the older version of LISTDICT.
Note: See Technical Bulletin #51 for details about changes to and customization options for system list reports.
The goal is to create output that looks much like that provided by the old LISTDICT command. For your reference, a sample LISTDICT report from the SAMPLE_INVOICES file is shown in Figure 2.
The specifications for the report are these:
- The dictionary is shown sorted in three levels: by type (F, G, S), by Position (FMC), and by field name.
- F-type fields display these columns for each field: Field Name, Type, Position, Single/Multivalued, Justification, Length, Output format, index information, and a description. (The emulation report includes all these fields except the description.)
- G-type fields display Type and, on a second line, the list of fields represented by the field.
- S-type fields display the same columns as F-type fields, but on subsequent lines they also display the formula.
- The formula in S-type fields has line numbers
- Each G- and S-type field prints a line of dashes to separate it from the field that follows.
Creating the Report
Several of these report specifications are easily handled by R/LIST. For example, R/LIST can sort the fields in a dictionary by dictionary type using the simple BY clause BY TYPE.
The display of information for F-type fields is likewise an easy job for R/LIST. Simply list the fields in an R/LIST report:
LIST DICT.filename TYPE FMC SM JUST LEN
The problem comes in attempting to use R/LIST to display the information for F, G and S-type fields in the same report. Because R/LIST is oriented to columns, it cannot fold the data from separate fields into a column. The solution is to create a single symbolic field that displays the data for all of the fields in the dictionary.
The R/LIST command to create a LISTDICT-like report is thus actually very simple (For this example, the field will be called FIELD_INFO):
LIST DICT.filename BY TYPE BY FMC BY @ID FIELD_INFO
The sorting is handled by a series of BY clauses. There are only two display fields: the key (implied in the command) and FIELD_INFO. All the formatting required for the report is built directly into the FIELD_INFO field.
Create the field FIELD_INFO in the DICT of VOC so that it will be global to all files. Make it symbolic and multivalued. If you want to assign it a data type, you can make it a VARCHAR type.
The justification should be left (L). You have some leeway in assigning a length, but allow at least 65 characters, and more if your printer is wider than 80 columns.
Two field attributes require close attention: the formula and the column heading.
Formula
The formula, which formats the data, is illustrated in Figure 3. Some notes about how the formula was coded:
- The current record is in @RECORD. When listing a dictionary, each field definition is one record. Different fields (positions) within the dictionary record store different field attributes. For example, the first field of a dictionary record contains the dictionary type (F, S, G), while the ninth field of a dictionary record contains that dictionary record's justification.
Note: For more information about the layout of dictionary records, see "Advanced Revelation Dictionaries" in the section Filing Systems. - The formula first evaluates the dictionary type (F, S, or G) and branches to the appropriate logic to format the information for that field correctly.
- Information for F-type fields is displayed on one line by concatenating together all the columns required for the line, much like the mailing label example earlier.
- To format the F-type line properly, each column is assigned a justification and length using this syntax:
@ANS := @RECORD<12> "L#11" : " "
- This method is a shorthand way of using the FMT function, which is used to place data within a field of spaces. In this instance, the data type displays left-justified in a field of 11 spaces. Notice that a space is concatenated onto the end of each field to keep it separate from the data following.
- Indexing information is stored in different locations in the dictionary record. Field 6 contains a 1 if the field has a Btree index on it. Fields 22 and 23 have reference information for Cross-reference and Relational indexing, respectively. If the index positions are blank, no index of that type is active for the field.
- Each time a line break is required in the display, a value mark (@VM) is concatenated onto the end of the line. If there is no value mark, the data is displayed on a single line (as with the line assembled for F-type fields).
- S-type fields display an F-type line followed by the formula. The formula is in field 8 of the dictionary record, with the lines of the formula separated by value marks. The logic to format the formula loops through each value (line) in the formula and concatenates a line number onto the front of the line.
Column Heading
The formula for the field FIELD_INFO produces the correct output for the contents of each field. The original output (from the 1.x LISTDICT command) also had column headings with such labels as "T", "Len", etc., all underlined.
You can achieve a similar result by creating a column heading for the field FIELD_INFO. It helps to know that you can create a two-line column heading in this case, text on the top line, and underline in the second line by putting a value mark between the two lines. The prompt for Column Heading in the Dictionary window is a multivalued prompt.
A sample column heading for the FIELD_INFO field is shown in Figure 4. Although it is not evident from the illustration, the column heading is padded with spaces out to 65 places (the width of the field) to avoid the display of the periods that normally pad a column heading.
Additional Options
You can add other formatting to the report with additional R/LIST options. To put a heading on the report, use an R/LIST HEADING statement. Include the 'F' option to display the filename in the heading. Use DBL-SPC to put a blank line after each field in the report.
You will probably want to limit the report to display only actual field definitions, excluding control records such as %FIELDS% and %PROTECT.SPEC%. To do so, add a WITH clause to the R/LIST statement:
WITH @ID NOT '%]'
A complete R/LIST command to create the report in Figure 2 appears in Figure 5.
Examples
Figure 1
KEY... NAME........ PHONE......... COMMENTS 100 Mary Smith (999) 999-9999 Long-time customer with several installed sites. Interested in becoming a field test site for future products. (800) 565-1234
Figure 2
Dictionary listing for: SAMPLE_INVOICES Date: 03 APR 1990 Page: 1 Field Name T Pos SM Jst Len Data Type Index ----------- - --- -- --- ---- --------- ------ INVOICE_NO F 0 S R 4 INTEGER CUSTOMER_ID F 1 S R 5 INTEGER R DATE F 2 S R 11 DATE B CODE F 4 M L 10 VARCHAR QTY F 6 M R 3 INTEGER COST F 7 M R 9 DOLLARS @CRT G COMPANY_NAME DATE INVOICE_TOTAL BY DATE ---------------------------------------------------------- COST_DFLT S M L 8 Formula: 001 ANS = XLATE("SAMPLE_PRODUCTS", {CODE}, 'RETAIL_PRICE','X') 002 IF ANS THEN 003 @ANS = ANS 004 END ELSE 005 * 006 * get the subscription price. 007 * 008 @ANS = XLATE('SAMPLE_PRODUCTS', {CODE},"SUBSCRIPTION_PR 009 END -------------------------------------------------------------
Figure 3
TYPE = @RECORD<1> * branch to formatting logic that matches the type of the dict item BEGIN CASE CASE TYPE = 'F' GOSUB F_TYPE CASE TYPE = 'G' GOSUB G_TYPE CASE TYPE = 'S' GOSUB S_TYPE END CASE RETURN @ANS F_TYPE: * create a single line with columns for each attribute @ANS ='' @ANS := TYPE 'L#1 ' : ' ' @ANS := @RECORD<2> 'C#3 ' :' ' ; * position (FMC) @ANS := @RECORD<4> 'L#2 ' :' ' ; * single/multi @ANS := @RECORD<9> 'L#3' :' ' ; * justification @ANS := @RECORD<10> 'R#3' :' ' ; * length @ANS := @RECORD<12> 'L#11' :' ' ; * data type * derive index information INDEX ='' IF @RECORD<6> THEN INDEX<1,-1> = 'B' ; * btree IF @RECORD<22> THEN INDEX<1,-1> = 'C' ; * cross-reference IF @RECORD<23> THEN INDEX<1,-1> = 'R' ; * relational CONVERT @VM TO ',' IN INDEX @ANS := INDEX 'L#6' ; * index info RETURN G_TYPE: * put G in the first line, and the field list in the 2nd line @ANS ='' @ANS := TYPE 'L#1' : @VM @ANS := @RECORD<3> : @VM ; * list of field(s) for G-type @ANS := STR(-,65) : @VM ; * add 'underline' beneath field info RETURN S_TYPE: * put F-type columns in the first line, formula in subsequent lines GOSUB F_TYPE @ANS := @VM : @VM ; * extra vm = blank line * format formula with line numbers FORMULA = @RECORD<8> ; * formula is vm-delimited in 8th field of dict record IF FORMULA THEN FORMULA_LINE_CNT = COUNT(FORMULA,@VM)+1 * add line numbers on front of each line FOR CTR = 1 TO FORMULA_LINE_COUNT FORMULA<1,CTR> = ('00':CTR) 'R#3' :' ': FORMULA<1,CTR> NEXT CTR @ANS ='Formula:':@VM:FORMULA:@VM ; * put a label above the formula @ANS := STR('-',65) : @VM END RETURN
Figure 4
T Pos SM Jst Len Data Type Index - --- -- --- --- ----------- -----
Figure 5
LIST DICT.filename FIELD_INFO BY TYPE BY FMC BY @ID WITH @ID NOT '%]' DBL-SPC LPTR HEADING "Dictionary Listing for: 'F' Date: 'DL'Page 'PPL'"