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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to code control breaks?

Conditionals

How to code control breaks?

by  slade  Posted    (Edited  )
This problem represents a major construct in business
programming, so the time you devote to this is well spent.

Input data is usually presented to a pgm in some sort sequence, e.g:

Code:
                    file
                      acct#1
                        product1
                          date1
                          date2
                          etc.
                        product2
                          date1
                          date3
                          date4
                          etc.
                      acct#2
                        product1
                          date3
                          etc.

So you have a file level, an acct level, a product level and a date level. These levels are important because they are used to process the breaks in the program.

The general form is as follows:

perform level n until level n-1 is finished

For the file described above the perform sequence would be:

In the mainline you code:
perform acct-lev until file-is-finished
In the acct-lev you code:
perform prod-lev until acct-is-finished
In the prod-lev you code:
perform date-lev until prod-is-finished
In the date-lev you code:
perform detl-lev until date-is-finished
In the detl-lev you code:
Aggregate all detl recs; aggregate all level
totals; etc. Read next I/P det lrec.

OK now lets flesh this out. How do we determine when each level is finished? One way is to expand the function of the read routine to do this:
Code:
         7000-read-rtn.
             move ws-ip-rec to ws-ip-prev
             read ip-file into ws-ip-rec 
               at end set ip-eof to true 
                  move high-values to ws-ip-rec  
              not at end add +1 to ws-ip-cnt
             end-read
             perform 7010-set-breaks
             .
         7010-set-breaks.
             if curr-acct not = prev-acct
                set acct-is-finished to true
                set prod-is-finished to true 
                set date-is-finished to true
             end-if
             if curr-prod not = prev-prod
                set prod-is-finished to true
                set date-is-finished to true
             end-if
             if curr-date not = prev-date
                set date-is-finished to true
             end-if

Second question: We haven't read any data yet, how can we test if the levels are finished? We do a priming read outside of the loops, usually in the init or mainline section. After this read, if EOF is detected, an error msg is displayed and the pgm is usually exited because no input data has been provided.

How can the loops be executed if the "is-finished" switch has already been set? They can't. So, we reset the switch before executing each lower level:
Code:
       0000-main-line.
           perform 7000-read-ip
           if ip-eof
              display error msg
              stop run
           end-if 
           perform 1000-acct-lev 
             until file-is-finished
           perform 6900-print-rpt-end
           perform 9000-end-it
           stop run
           .
       1000-acct-lev.
           perform 6000-print-rpt-heads
           set reset-acct-sw to true 
           perform 2000-prod-lev 
             until acct-is-finished
           perform 6100-print-acct-tots 
           zero tots, etc. 
           .
       2000-prod-lev.
           set reset-prod-sw to true 
           perform 3000-date-lev 
             until prod-is-finished
           . 
       3000-date-lev.
           set reset-date-sw to true 
           perform 4000-detl-lev 
             until date-is-finished
                        . 
       4000-detl-lev.
           move ip data to rpt-line or whatever
           perform 7000-read-ip
           .

Note that the form of each level except the detail level is:

Do pre-break stuff (print rpt heads, save data that won't be available after return from perform, etc.)

Reset the level switch.

Perform the next lower level.

Do post-break stuff (strike and/or zero or roll totals, write total recs, etc.)

At the detail level process the previous rec and read the next rec before exiting.

At entry to each level the record has already been read and is ready for processing.

Here's what a break switch would look like:


Code:
     01 ws-break-switches.
        05 ws-acct-sw                 pic x(001).
           88 acct-is-finished            value 'F'.
           88 reset-acct-sw               value 'R'.

This example has 2 break levels so your performs would look like:
Code:
       0000-mainline.
           . 
           . 
           .
           perform 8000-init
           perform 7000-read-ip 
           if ip-eof 
              display 'no data in i/p file' 
              stop run 
           end-if
           perform 1000-process-codes 
             until ip-eof
           . 
           . 
                        . 
       1000-process-codes.
           set reset-code-sw to true
           perform 1100-process-detl 
             until code-is-finished
           .
       1100-process-detl.
           collect data, etc.
           perform 7000-read-ip
           .
You have to ask: What do I do before the breaks; what do I do after. The answers to these questions may differ from project to project, but the basic concept: the cascading perform process is constant.

There are are other slightly more efficient ways of solving this problem but I tried to keep my version as "readable" as possible. If you do a keyword search on "construct" you will find them discussed in the thread started by "slade".

This is one of the two major batch processing constructs in DP. The other is the file match. When I get some time I'll post something on this.

Let me know if this helps or if you have any questions.

Jack
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top