03 StateBranchCount PIC 9(5).
Multidimensional Program
Listing 11-3 is a solution to the changed specification that uses the two-dimensional table described in Example 11-5.
Listing 11-3. Using a Two-dimensional Table to Solve the Problem Posed by the Changed Specification IDENTIFICATION DIVISION.
PROGRAM-ID. Listing11-3.
AUTHOR. Michael Coughlan
* Program that for each state and for the whole US
* sums the Monthly Sales for each branch of YoreCandyShoppe, counts the number of
* branches and displays the State Sales per month in StateNum order
* Calculates the US sales, the number of branches in the US and the average US sales
* Uses as input the Sequential BranchSalesFile ordered on ascending BranchId
257
Chapter 11 ■ Creating tabular Data
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT BranchSalesFile ASSIGN TO "Listing11-3BranchSales.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD BranchSalesFile.
01 BranchSalesRec.
88 EndOfSalesFile VALUE HIGH-VALUES.
02 BranchId PIC 9(7).
02 StateNum PIC 99.
02 SalesForMonth PIC 9(5)V99 OCCURS 12 TIMES.
WORKING-STORAGE SECTION.
01 StateSalesTable.
02 State OCCURS 50 TIMES.
03 StateBranchCount PIC 9(5).
03 StateMonthSales PIC 9(5)V99 OCCURS 12 TIMES.
01 ReportHeading.
02 FILLER PIC X(20) VALUE SPACES.
02 FILLER PIC X(38) VALUE "YoreCandyShoppe Monthly Sales by State".
01 ReportUnderline.
02 FILLER PIC X(20) VALUE SPACES.
02 FILLER PIC X(38) VALUE ALL "-".
01 ReportSubjectHeadings1.
02 FILLER PIC X(12) VALUE "State NOBs".
02 FILLER PIC X(63)
VALUE " Jan Feb Mar Apr May Jun".
01 ReportSubjectHeadings2.
02 FILLER PIC X(12) VALUE SPACES.
02 FILLER PIC X(63)
VALUE " Jul Aug Sep Oct Nov Dec".
01 DetailLine1.
02 PrnStateNum PIC BZ9.
02 PrnBranchCount PIC BBZZ,ZZ9.
02 PrnMonthSales1 PIC B$$$,$$9.99 OCCURS 6 TIMES.
01 DetailLine2.
02 FILLER PIC X(11) VALUE SPACES.
02 PrnMonthSales2 PIC B$$$,$$9.99 OCCURS 6 TIMES.
258
Chapter 11 ■ Creating tabular Data
01 US-Totals.
02 US-TotalSales PIC 9(9)V99.
02 US-BranchCount PIC 9(6).
02 PrnUS-TotalSales PIC $,$$$,$$$,$$9.99.
02 PrnUS-BranchCount PIC B(9)ZZZ,ZZ9.
02 PrnUS-AverageSales PIC BB$$$,$$$,$$9.99.
01 StateIdx PIC 99.
01 MonthIdx PIC 99.
PROCEDURE DIVISION.
Begin.
MOVE ZEROS TO StateSalesTable
OPEN INPUT BranchSalesFile
READ BranchSalesFile
AT END SET EndOfSalesFile TO TRUE
END-READ
PERFORM UNTIL EndOfSalesFile
ADD 1 TO StateBranchCount(StateNum), US-BranchCount
PERFORM VARYING MonthIdx FROM 1 BY 1 UNTIL MonthIdx > 12
ADD SalesForMonth(MonthIdx) TO
StateMonthSales(StateNum, MonthIdx), US-TotalSales
END-PERFORM
READ BranchSalesFile
AT END SET EndOfSalesFile TO TRUE
END-READ
END-PERFORM
PERFORM DisplayResults
CLOSE BranchSalesFile
STOP RUN.
DisplayResults.
DISPLAY ReportHeading
DISPLAY ReportUnderline
DISPLAY ReportSubjectHeadings1
DISPLAY ReportSubjectHeadings2
PERFORM VARYING StateIdx FROM 1 BY 1
UNTIL StateIdx GREATER THAN 50
MOVE StateIdx TO PrnStateNum
MOVE StateBranchCount(StateIdx) TO PrnBranchCount
PERFORM VARYING MonthIdx FROM 1 BY 1 UNTIL MonthIdx > 6
MOVE StateMonthSales(StateIdx, MonthIdx) TO PrnMonthSales1(MonthIdx)
END-PERFORM
PERFORM VARYING MonthIdx FROM 7 BY 1 UNTIL MonthIdx > 12
MOVE StateMonthSales(StateIdx, MonthIdx) TO PrnMonthSales2(MonthIdx - 6)
END-PERFORM
DISPLAY DetailLine1
DISPLAY DetailLine2
DISPLAY SPACES
END-PERFORM
259
Chapter 11 ■ Creating tabular Data
MOVE US-TotalSales TO PrnUS-TotalSales
MOVE US-BranchCount TO PrnUS-BranchCount
COMPUTE PrnUS-AverageSales = US-TotalSales / US-BranchCount
DISPLAY "YoreCandyShoppe branches in the US = " PrnUS-BranchCount
DISPLAY "YoreCandyShoppe sales in the US = " PrnUS-TotalSales
DISPLAY "YoreCandyShoppe average US sales = " PrnUS-AverageSales.
Correct Depiction of COBOL Tables
Two-dimensional tables are often depicted using a grid of rows and columns. This is an accurate representation for arrays, but for COBOL tables it has the flaw that it does not accurately reflect the data hierarchy.1
The table described in Example 11-5 allows you to manipulate the table using statements such as MOVE ZEROS
TO State(1) and MOVE 123 TO BranchCount(2). In a row-and-column grid depiction, it is not clear how such
manipulations are possible.
The diagram in Figure 11-3 uses the correct representation for StateSalesTable. This diagram expresses the data hierarchy inherent in the table description where one OCCURS clause is subordinate to another. With this representation, you can see how statements such as MOVE ZEROS TO State(1) and MOVE 123 TO StateBranchCount(2) affect the
values in the table.
Figure 11-3. Diagram showing the hierarchy in a COBOL table description
Three-Dimensional Tables
In COBOL, multidimensional tables rarely have more than three dimensions. Prior to the ANS 85 version of COBOL, a maximum of three dimensions were permitted; the restriction on PERFORM..VARYING that allows only three
counting variables harks back to those days. In the ANS 85 and ISO 2002 COBOL standards, the maximum number of dimensions is seven.
A discussion of how three-dimensional tables are created and processed should help to solidify your
understanding of multidimensional tables. This time, however, I present the problem specification and show the declarations necessary to create the three-dimensional table, but I don’t write a full program. I leave that as an exercise for you at the end of the chapter.
Keep in mind that this specification is designed with an eye toward what is easy to present diagrammatically rather than toward realism.
260
Chapter 11 ■ Creating tabular Data
Problem Specification
The U.S. Census Bureau has provided you with a subset of census data in a file containing the age category, gender, state number, and car-ownership information of every person in the country. The CensusFile is an unordered sequential file, and its records have the following description:
Field
Type
Length
Value
StateNum
9
2
1–50
AgeCategory
9
1
1 = Child
2 = Teen
3 = Adult
GenderCategory
9
1
1 = Female
2 = Male
CarOwner
X
1
Y or N
You are required to write a program to process the CensusFile and display the number of males and females in each AgeCategory (Child, Teen, and Adult)
in each state, as shown in Figure 11-4.
Figure 11-4. Report template
To accumulate the population totals for each state, you use the three-dimensional table defined in Example 11-7.
Example 11-7. Three-dimensional Table to Hold Population Totals
01 US-PopulationTable.
02 State OCCURS 50 TIMES.
03 AgeCategory OCCURS 3 TIMES.
04 GenderCategory OCCURS 2 TIMES.
05 PopTotal PIC 9(8).
For each record that you read from the CensusFile, you execute the following statement:
ADD 1 TO PopTotal(StateNum, Age, Gender)
261
Chapter 11 ■ Creating tabular Data
Depicting a Three-dimensional Table
Figure 11-5 is a depiction of the three-dimensional table defined in the Example 11-7.
Figure 11-5. Structure of a three-dimensional table
The data in the table has been changed by executing the following statements:
MOVE ZEROS TO State(1)
MOVE ZEROS TO AgeCategory(2,3)
MOVE ZEROS TO GenderCategory (3,1,1)
MOVE ZEROS TO PopTotal(2,1,2)
MOVE 156 TO PopTotal(2,2,2)
As you can see from these statements, the data names defined in the table allow you to manipulate the table at various levels of granularity. When you refer to the State data item, you must use one subscript because it is a data item whose description contains an OCCURS clause. When you refer to AgeCategory, you must use two subscripts because AgeCategory is subordinate to an item that contains an OCCURS clause, and it itself contains an OCCURS
clause. Finally, when you refer to GenderCategory and PopTotal, you must use three subscripts: GenderCategory is subordinate to two items that contain an OCCURS clause, and it contains an OCCURS clause itself; and PopTotal is subordinate to three items that contain an OCCURS clause. PopTotal and GenderCategory are data names that refer to the same area of storage. The US-PopulationTable could have been defined as
01 US-PopulationTable.
02 State OCCURS 50 TIMES.
03 AgeCategory OCCURS 3 TIMES.
04 GenderCategory PIC 9(8) OCCURS 2 TIMES.
However, the PopTotal data item was added for clarity, as documentation.
Prefilled Tables
In all the examples in this chapter, the table used has been filled with data in the course of running the program.
Sometimes, however, the table needs to be prefilled with data values. When the program starts, the table must already have been instantiated with the data values.
For instance, in Listing 11-3, when you display the results, you display a state number instead of the name of the state. Obviously it would be better to display the actual state name. A simple way to do this is to set up a prefilled table containing the names of the states and then display the appropriate name using a statement such as DISPLAY
StateName(StateIdx).
262
Chapter 11 ■ Creating tabular Data
REDEFINES Clause
To set up a prefilled table in COBOL, you have to use a special data-description clause called the REDEFINES clause.
The REDEFINES clause is not limited to creating prefilled tables. It is a powerful data-manipulation language element that is used for a number of purposes. I discuss the REDEFINES clause in detail in Chapter 12, including its full syntax, the semantic rules that apply to it, and the many ways it may be used. In this chapter, I discuss the REDEFINES clause only in the context of creating prefilled tables.
When a file contains different types of records, a record description is created for each record type in the FILE
SECTION. However, all these record descriptions map on to the same area of storage. They are, in effect, redefinitions of the area of storage. The REDEFINES clause allows you to achieve the same effect for units smaller than a record and in the other parts of the DATA DIVISION—not just the FILE SECTION.
Creating Prefilled Tables of Values
You can use the REDEFINES clause to create a prefilled table by applying the following procedure:
1. Reserve an area of storage, and use the VALUE clause to fill it with the values required
in the table.
2. Use the REDEFINES clause to redefine the area of memory as a table.
For instance, to create a table prefilled with the names of the months, the first step is to reserve an area of storage and fill it with the names of the months (see Example 11-8). The diagram in Example 11-8 depicts the undifferentiated area of storage filled with the month names.
Example 11-8. Setting Up an Area of Storage Containing the Month Names
01 MonthTable.
02 MonthValues.
03 FILLER PIC X(18) VALUE "January February".
03 FILLER PIC X(18) VALUE "March April".
03 FILLER PIC X(18) VALUE "May June".
03 FILLER PIC X(18) VALUE "July August".
03 FILLER PIC X(18) VALUE "SeptemberOctober".
03 FILLER PIC X(18) VALUE "November December".
The next step is to redefine the area of storage to impose a table definition on it, as shown in Example 11-9.
Now MonthName(3) contains the value "March", and MonthName(6) contains "June".
Example 11-9. Redefining the Area of Storage as a Table
01 MonthTable.
02 MonthValues.
03 FILLER PIC X(18) VALUE "January February".
03 FILLER PIC X(18) VALUE "March April".
03 FILLER PIC X(18) VALUE "May June".
03 FILLER PIC X(18) VALUE "July August".
03 FILLER PIC X(18) VALUE "SeptemberOctober".
263
Chapter 11 ■ Creating tabular Data
03 FILLER PIC X(18) VALUE "November December".
02 FILLER REDEFINES MonthValues.
03 MonthName OCCURS 12 TIMES PIC X(9).
Creating a Prefilled Two-dimensional Table
To set up a two-dimensional table prefilled with data values, you use the same procedure as for a one-dimensional table. First you create an area of storage that contains the values you want in the table, and then you redefine the area as a table.
Suppose a company pays a bonus depending on ServiceCategory and MaritalStatus, as shown in Table 11-1.
You can set up a prefilled table as shown in Example 11-10. In this table, Bonus(4,1) = 135 and Bonus(2,2) = 085.
The data items MaritalStatus and Bonus refer to the same area of storage. The Bonus data item has been added for purposes of clarity.
Table 11-1. Bonus Table
Service Category
5–10 years
11–20 years
21–30 years
30–50 years
Single
050
085
100
135
Married
075
120
150
175
Example 11-10. Two-dimensional Bonus Table
01 BonusTable.
02 BonusValues PIC X(24) VALUE "050075085120100150135175".
02 FILLER REDEFINES BonusValues.
03 ServiceCategory OCCURS 4 TIMES.
04 MaritalStatus OCCURS 2 TIMES.
05 Bonus PIC 9(3).
Prefilled Table Program
The program in Listing 10-1 in Chapter 10 implemented a three-level control break. In the discussion of that program, I noted that in order to reduce the amount of storage occupied by the data file, the normal practice would be to use a state number instead of a state name. I mentioned that in such a program, when it is necessary to print out the state name, the state number is converted to a name by means of a lookup table.
264
Chapter 11 ■ Creating tabular Data
So let’s write a program to the same specification as Listing 10-1, except that now the records in the Sales file should use a state number rather than the full state name. The revised program specification follows.
R
evised Specification
Electronics2Go has branches in a number of American states. A program is required to produce a report showing the total sales made by each salesperson, the total sales for each branch, the total sales for each state, and a final total showing the total sales for the entire United States. The report must be printed by ascending SalespersonId within ascending BranchId within ascending StateName.
The report is based on the Electronics2Go sales file. This file holds details of sales made in all the branches of the company. It is a sequential file, ordered on ascending SalespersonId within ascending BranchId within ascending StateNum. Each record in the sales file has the following description:
Field
Type
Length
Value
StateNum
9
2
01–50
BranchId
X
5
-
SalespersonId
X
6
99999X (M/F)
ValueOfSale
9
6
0000.00–9999.99
The report format should follow the template shown in Figure 11-6.
Figure 11-6. Template for the Electronics2Go sales report
265
Chapter 11 ■ Creating tabular Data
Final Prefilled Table Program
The program in Listing 11-4 implements the final specification.
Listing 11-4. Report with Three Control Breaks, Using a State Name Table (Changes from Listing 10-1 Shown in Bold) IDENTIFICATION DIVISION.
PROGRAM-ID. Listing11-4.
AUTHOR. Michael Coughlan.
* A three level Control Break program to process the Electronics2Go
* Sales file and produce a report that shows the value of sales for
* each Salesperson, each Branch, each State, and for the Country.
* The SalesFile is sorted on ascending SalespersonId within BranchId
* within StateNum.
* The report must be printed in SalespersonId within BranchId
* within StateName. There is a correspondence between StateNum order
* and StateName order such that the order of records in
* the file is the same if the file is ordered on ascending StateNum
Michael Coughlan Page 33