===================================================================== 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -