I am using Proc Report to produce tables with group variables in PDF format. Rows corresponding to the same value of a group variable may break across two pages if there is no enough space in the preceding page. Instead of displaying rows of the same value of a group variable in separate pages, I would like to move all of them to the next page if they cannot be displayed in the preceding page. Could anyone suggest how to solve the problem? Thanks.
Are you sure that an entire group will fit on one page??? If so, then let's say you have a variable called GRPVAR which is defined like this:
define grpvar / group 'My Group Var';
Then on your break statement, you can do this:
break after grpvar / page;
break after grpvar / page summarize; >---if you also want a summary line
However, if one group's rows will NOT fit on one page, then the rows will spill to the next page. The next group will start on a new page. In paged destinations, like LISTING, RTF and PDF, the new page for each group will be a physical page. In a destination like HTML, the style that you use will determine how the page break is handled. Most ODS styles use a horizontal rule between tables to indicate the presence of a "logical" page.
Thanks Cynthia for the suggestions.
I think I have not made myself clear about the problem. In fact, I don't want to produce a group of tables separated by a group variable. What I want is to display as many rows as possible on the one page. And if there is not enough space left for all rows of the next value of the group variable, they should be moved to the next page.
For example, a group variable GRP_VAR has value a, b, c and d. On the first page, after rows corresponding to a, b and c, there is not enough space to display all rows correponding to value d. The default output is severval rows of value d diplayed on first page, and other rows of value d in the second page. Is there any way to move all rows of value d to the second page? More generally, is there any way to move all rows of a value of a group variable to the next page whenever there is not enough space left on the current page? The position to break for each page may be different due to the variant number of rows corresponding to a value of the group variable. So it is important let SAS to decide/suggest after which value of the group variable should the page break be.
When you use the PAGE option with PROC REPORT, that provides one level of control. If you do NOT use the PAGE option, then PROC REPORT tries to put as many rows as possible on each page, subject to the limits of whatever destination is being sent output.
So, for example, if the output is being sent to the LISTING destination, then the margin and pagesize options come into play. If the output is being sent to the HTML destination, then margin and pagesize options have no impact on the output and the output can be as "long" as it needs to be. If the output is being sent to RTF and PDF then margin options might have an impact, but pagesize options would not have an impact.
PROC REPORT writes one report row at a time. It doesn't really have the type of visibility of the lines left on the page that way you envision. Conceptually, PROC REPORT writes one row at a time until it gets close to the area that is allocated to the footnote at the bottom of the page for the destination...by the time PROC REPORT gets to that area on the page, (and only for paged destinations), it can't "go back" and remove rows once they've been written, in order to move them to the next page, such as you suggest.
If you were sending output to the LISTING destination and using a DATA step program with FILE and PUT statements, then there is a LINESLEFT automatic variable that you can test before your program writes a line of output.
You did not say what your destination of interest is. DATA step and the LINESLEFT option sound like what you want -- but only if your destination of interest is the LISTING destination. LINESLEFT may not work in other destinations as it works for the LISTING destination.
I know that one way folks deal with this type of requirement and PROC REPORT is to figure out (for their destination of interest), how many rows will fit on a page and then they "pre-process" the report data so they can tell ahead of time whether their group will all fit in the space allocated -- this technique is easier to implement for the LISTING destination than for other ODS destinations, because a change in font size with a different style could increase or decrease the number of rows that would fit. Basically, they make a dummy page break variable and use that variable with the PAGE option of PROC REPORT in order to ensure that their report rows get written as they desire.
Thank you very much Cynthia, for your detailed and insightful comments on the issue.
The destination I am interested in is PDF and RTF. By using the option SPANROWS in PROC REPROT, the problem of a group's rows beaking across pages can be solved partially. According to my observation, it looks like the problem does not exist for RTF but still there for PDF.
Yes. One way to solve the problem is to pre-determine page break by creating a dummy page break variable. But it would be a tedious work in my case as the program needs to accomodate different font types and column width is not fixed.
If the problem doesn't exist when you create RTF output, then one possibility would be to create RTF output and use Acrobat Distiller or the Word plug-in for Acrobat to make your PDF file from the RTF file, opened in Word.
Sorry I didn't mention SPANROWS, originally I was thinking that you wanted each group on a separate page, in which case, SPANROWS would be unnecessary. Using SPANROWS will cause the group variable value to repeat when the group does break across pages, which is very useful.
Just as Cynthia said.Maybe you need the help with data step.
But I do not think it is tedious and difficult.Example is
where ranuni(0) ge .5 ;
ods listing close;
ods pdf file='c:\x.pdf'; * to test the page size of pdf;
proc print data=base; *column obs is to see how many lines each page;
run; *34 is the number of lines in pdf;
ods pdf close;
proc means data=base nway;
output out=count n=count;
merge base count(keep=region count);
data result; * To decide Page break point;
retain break 1;
if last.region then sum_mod+mod;
if count +sum_mod ge 34 and region ne lag(region) then do;
ods listing close;
ods pdf file='c:\report.pdf';
proc report data=result nowd spanrows;
column region product subsidiary stores sales inventory returns break;
define break /group noprint;
break after break /page;
ods pdf close;