=====================================================================
     Keeping Groups Together on a Page
     =====================================================================
     PRODUCT: R:BASE            VERSION:3.X,4.0,4.5
     =====================================================================
     AREA: Reports              CATALOG: FORMS, REPORTS & LABELS
     =====================================================================
 
     Breakpoints in reports are used for categorizing, showing totals, and 
     generally, providing a clearer organization of database information. 
     Breakpoints have headers, footers and detail sections. Sometimes, the 
     break header will print at the bottom of page 2 and the break detail 
     information and the footer on page 3. Or the header and detail will 
     print on page 2 and the footer on page 3. 
     
     R:BASE reports consider the header, detail and footer sections of a 
     breakpoint to be separate. The report writer is designed to not split 
     a section across pages, but since each part of a breakpoint is 
     considered a separate section it won't automatically keep all three 
     parts of a breakpoint together on a page. Break header and footer 
     sections are a fixed size (number of lines), but the detail section 
     expands based on the amount of data (number of rows) to be printed. 
     Because the detail section can vary in size, all parts of a breakpoint 
     may not print on the same page.
 
     The techniques described below will keep the header and footer and all 
     corresponding detail rows on the same page. If the three groups won't 
     fit on what's left of the page, a form feed is done. If you have lots 
     of detail lines, you may not be able to keep the header and footer 
     from splitting across pages.
 
     One group per page
 
     To have only one group or breakpoint print on each page of your report 
     simply specify a form feed before break header for the breakpoint on 
     the Create breakpoints screen off the Layout menu in Reports 
     Create/modify. However, you may have a situation with several small 
     breakpoints printing on one page, and you don't want any part of a 
     breakpoint split over two pages. 
 
     Fixed number of groups per page -- No detail section
 
     If you have only break header and footer lines, no detail lines, you 
     can keep them together on a page by specifying a calculated number of 
     lines per page (under the Page settings screen off the Layout menu in 
     Reports Create/modify). To determine the number of lines per page for 
     break information, make the following calculations:
 
     1. Total the number of marked lines for page header and footer 
        (PH, PF)
     2. Subtract this total from the Liner per page setting
 
     The result tells you how many lines per page you have for the break 
     information.  To determine how many break groups you can fit in that
     number of lines, perform these calculations:
 
     3. Total the marked lines for the break header adn footer (H1, F1)
     2. Divide the previous calculation (#2) by this total of marked break
        lines
 
     The result of calculation #4 is how many groups you can fit on a page.
     Make sure this number comes out even, you don't want any remainder.
     
     For example, there are 5PH lines and 1 PF line for a total of 6 lines 
     that will print every page. Subtract this number from 60, the default 
     Lines per page; 60 - 6 = 54. There are 54 lines available on each page 
     for printing break groups. If there are 3 H1 lines and 1 F1 line 
     defined, 13 groups will fit in 54 lines ( 54/4 = 13), but there are an 
     extra 2 lines per page left over. Subtract these leftover lines from 
     the default Lines per page setting, change it from 60 to 58. Then the 
     right number of groups will always print on a page and no group will 
     be split between pages. This technique uses R:BASE's automatic form 
     feed at the end of a page.
 
     If you are printing a detail section as well as break header and 
     footer sections, use one of the following techniques to keep all of a 
     groups' information on the same page. Because the size of the detail 
     section can vary, you can't just calculate the page size.
 
     Fixed number of groups per page  -- With detail section
 
     If your breakpoints are of relatively similar size, meaning that they 
     each take about the same number of lines per page, print a fixed 
     number of breaks or groups per page. Using the Concomp database as an 
     example, the transactions recorded in the Transdetail table have one 
     or two detail lines each. Build a report on the Transdetail table that 
     prints 6 groups per page and then form feeds. The breakpoint column 
     will be the transid column. Here are the steps:
 
     First define the variables. There are five required.
 
     1) vcnt INTEGER = (.vcnt + 1)
     2) vbdetot = (COUNT(transid)) IN transdetail WHERE transid = transid
     3) vbrkcnt INTEGER = (IFEQ(.vcnt, 1, .vbrkcnt + 1, .vbrkcnt))
     4) vbreak INTEGER = (IFEQ(.vcnt, .vbdetot, IFEQ(.vbrkcnt, 6, (.vbreak 
        + 1), .vbreak), .vbreak))
     5) vpbreak INTEGER = .vbreak
 
     Next, reorder the variables to place vpbreak first in the variable 
     list. It can't be defined until vbreak is defined, but for this 
     technique to work it needs to execute first.
 
     The variable, vcnt, counts the rows in the table as the report prints 
     them. Reset it at the transid breakpoint. Vbdetot counts the total 
     number of rows that are in the group, it "looks up" the count. The 
     variable vbrkcnt counts of the number of breaks that have printed. 
     Reset vbrkcnt at the page. 
 
     The variable vbreak does most of the work. It decides when you have 
     printed the specified number of groups on a page, and then increments 
     itself. It works by comparing the number of rows the report has 
     counted (in the vcnt variable) with the number of rows the report 
     looked up (in the vbdetot variable). When these two values equal each 
     other, the report has reached the last row within a group. Then, the 
     report checks to see if the number of groups or breakpoints has 
     reached the number specified to print on a page. If yes, the variable 
     vbreak increments and breaks, causing a form feed. The variable 
     vpbreak  makes sure the last row of the last break prints on the 
     correct page. 
 
     Since all expressions are processed in order starting with expression 
     one, vpbreak contains the value of vbreak from the previous row. It is
     needed because vbreak is evaluated on the last row of data before the 
     data has printed. If the breakpoint was set up on vbreak, the last row 
     of the last break or group of the page would print on the top of the 
     next page. This is just what the report is designed to avoid.
 
     After defining the variables, set up the rest of the report. Make 
     vpbreak the first breakpoint of the report and choose to reset the 
     variable vbrkcnt. In addition, answer Yes to Form feed before break 
     header for the vbpreak breakpoint. Define transid as the second 
     breakpoint. Reset the variable, vcnt, at this break.
 
     The report must have a header line, H1, marked for vpbreak. This line 
     will act like part of the page header, it will only print once at the 
     beginning of each page. You can put page header information on it, or 
     it can be left blank. There is no need for an F1 line. 
 
     For the transid break, set up the header (H2), detail (D) and footer 
     (F2) sections as you like. Define other variables for transaction 
     totals or detail amounts, put in text for headings and footer 
     information and place your fields locations just as you would in any 
     other report.
 
     ZERO must be set ON for the report variables to initialize and 
     evaluate properly. Also, since the variable vpbreak references a 
     variable below it in the variable list, the referenced variable, 
     vbreak, must be initialized prior to printing the report. Do this at 
     an R> prompt with the command SET VAR vbreak INTEGER, or in an 
     application, insert a Custom action before the Print action. The 
     custom code entered is SET VAR vbreak INTEGER. 
 
     The report prints as many breaks as you specified per page! To change 
     the number of breaks printed per page, just change the number 
     specified in the vbreak variable (in this example, the number is 6).
 
     Varied number of groups per page  -- With detail section
 
     Another way to keep break groups that include detail together on a 
     page is to look at the number of lines left on the page and compare 
     that with the number needed for the group. This is similar to the 
     method you can use when you aren't printing a detail section.  Use a
     copy of the previous example's report to see how to set up this 
     report. Most of the work is done with variables.  In fact, most of the 
     variables are the same.  However, you need an extra variable and the 
     expression changes slightly on two others.
     
     1) vcnt INTEGER = (.vcnt + 1)
     2) vbdetot = (COUNT(transid)) IN transdetail WHERE transid = transid
     3) vbrkcnt INTEGER = (IFEQ(.vcnt,1,.vbrkcnt + 1,.vbrkcnt))
     4) vbrkpgsiz INTEGER = (IFEQ(.vcnt,1, (IFGT(.vbrkcnt,1,(.vbrkpgsiz + 
        .vbdetot + 2), (.vbrkpgsiz + .vbdetot + 6))), .vbrkpgsiz))
     5) vbreak INTEGER = (IFEQ(.vcnt,.vbdetot,(IFEQ(.vbrkpgsiz,50,(.vbreak 
        + 1), (IFGT(.vbrkpgsiz,50,(.vbreak+1),.vbreak)))),.vbreak))
     6) vpbreak = .vbreak
 
     Next, reorder the variables to place vpbreak first in the variable 
     list. It can't be defined until vbreak is defined, but for this 
     technique to work it needs to execute first.
 
     The variable, vcnt, counts the rows in the table as the report prints 
     them. Reset it at the transid breakpoint. Vbdetot counts the total 
     number of rows that are in the group, it "looks up" the count. The 
     variable vbrkcnt counts of the number of breaks that have printed. 
     Reset vbrkcnt at the page. 
 
     The variable vbrkpgsiz keeps track of how many lines have printed on 
     the page.  Before you define vbrkpgsiz, make the following two 
     calculations.  The expression contains these two calculated numbers. 
     
     1. Total the number of lines marked for the page header (PH) and page 
     footer (PF sections and the number of header (H1) and footer (F1) 
     lines marked for break 1, vpbreak (the number is 6 in the example.).
 
     2. total the number of lines marked for the break header (H2) and 
     footer (F2) for the transid breakpoint (the number is 2 in this 
     example.).
     
     Vbrkpgsiz evaluates as follows:
 
     "(IFEQ(.vcnt,1," .  - check the vcnt variable.  If vcnt is 1, the 
     report is at the start of a new break group and the nested ifgt 
     function is evaluated. 
 
     If vcnt is not 1, the value of vbrkpgsiz doesn't change.
 
     "IFGT(.vbrkcnt,1,". If vbrkcnt is 1 (the report is at the top of a new 
     page), then vbrkpgsiz increments itself with the calculated number of 
     lines in the page header/footer sections (calculation #1 above) and the 
     number of detail lines (stored in the vbdetot variable) for the first 
     breakpoint on the page -- ".vbrkpgsiz + .vbdetot + 6". 
     
     If vbrkcnt is greater than 1, then the report is on a break in the 
     middle of a page and vbrkpgsiz needs to be incremented with the number 
     of lines marked as headers and footers for the transid break and the 
     number of detail lines (vbdetot) -- ".vbrkpgsiz + .vbdetot + 2". 
     
     This appears confusing, but what is basicall means is: add the page 
     header lines at the top of the page; add the break header and detail 
     lines at the start of each break of stay the same.
 
     The variable vbreak does almost as much work as vbrkpgsiz. It decides 
     when the specified number of lines have been printed on a page, and 
     then it increments itself. Vbreak evaluates as follows. 
     "(IFEQ(vccnt,.vdbetot"- compares the number of rows the report 
     has counted (in the vcnt variable) with the number of rows the looked 
     up (in the vbdetot variable) 
     
     When these two variables equal each other, the last row within a group 
     has been reached and the nested function is evaluated. 
     
     "( IFEQ(.vbrkpgsiz,50,(.vbreak + 1)
     IFGT(.vbrkpgsiz,50,(.vbreak + 1)"
     
     checks to see if the numver of lines printed (vbrkpgsiz) has reached 
     the number of specified to print on a page (50). If vbrkpgsiz is 
     greater than or equal to 50, vbreak is incremented.
 
     The variable vpbreak  makes sure the last row of the last break prints 
     on the correct page. 
 
     Since all expressions are processed in order starting with expression 
     one, vpbreak contains the value of vbreak from the previous row. It is 
     needed because vbreak is evaluated on the last row of data before the 
     data has printed. If the breakpoint was set up on vbreak, the last row 
     of the last break or group of the page would print on the top of the 
     next page. This is just what the report is designed to avoid.
 
     After defining the variables, set up the rest of the report. Make 
     vpbreak the first breakpoint of the report and choose to reset the 
     variable vbrkcnt. In addition, answer Yes to Form feed before break 
     header for the vbpreak breakpoint. Define transid as the second 
     breakpoint. Reset the variable, vcnt, at this break.
 
     The report must have a header line, H1, marked for vpbreak. This line 
     will act like part of the page header, it will only print once at the 
     beginning of each page. You can put page header information on it, or 
     it can be left blank. There is no need for an F1 line. 
 
     For the transid break, set up the header (H2), detail (D) and footer 
     (F2) sections as you like. Define other variables for transaction 
     totals or detail amounts, put in text for headings and footer 
     information and place your fields locations just as you would in any 
     other report.
 
     ZERO must be set ON for the report variables to initialize and 
     evaluate properly. Also, since the variable vpbreak references a 
     variable below it in the variable list, the referenced variable, 
     vbreak, must be initialized prior to printing the report. Do this at 
     an R> prompt with the command SET VAR vbreak INTEGER, or in an 
     application, insert a Custom action before the Print action. The 
     custom code entered is SET VAR vbreak INTEGER. 
 
     You now have two new ways to produce reports that can group your data 
     neatly on a page and provide valuable information in a well organized 
     and clearly formatted style.
 
     PH
     PH  Transaction Report
     PH                        Page: 1
     H1
     H2  Transid: _______ 
     D   Model: _______ Units: _______ Price: __________
     F2                     Total Price:  __________________
     PF  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -