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!
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.