I want to print a statement at the top of each BYVAL table (or the top of each page) labelling the BYVAL. However, when an ODS PDF page break occurs in the middle of a table, the label should include the word "(continued)".
I don't care if this happens through a line statement, ODS text, conditional label, some span functionality, etc. I don 't care if the proc report uses a BY statement or if I have to create a macro to run each BYVAL individually.
I've only tried output ODS PDF, which needs to be the final result. But I guess if ODS PDF is causing the problem, I could use another ODS and save the result to pdf manually.
I think I should be able to do this by evaluating _break_ type or observation number. I feel like I might need a hold value from one compute statement to use in another compute statement, but I can't get it right.
Thank you in advance for any advice!
proc sort data=sashelp.cars out=cars_make;
by make;
run;
ods escapechar='^';
options nobyline;
Title1 color='black' "^S={font_face='Verdana' font_size=18pt}Title1" ;
Title2 color='black' "^S={font_face='Verdana' font_size=18pt}Title2" ;
Title3 color='black' "^S={font_face='Verdana' font_size=18pt}Title3" ;
ods pdf file ="SGE26.pdf" notoc startpage=no ;
proc report data=cars_make (firstobs= 1 obs= 500) out=tryout;
where origin = 'USA';
by make;
column make DISP_make model type origin newobs;
define make /group noprint;
define DISP_make /computed;
define model / order order=internal;
define type / order order=internal;
define origin / order order=internal;
define newobs/display computed;
break after make/;
compute newobs;
_obs_+1;
newobs=(_obs_)-1;
endcomp;
compute before _page_ /left;
length text $100;
if hold_obs <2 then do;
text="For Bucket xxx";
num=100;
end;
else do;
text="For Bucket XXX (continued)";
num=150;
end;
line text $varying. num;
endcomp;
compute before make;
cnt_make + 1;
hold_make= make;
hold_obs=newobs;
endcomp;
compute DISP_make / character length= 20;
DISP_make = hold_make;
endcomp;
run;
ods pdf close;
If you want compact layout, try this one :
%let n=20; * a page has 20 records ;
DATA AAA;
SET SASHELP.CARS(obs=400);
RUN;
proc sort data=AAA;
by Make;
run;
data AAA;
set AAA;
by Make;
if first.Make then n=0;
n+1;
if first.Make or mod(n,&n.)=1 then PAGE_NO+1;
drop n;
run;
proc freq data=AAA noprint;
table Make*PAGE_NO/out=PAGE_NO;
run;
data PAGE_NO;
length Make $ 80;
set PAGE_NO;
by Make;
if not first.Make then Make=catx(' ',Make,'(continued)');
total+count;
if total>20 then do;group+1;total=count;end;
run;
data AAA2;
merge AAA(drop=Make) PAGE_NO(keep=Make PAGE_NO group);
by PAGE_NO;
run;
proc freq data=PAGE_NO noprint;
table group/out=group;
run;
%macro report(group=);
PROC REPORT DATA=AAA2 nowd contents='';
where group=&group.;
by PAGE_NO;
COLUMNS Make Model Type Origin DriveTrain MSRP;
DEFINE Make / order ;
DEFINE Model / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Type / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Origin / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE DriveTrain / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE MSRP / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
compute before _page_/style={just=l};
line Make $80.;
endcomp;
RUN;
%mend;
ODS PDF FILE= "c:\temp\A.pdf" startpage=no;
option nobyline;
data _null_;
set group end=last;;
call execute(catt('%report(group=',group,')'));
if not last then call execute('ods pdf startpage=now;');
run;
ODS PDF CLOSE;
Yeah. It is a little complicated ,but still doable.
%let n=20; * a page has 20 records ;
DATA AAA;
SET SASHELP.CARS(obs=400);
RUN;
proc sort data=AAA;
by Make;
run;
data AAA;
set AAA;
by Make;
if first.Make then n=0;
n+1;
if first.Make or mod(n,&n.)=1 then PAGE_NO+1;
run;
proc freq data=AAA noprint;
table Make*PAGE_NO/out=PAGE_NO;
run;
data PAGE_NO;
length Make $ 80;
set PAGE_NO;
by Make;
if not first.Make then Make=catx(' ',Make,'(continued)');
run;
%macro report(PAGE_NO=,Make=);
PROC REPORT DATA=AAA nowd contents='';
where PAGE_NO=&PAGE_NO.;
COLUMNS ("(*ESC*)S={just=l}For Bucket &Make." Make Model Type Origin DriveTrain MSRP);
DEFINE Make / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Model / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Type / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Origin / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE DriveTrain / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE MSRP / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
RUN;
%mend;
ODS PDF FILE= "c:\temp\A.pdf" ;
data _null_;
set PAGE_NO;
call execute(catt('%report(PAGE_NO=',PAGE_NO,',Make=',Make,')'));
run;
ODS PDF CLOSE;
If you want compact layout, try this one :
%let n=20; * a page has 20 records ;
DATA AAA;
SET SASHELP.CARS(obs=400);
RUN;
proc sort data=AAA;
by Make;
run;
data AAA;
set AAA;
by Make;
if first.Make then n=0;
n+1;
if first.Make or mod(n,&n.)=1 then PAGE_NO+1;
drop n;
run;
proc freq data=AAA noprint;
table Make*PAGE_NO/out=PAGE_NO;
run;
data PAGE_NO;
length Make $ 80;
set PAGE_NO;
by Make;
if not first.Make then Make=catx(' ',Make,'(continued)');
total+count;
if total>20 then do;group+1;total=count;end;
run;
data AAA2;
merge AAA(drop=Make) PAGE_NO(keep=Make PAGE_NO group);
by PAGE_NO;
run;
proc freq data=PAGE_NO noprint;
table group/out=group;
run;
%macro report(group=);
PROC REPORT DATA=AAA2 nowd contents='';
where group=&group.;
by PAGE_NO;
COLUMNS Make Model Type Origin DriveTrain MSRP;
DEFINE Make / order ;
DEFINE Model / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Type / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE Origin / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE DriveTrain / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
DEFINE MSRP / DISPLAY STYLE(COLUMN)={CELLWIDTH=1IN};
compute before _page_/style={just=l};
line Make $80.;
endcomp;
RUN;
%mend;
ODS PDF FILE= "c:\temp\A.pdf" startpage=no;
option nobyline;
data _null_;
set group end=last;;
call execute(catt('%report(group=',group,')'));
if not last then call execute('ods pdf startpage=now;');
run;
ODS PDF CLOSE;
Wow! This is quite the "work-around," but it indeed WORKS! Thank you so much!
This second "compacted" method fit my needs better by not automatically page -breaking between the groups.
I'm pretty new to Proc Report; I never would have thought to create a table to hold the record count, page numbering and the "continued" text. I've added several new concepts to my SAS toolbox by working through this code with my real-life report. Thanks again!
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!
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.
Ready to level-up your skills? Choose your own adventure.