BookmarkSubscribeRSS Feed
Joan
Fluorite | Level 6
I am using proc report to create a mix of single and multi page tables for a large report in pdf format. I am using #byval, if that matters.

My humble wish is to be able to include the word "continued" from the 2nd page forward in the first title line for the tables that span multiple pages.

I have spent quite a bit of time trying to do this using compute block with no luck.

Any suggestions? Thanks.
11 REPLIES 11
Cynthia_sas
SAS Super FREQ
Hi:
Here's my question. What do you envision...for example, if I were using SASHELP.SHOES, Africa and Canada's table might each take up 2 pages, while the by group for Asia might only take up 1 page. So which of these possibilities would you want to see:

Possibility 1:
[pre]
Title for Africa (first page of By Group... page number 1)
....
Continued Africa (By Group second page.... page number 2)
.....
****** next BY group ******
Title for Asia (first page of By Group... page number 3)
....
****** next BY group ******
Title for Canada (first page of By Group... page number 4)
....
Continued Canada (second page of By Group... page number 5)
.....
****** next BY group ******
etc, etc...
[/pre]

Possibility 2:
[pre]
Title for Africa (first page of By Group... page number 1)
....
Continued Africa (By Group second page.... page number 2)
.....
****** next BY group ******
Title for Asia (first page of By Group... start page number at 1)
....
****** next BY group ******
Title for Canada (first page of By Group... start page number at 1))
....
Continued Canada (second page of By Group... page number 2)
.....
****** next BY group ******
etc, etc...
[/pre]

Possibility 3:
[pre]
Title for Africa (first page of By Group... page number 1)
....
Continued Africa (By Group second page.... page number 2)
.....
****** next BY group ******
Continued all of Asia (first page of By Group... start page number at 3)
....
****** next BY group ******
Continued all of Canada (first page of By Group... start page number at 4))
.....
****** next BY group ******
etc, etc...
[/pre]

There is no way automatically to do what you want, if you pick from one of the 3 possibilities. But, as you can see, your requirement leaves some room for interpretation and mis-interpretation.

Perhaps you could code an example using SASHELP.SHOES and post the PROC REPORT code here to help give some folks an idea of what you're working with and what you want to achieve. In my mind, there are 2 issues...
1) should the word "Continued" appear in the title on EVERY page after the first page? OR, should the word "Continued" appear in the title on the second page of every BY group, if there is a second page??

2) How should page numbers be treated ... start at 1 and continue to increment across all by groups? OR should the page numbers restart at 1 for every BY group.

cynthia
Joan
Fluorite | Level 6
Thank you for your response.

In response to your questions:
"1) should the word "Continued" appear in the title on EVERY page after the first page? OR, should the word "Continued" appear in the title on the second page of every BY group, if there is a second page??"

The word "continued" should appear in the title on the second page of every by group (if there is second page).

"2) How should page numbers be treated ... start at 1 and continue to increment across all by groups? OR should the page numbers restart at 1 for every BY group."

Page numbers should start at 1 and continue to increment across all by groups.

The example you outlined as "Possibility 1" is what I envision.

I am not familiar with SASHELP.SHOES but here is the basic setup.

This proc report creates 1,000 pages with 250 tables, and all the pages are numbered at the bottom of the page as follows: 1 of 1,000; 2 of 1,000; 3 of 1,000, …; 1,000 of 1,000. (which is what I want)

proc report;
by atype psgd stt agec tnum;
format atype $atype. psgd psgd. stt stt. agec agec.;
……

title1 "Table #BYVAL(tnum)";
title2 "#BYVAL(atype), #BYVAL(psgd)", #BYVAL(stt), BYVAL(agec)";
run;

The TNUM (table number) variable increments when any of the other #bval variables changes and a new table is created with a unique set of titles. (TNUM goes from 1 to 250).

