BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
kscdenney
Calcite | Level 5

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!

 

ODS PDF.png

 

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;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Ksharp
Super User

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;

View solution in original post

3 REPLIES 3
Ksharp
Super User

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;

Ksharp_0-1741924254812.png

 

Ksharp
Super User

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;
kscdenney
Calcite | Level 5

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! 

 

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 1886 views
  • 0 likes
  • 2 in conversation