The one thing, above all others, that I wish PROC REPORT could do is know which observations from my data set that I want kept together on a single page of non-Listing output. This is problematic for two reasons. 1. PROC REPORT cannot read my mind! 2. PROC REPORT does not actually control the placement of the table on a page, the output destination does.
Unfortunately for me (and perhaps fortunate for PROC REPORT?) PROC REPORT will never learn to read my mind. Instead, I have to learn to tell it exactly what I want it to do. Here is where that second part comes in––I have to tell PROC REPORT what to do so that it takes some of the control back over ODS destinations.
I have to tell PROC REPORT what to do if I want any of the following outcomes:
- Make each value of a grouping variable start on its own page
- Have the value of a grouping variable repeat at the top of each page
- Force text to appear at the bottom of each page
- Display the bottom table border on each RTF page, when using certain style templates
- Print all of the columns for one set of observations for a really wide table, then print the next set of observations
The way to achieve all of these objectives is to use a BREAK statement and specify the PAGE option.
break after mygrp / page;
But of course things are not always that simple! For instance, the report I am creating might only be two pages long, with no real grouping variable, but I need text on each page under the data. In that case, and in most of the other ones listed, I need to create a grouping variable.
Yes, this is where I really, really wish PROC REPORT could read my mind. Instead, not only do I have to modify my PROC REPORT code, I have to write another DATA step to create a grouping variable. On top of that there is no automatic way to determine what the values of my new variable should be. The value is arbitrary and is based on what I think will fit on a page. And its value might need to change when I get new data or change my font.
The steps to controlling the pagination are:
- Create a new variable. The observations that need to be on a page together should be given one value, the next set of observations should be given another value, and so on.
- Add the new variable to the COLUMN statement in PROC REPORT.
- Add a DEFINE statement for the new variable. Be sure to define it as ORDER or GROUP. Include the NOPRINT option if you do need to see the value in the final report.
- Add a BREAK statement with the PAGE option.
Here is an example of the code that is used to control pagination so that I can put text at the bottom of each page:
data price; set sashelp.pricedata(obs=100); if _n_<=30 then pageit=1; else if 60 >= _n_ > 30 then pageit=2; else if 90 >= _n_ > 60 then pageit=3; else pageit=4; run; ods pdf file='myoutput.pdf'; title 'In lieu of PROC MINDREAD:'; proc report data=price nowd; column pageit date price1-price7; define date /order id; define pageit /order noprint; break after pageit /page; compute after _page_; line 'I want this text at the bottom of each page'; endcomp; run; ods pdf close;
In my book, The SAS® Programmer’s PROC REPORT Handbook, Chapter 2 gives a more detailed explanation of how pagination works with PROC REPORT. Both Chapters 3 and 4 contain an example of inserting page breaks for specific report types. You can also read an excerpt of it online.