DOCUMENT #719
     =======================================================================
     ONCE-PER-BREAK OPERATIONS
     =======================================================================
     PRODUCT:  R:BASE               VERSION :  3.1 or Higher
     =======================================================================
     CATALOG:  Reports              AREA    :  Breakpoints       
     =======================================================================
 
 
     When you create a breakpoint in a report, R:BASE sorts the column in 
     ascending order to create groups of like values. Break header and 
     footer sections allow you to print information only once for a group 
     of like data values (a break). Many times there is a need to process 
     an expression only once for a break. But report expressions are 
     designed to evaluate for each row from the driving table or view of 
     the report. In other words, expressions will evaluate for each row of 
     data in a break group, not just at the header or the footer. 
 
     R:BASE logical functions are used in expressions to "trick" reports 
     into processing a calculation only once-per-break. The logical 
     function expression is evaluated every row, but it does a comparison 
     which is true only once per break -- at the header or at the footer. 
     Only when the logical function comparison is true is the calculation 
     executed.
 
     Using logical function expressions, you can do these once-per-break 
     operations: 
 
     - Count the number of breaks (different groups of like data values)
     - Add a lookup value once per break.
     - Print a descriptive heading on the first detail row without repeating 
       the heading on every row of detail. 
     - Add a blank line after every five lines of detail.
     - Do calculations, such as a sum, of break footer totals
 
     Most of these operations can be done either at the beginning of the 
     break (header), or at the end of the break (footer). It's faster to 
     do the once-per-break operation at the beginning of the break since 
     there are less expressions to evaluate and the expressions themselves 
     evaluate faster, but some calculations need to be done at the end 
     after all the data for the break has been processed. 
 
     If you choose to evaluate the once-per-break expression at the header 
     (the beginning of the break), you can locate the result in either the 
     header or the footer section. If you choose to evaluate the once-per-
     break expression at the footer (the end of the break) you must locate 
     the result in the break footer. In all cases, SET ZERO ON before 
     printing the report.
 
 
     Count the Number of Breaks
     =============================
     To count the number of breaks (the number of different values in the 
     break column) define these expressions to evaluate at the header:
 
       vcount INTEGER = (.vcount + 1)
       vbnum INTEGER = +
       (IFEQ(.vcount,1,(.vbnum + 1),.vbnum))
 
     Or these expressions to evaluate at the footer:
 
       vcount INTEGER = (.vcount + 1)
       vrowcount = (COUNT(*)) FROM rep_table WHERE break_column=break_column
       vbnum INTEGER = (IFEQ(.vcount,.vrowcount,(.vbnum + 1),.vbnum))
 
     Add VCOUNT to the break column's reset list. Then locate VBNUM in the 
     report footer (RF) section.
 
 
     Add Lookup Once Per Break
     ============================
     To total a lookup value, you need to use a once-per-break operation. 
     For example, if the lookup column (COLNAME) has a CURRENCY data type, 
     define these expressions to calculate at the header: 
 
       vcolname = colname IN look_table WHERE look_column=break_column
       vcount INTEGER = (.vcount + 1)
       vsum CURRENCY = (IFEQ(.vcount,1,(.vsum + .vcolname),.vsum))
 
     Or these expressions to evaluate at the footer:
 
       vcolname = colname IN look_table WHERE look_column=break_column
       vcount INTEGER = (.vcount + 1)
       vrowcount = (COUNT(*)) FROM rep_table WHERE break_column=break_column
       vsum CURRENCY = (IFEQ(.vcount,.vrowcount,(.vsum + .vcolname),.vsum))
 
     Add VCOUNT to the break column's reset list. Then locate VSUM in a break 
     footer or report footer section.
 
 
     Heading on First Detail Line
     ================================
     You can print heading information on the first detail line of a break 
     group without repeating the information on every line of detail. For 
     example, you might base the report on a transaction table, and look 
     up the company name in another table. The report might look like this:
 
         Company A              Transaction Information
                                Transaction Information
                                Transaction Information
         Company B              Transaction Information
         Company C              Transaction Information
                                Transaction Information
 
     Define these expressions:
 
       vcolname = colname IN look_table WHERE look_column=break_column
       vcount INTEGER = (.vcount + 1)
       vprint TEXT = (IFEQ(.vcount,1,.vcolname,' '))
 
     Add VCOUNT to the break column's reset list. Locate VPRINT on the 
     left side of the detail (D) line. You don't need a break header or 
     break footer section but can include them. VPRINT contains the 
     company name on the first row of the break group but is blank on 
     all the subsequent rows. 
 
     To calculate the expression at the footer use these expressions:
 
       vcolname = colname IN look_table WHERE look_column=break_column
       vcount INTEGER = (.vcount + 1)
       vrowcount = (COUNT(*)) FROM rep_table WHERE break_column=break_column
       vprint TEXT = (IFEQ(.vcount,.vrowcount,.vcolname,' '))
 
 
     Add a Blank Line Every Five Lines
     =====================================
     You can improve readability by adding a blank line after every five 
     detail lines. Define these expressions: 
 
       vcount INTEGER = (.vcount + 1)
       vbreak INTEGER = (IFEQ(.vcount,6,1,0))
 
     VCOUNT counts the number of rows, and the IFEQ function in the VBREAK 
     expression determines when five lines have printed. The IFEQ function 
     says, "If VCOUNT is six, set VBREAK to 1; otherwise, set VBREAK to 0."
 
     Make VBREAK a breakpoint and add VCOUNT to its reset list. When you lay 
     out the report make a one-line, blank break footer section. R:BASE 
     prints a blank line when VBREAK changes value.
 
 
     Sum break footer totals
     ==========================
     Usually multiple levels of totals are done by repeating the same 
     totaling expression for a different variable name and not resetting 
     the variable. For example, to print total sales by region, salesperson 
     and then for the whole company, three variables are defined:
 
       vregion_tot = SUM OF sales_amount
       vsalesprsn_tot = SUM OF sales_amount
       vcompany_tot = SUM OF sales_amount
 
     Each variable has the same definition but accumulates the totals for 
     different groups of data based on when the variable is reset. The 
     variable vregion_tot is reset at the breakpoint for region, the 
     variable vsalesprsn_tot is reset at the breakpoint for salesperson, 
     and the variable vcompany_tot is not reset at all.
 
     Sometimes, a sub-total or break total is not a simple SUM OF, but is 
     the result of other calculations. It may not be possible to duplicate 
     the expressions for a different level of total. By using the once-per-
     break operation and setting it up to calculate the expression at the 
     footer you can simply total the break footer amount without duplicating 
     all the other expressions. Use the following expressions:
 
       vcount INTEGER = (.vcount + 1)
       vrowcount = (COUNT(*)) FROM rep_table WHERE break_column=break_column
       vgrand_total CURRENCY = (IFEQ(.vcount,.vrowcount, +
        (.vgrand_total + .vsub_total),.vgrand_total))