I want "continued" to appear when there are multiple pages within TNUM. So, I would like the first title of the first 3 tables spanning the first 5 pages of the report to be (using your possibility #1):
Table 1
Table 1, continued
Table 2
Table 3
Table 3, continued
(the page numbering shown at the bottom of each page should continue to be: 1 of 1,000; 2 of 1,000; 3 of 1,000; 4 of 1,000; 5 of 1,000)
Cynthia_sas
SAS Super FREQ
Hi:
Are you using ODS ESCAPECHAR in the footnote to get the page x of y page numbering???? Something like this:
[pre]
ods escapechar='^';
footnote 'Page ^{thispage} of ^{lastpage}';
[/pre]

cynthia
Joan
Fluorite | Level 6
I am using the ods escapechar (^). However, I am not using a footnote. Instead, I modify the printer style template.

Style PageNo from TitlesAndFooters /
cellpadding = 0
cellspacing = 0
pretext = "Page "
posttext = " of ^{lastpage}"
vjust=b
just=r;
Cynthia_sas
SAS Super FREQ
What version of SAS are you using??? Would the word 'Continued' absolutely have to be in the title???

You might be able to use PROC REPORT to write the word 'Continued' at the second page of the by group -- putting continued into the title is trickier to do.

How well do you know SAS Macro processing???

cynthia
Joan
Fluorite | Level 6
I am currently using SAS 9.1.3. However, I have SAS 9.2 available on our new unix server and will be using it for new projects. It is possible but difficult for me to use 9.2 on current problem (move everything to new server, problem with libnames, etc.)

I greatly prefer to put "continued" in the title, and this is a "trick" I would use in a lot of my work if I could figure it out once.

I know SAS macro processing, but it is not something I can do in my sleep 🙂 Fair to middling skills.
Cynthia_sas
SAS Super FREQ
Hi:
This example uses 3 regions from SASHELP.SHOES. The first example is sort of brute force and uses hard-coded values for OBS= and FIRSTOBS= in order to change the title statement between "groups". If you could macro-ize this code, it would make it a bit easier to handle, but you still have to figure out the right numbers for OBS and FIRSTOBS.

If you could live with the 'Continued' not being in the title, then you could use a PROC REPORT solution, using COMPUTE BEFORE _PAGE_, as shown in the second program. The trick here is to use $VARYING with a variable for the page number in each region. If the page number is 1, then the NUM variable for use with $VARYING is set to 0, which effectively suppresses the LINE statement. You would still have to set the REGPG variable, but you can do that in a quick DATA step program.

cynthia

[pre]
*** Approach #1 -- brute force;
ods path work.tmp(update)
sasuser.templat(update)
sashelp.tmplmst(read);

ods escapechar='^';

proc template;
define style styles.pgno;
parent=styles.printer;
Style PageNo from TitlesAndFooters /
cellpadding = 0
cellspacing = 0
pretext = "Page "
posttext = " of ^{lastpage}"
vjust=b
just=r;
end;
run;

options nodate pageno=1 nobyline;
ods listing close;

proc sort data=sashelp.shoes out=shoes;
by region;
run;

ods pdf file='test_continued_report.pdf' style=styles.pgno;
** first BY group;
** have to test a few times to see exactly how many obs will;
** fit on one page given the titles, etc. in order to adjust;
** obs= and firstobs= -- for example, initially, I tried 35 and that;
** was too many obs...then 32...still too many, finally 30 seemed to work;
** best. If wrong number picked, then the page breaking will be off;

proc report data=shoes(obs=30) nowd;
where region = "Africa";
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Title on First Page #byline';
run;

proc report data=shoes(firstobs=31) nowd;
where region = "Africa";
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Continued...on all subsequent pages for #byline';
run;

** second BY group;
proc report data=shoes(obs=30) nowd;
where region = "Asia";
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Title on First Page #byline';
run;

proc report data=shoes(firstobs=31) nowd;
where region = "Asia";
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Continued...on all subsequent pages for #byline';
run;

** third BY group;
** could "macroize" the basic proc report program;
** and invoke the program for every BY group;
proc report data=shoes(obs=30) nowd;
where region = "Canada";
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Title on First Page #byline';
run;

proc report data=shoes(firstobs=31) nowd;
where region = "Canada";
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Continued...on all subsequent pages for #byline';
run;
ods pdf close;

options byline;
title;
footnote;
[/pre]


[pre]
*** Approach #2 -- PROC REPORT with REGPG variable;
*** uses same style as program above;
options nodate pageno=1 nobyline;
ods listing close;

proc sort data=sashelp.shoes out=shoes;
by region;
where region in ('Africa', 'Asia', 'Canada');
run;

** make variable to represent page for each region and count within page;
data shoes2;
set shoes;
by region;
if first.region then do;
regcnt = 0;
regpg = 1;
end;
regcnt + 1;
if mod(regcnt,31) = 0 then regpg + 1;
** obs 1-30 will be on pg 1;
** obs 31-61 on pg 2;
** obs 62-92 on pg 3, etc, etc;
run;

ods pdf file='compute_continued.pdf' style=styles.pgno;

proc report data=shoes2 nowd ;
title 'Report for #byline';
by region;
column regpg regcnt subsidiary product sales inventory ;
define regpg / order noprint;
define regcnt / order noprint;
break after regpg / page;
compute before _page_;
length txtstr $20;
if regpg gt 1 then do;
txtstr = 'Continued . . .';
num = length(txtstr);
end;
else if regpg = 1 then do;
txtstr = ' ';
num = 0;
end;
line txtstr $varying. num;
endcomp;
run;

ods pdf close;

options byline;
title;
footnote;
[/pre]
Joan
Fluorite | Level 6
Thanks, this is all very helpful. I may not implement either solution -- because the effort may be too great for this specific report -- but it is helpful to see the possibilities.

For the first approach, the #byval is such an enormous time-saver that I am loathe to give it up. The overall pdf report is based on many proc reports using many #byval configurations.

For the second approach, different tables in the report have different numbers of title lines, so this complicates matters. I use code like you suggest to place conditional notes at the end of each table, based on the content in the table as assessed from within proc report, and it works great. But the conditional aspect here is the ever changing number of rows in a page -- which it seems cannot be calculated from within proc report.

Again, I appreciate the thoughtful suggestions. Thank you!
Cynthia_sas
SAS Super FREQ
Hi:
I understand your predicament...but you are not giving up #BYVAL with the first approach -- it can still be used for the by values in the title, but you give up the elegant way that BY group processing works if you add on the requirement to control the TITLE statement and add the word "continued" on the second page of the output table.

If you could use RTF output, then in 9.2, the new TAGSETS.RTF destination places the word "continued" underneath a table that's about to span multiple pages. That is a good feature because it places the "continued" automatically at the bottom of the page for those BY groups that exceed 1 page. The code for TAGSETS.RTF approach in 9.2 is posted at the bottom.

cynthia
[pre]
ods path work.tmp(update)
sasuser.templat(update)
sashelp.tmplmst(read);

ods escapechar='^';

proc template;
define style styles.pgno;
parent=styles.printer;
Style PageNo from TitlesAndFooters /
cellpadding = 0
cellspacing = 0
pretext = "Page "
posttext = " of ^{lastpage}"
vjust=b
just=r;
end;
run;

options nodate pageno=1 nobyline;
ods listing close;

proc sort data=sashelp.shoes out=shoes;
by region;
run;

ods tagsets.rtf file='test_continued_report.rtf' style=styles.pgno;

proc report data=shoes nowd;
by region;
column region subsidiary product sales inventory;
define region / order noprint;
break after region / page;
title 'Title with #byline';
run;

ods tagsets.rtf close;

options byline;
title;
footnote;

[/pre]
Joan
Fluorite | Level 6
There's a paper in the 'technical tips archive' that seems to do something along the lines of what the SAS 9.2 RTF tagset does. I can't be sure because the link to the paper is broken (i just emailed sas support to see if they can fix it).

http://support.sas.com/sassamples/archive.html
SAS Tech Report Technical Tips Archive
March 2006
Printing Text at the End of Every Page but the Last One in PROC REPORT A COMPUTE AFTER block is processed before the COMPUTE AFTER_PAGE_ on the last page.

Perhaps the idea is to create a last page indicator in 'compute after' and then print a line conditional on this indicator in 'compute after _page_'? If something like that would work, I would use it. It's not exactly what I want, but it would be an improvement without a lot of extra work.

Thanks again for your help.
Cynthia_sas
SAS Super FREQ
Hi:
I believe the logic was similar to what I showed with the variable for determining the COMPUTE BEFORE _PAGE and/or similar to this other Tech Support note:
http://support.sas.com/kb/25/092.html

However, I stopped using COMPUTE BEFORE _PAGE_ and COMPUTE AFTER _PAGE_ with ODS in earlier versions of SAS because the techniques (for counting page breaks) that worked with the LISTING dest (where the page break was fixed) did -not- always work with ODS destinations like PDF or RTF or HTML. For example, if you run the code in above Tech Support note, it will work in the LISTING window, but not in ODS PDF. So ,that's why I started to just compute my own "paging" variable for ODS and/or use TAGSETS.RTF in SAS 9.2.

cynthia

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 11 replies
  • 4836 views
  • 1 like
  • 2 in conversation