Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Control Breaks

Status
Not open for further replies.

3gm

Programmer
Mar 7, 2001
437
US
I am managing a group of mixed contractors/employees doing new development and maintenance in COBOL (APS really) on an IBM z/OS system. There seem to be several different ways that our group is handling/has handled multi-level control breaks in report programs.

I long ago settled on what I consider to be a superior method that allows me to write control break code quickly, easily, and (almost) bug-free. I am curious though about the experience of this group. Do you have a standard way of handling control breaks? Can you point me to online or print resources that describe your technique? I'd like to share this information with my group in hopes of coming up with a standard or at least raising awareness of alternate techniques.

Thanks.

Glenn
 
I've encountered two ways people have done it. The first was okay, but much less efficient than the second. The one I've settled on involves moving through records by looping on each control variable until the value changes and then doing the C/B change. The other one, which was taught in my first COBOL class (13 years ago!) involved looping through the records with IF statements for the breaks.

Any method can be applied but the keys are ease of maintenance, performance (yes the initial way I rejected was on the order of seconds/minutes worse as you can guess), and uniformity. For how I do it, I've come to like it best, and no one has exactly showed me a third way yet.

I don't have any code samples in front of me right now for you (long time since I wrote report programs so I'd have to look a while in my backups), but I could go look when I get the chance and see what kind of source I have handy.
 
Glenn9999-

Thanks.

I'm not quite sure I understand. I think you're saying your preferred method involve PERFORM UNTIL control break change and the other method involves setting/testing some switches with IF statements?

Any clarification or examples would be appreciated.

Glenn
 
I would get in a loop until my input file is empty. I would use either IF statemetns or an EVALUATE to check for breaks, checking the most major break first.
Code:
EVALUATE TRUE
    WHEN COMPANY NOT = SA-COMPANY
        PERFORM 9100-PRINT-COMPANY-TOTAL
    WHEN DIVISION NOT = SA-DIVISION
        PERFORM 9120-PRINT-DIVISION-TOTAL
    WHEN STATE NOT = SA-STATE
        PERFORM 9140-PRINT-STATE-TOTAL
END-EVALUATE
PERFORM 9100-PRINT-DETAIL-LINE

Each control break paragraph would perform the break "below" it. For example:

Code:
9100-PRINT-COMPANY-TOTAL.
    PERFORM 9120-PRINT-DIVISION-TOTAL

    code here to print the company total, add the company total to the final totals, and zero the company totals

9120-PRINT-DIVISION-TOTAL.
    PERFORM 9140-PRINT-STATE-TOTAL

    code here to print the division total, add division totals to company totals, and zero the division totals
 
Here's method #1 I was taught, all the IF statements. Seems real similar to what Kenny posted. All the breaks are in order from major to minor, if I recall this program correctly.

Code:
PROCEDURE DIVISION.          
OUTPUT-DRIVER SECTION.     
   PERFORM 100-INIT.
   PERFORM 200-WORK UNTIL EOF = 'Y'.
   PERFORM 300-WRAP.
OUTPUT-DRIVER-END SECTION.

200-WORK.         
   IF HOLD-AGENCY-NO NOT = F1WK-AGENCY-NO
      PERFORM 220-AGENCY-BREAK
      PERFORM 110-WRITEHEADER-1
      PERFORM 120-WRITEHDRS1
      PERFORM 130-WRITEHDRS2
   END-IF.
   IF HOLD-IR-NO NOT = F1WK-IR-NO
      PERFORM 230-IR-BREAK
   END-IF.
   IF HOLD-ST-PROV-CODE NOT = F1WK-ST-PROV-CODE
      PERFORM 240-ST-PROV-BREAK
   END-IF.
   IF LINE-COUNT > 49
      PERFORM 110-WRITEHEADER-1
      PERFORM 130-WRITEHDRS2
      PERFORM 205-MOVEALL
   END-IF.
   PERFORM 210-MOVEWRITE.
   RETURN SRT-FILE AT END MOVE 'Y' TO EOF.
 
Here's something we do in report programs to have a real straight forward way to get the headers produced.

Code:
01  ACCUMULATOR-AREAS                PACKED-DECIMAL.
    03  AA-LINE-COUNT  VALUE +999         PIC S9(03).
        88  AA-FULL-PAGE
                       VALUES +56 THRU +999.



9000-WRITE-A-LINE.
    IF AA-FULL-PAGE
        MOVE O-REPORT-LINE    TO SA-REPORT-LINE
        PERFORM 9020-WRITE-HEADERS
        MOVE SA-REPORT-LINE   TO O-REPORT-LINE
    END-IF
    PERFORM 9040-WRITE.
9020-WRITE-HEADERS.
    MOVE HEADER-1             TO RLO-DATA
    WRITE O-REPORT-LINE
        AFTER ADVANCING PAGE
    MOVE +1                   TO AA-LINE-COUNT
    SET RLO-DOUBLE-SPACE      TO TRUE
    MOVE HEADER-2             TO RLO-DATA
    PERFORM 9040-WRITE 
    more code here to write the rest of the headers
9040-WRITE.
    EVALUATE TRUE
        WHEN RLO-SINGLE-SPACE
            ADD +1            TO AA-LINE-COUNT
        WHEN RLO-DOUBLE-SPACE
            ADD +2            TO AA-LINE-COUNT
        etc
    END-EVALUATE
    WRITE O-REPORT-LINE
        AFTER ADVANCING RPO-CARR-CTL LINES.

Notice with the line count initialized to a value that satisfies the condition AA-FULL-PAGE, the first time we try to write we will print the headers so there is no need for any special first time header printing.

Also if we ever decide that we need to print headers before the next grouping, instead of writing headers after we're done printing a total line, we set AA-FULL-PAGE to TRUE. Then the next time we try to write a line, the page is full and headers are printed.

Whenever we want to allow headers to be printed before a data line, we PERFORM 9000-WRITE-A-LINE. Sometimes we don't want to let a sub-total overflow. In that case we will PERFORM 9040-WRITE. It will count the line printed and print it, but will not check for full page so you are assured the sub-total stays on the same page. You want to make sure the value you set for AA-FULL-PAGE is okay to assure that the line you are printing without overflow won't end up too close to the bottom of the page.




 
The way I was educated:
Code:
01  ksk.
    03 old        pic x(90).
    03 new.
       05 country pic x(30).
       05 city    pic x(30).
       05 street  pic x(30).
000-main.
    perform 010-init-pgm.
    perform 100-main until new in ksk equal high-value.
    perofrm 090-exit-pgm.
    stop run.

100-main.
    perform 110-init-country.
    perform 200-main-country.
    perform 200-main-country until new in ksk (01:30) 
                         not equal old-in ksk (01:30).
    perform 190-exit-country.

200-main-country.
    perform 210-init-city.
    perform 300-main-city.
    perform 300-main-city    until new in ksk (01:60) 
                         not equal old in ksk (01:60).
    perform 290-exit-city.

200-main-city.
    perform 210-init-street.
    perform 300-main-street.
    perform 300-main-street  until new in ksk  
                         not equal old-in ksk        .
    perform 290-exit-city.

300-main-street.
    perform 310-process-record.
    perform 320-readnxt-record.

320-readnxt-record.
    move old in ksk 
      to new in ksk
    read whatever-file next
         at end
            move high-value to new in ksk 
     not at end
            move country in whatever-rec
              to country in new in ksk
            move city    in whatever-rec
              to city    in new in ksk
            move street  in whatever-rec
              to street  in new in ksk
    end-read.
This structure saves yourself an EOF switch.
The "perform X" followed by "perform X until.." looks odd at at 1st, but it is required.

The 010-init-pgm will contain the open of the file and the 1st perform of 320-readnxt-record.
 
There used to be Easy-trieve and Cobol. Easzy-trieve was faster for quickie-reports.... except when yout got strange error codes which were sometimes difficult to deal with.

Also the quickie reports often ended in production, they used more cpu time (I think it was interpretive). Then as time went bye, more stuff got packed into the original pure report programs with the result of getting a greater chance of encountering the strange error codes. At that time often the programs were converted to Cobol....

At some point I had to write a whole lot of report programs and I came up with a program that would read the program source and generate the report logic from special comment lines. Once I had this working I could write report programs faster than using Easy-trieve... and they never needed to be converted to Cobol because the source code was Cobol. I was also possible to add such a report to an existing program. Needless to say the unintended result was that I had to write a whole lot more report programs than I ever intended.

The positive result was that report logic, break logic, company header lines, field titles, field labels were all standardized and anybody could do maintenance. Like, you could add/remove a column, add/remove a total field or a level break by changing just one of these special comment lines.

I still have the assembler source for this Cobol Report Generator.
 
Here's the way I do it.
Code:
01  OLD-KEY.
    05  OLD-MAJOR
        10  OLD-LEVEL-1
        10  OLD-MID
            15  OLD-LEVEL-2
            15  OLD-MINOR
                20  OLD-LEVEL-3

01  NEW-KEY   Same sructure.
. . .
MAINLINE-PROCESS.
    Perform READ-INPUT
    Perform BEGIN-REPORT-PROCESS
    Perform Until Eof
        Perform NEW-MAJOR-PROCESS
        Perform Until NEW-KEY not = OLD-KEY
            Perform NEW-MID-PROCESS
            Perform Until NEW-MID not = OLD-MID
                Perform NEW-MINOR-PROCESS
                Perform Until NEW-MINOR not = OLD-MINOR
                    Perform DETAIL-PROCESS
                    Perform READ-INPUT
                End-Perform
                Perform END-MINOR-PROCESS
            End-Perform
            Perform END-MID-PROCESS
        End-Perform
        Perform END-MAJOR-PROCESS
    End-Perform
    Perform END-REPORT-PROCESS
    .

READ-INPUT.
    Move NEW-KEY to OLD-KEY
    Read Input File
        At End 
            Move High-Value to NEW-KEY
            Exit Paragraph
    End-Read
    build NEW-KEY
    .
Note that this can be extended to as many levels as needed. I rarely use more than three.
 
Hi Glenn,

Here's a link to a FAQ I did a long time ago. It's pretty basic - good for beginners. Don't know if will serve your needs.



Regards, Jack.

"A problem well stated is a problem half solved" -- Charles F. Kettering
 
P.S.

It's easier to read if you cut&paste it into a .txt file.

Regards, Jack.

"A problem well stated is a problem half solved" -- Charles F. Kettering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top