BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
oussema
Obsidian | Level 7

Hello all,

I have this dataset;

id start_date    aval1    aval2         grp

1      1                4            .               A

1      3                4            .               A

1      5                6            .               A

1     10                .           12             B

1     12                .            21            B

1     14                .           11             B 

1     16                .           12             B

1     11                .            25             B

2      2               4              .               A          

2      3               6              .               A

2      5               9              .               A

2     19             12             .               A 

2     23              .              13             B

3     6                5              .               A

3     8               18             .               A 

3    10                .             20             B

3    13                .             17             B  

For each id, I want to get a figure in one rtf page (so 3 pages).For each page , I want to have as footnote 'page n of N'. n is the number of the id and N is the total number (which is 3).I've created macro variables and I tried to use the 'where' statement in proc sgplot but it doesn't work because the where statement was rejected. This is a part of my code:

%DO i=1 %to &TOTAL. ;
TITLE font="Courier New" justify=center h=1.8 j=l "&&sub&i";
footnote4 font="Courier New" h=1.8 j=l "Page &i of &total";
proc sgplot data=fin2;
where id=&i.;
by id;
step x=start_date y=aval1 / lineattrs=(color=grey pattern=solid thickness=1.4mm) ;
step x=start_date y=aval2 / y2axis lineattrs=(color=green pattern=solid thickness=1.4mm) ;
xaxis label='Study day' minor minorcount=4  type=linear ;
yaxis label='Inhaled treprostinil' minor minorcount=4 offsetmin=1 offsetmax=1 type=linear  ;
y2axis label='Selexipag' labelpos=center minor minorcount=4 offsetmin=0 offsetmax=0 type=linear ;
keylegend / across=1 down=2 noborder linelength=4mm ;
run;
ods rtf close;

%end;
ods _all_ close;
options ls=120;
%mend print;
%print;

 

Any suggestion please ?

  

1 ACCEPTED SOLUTION

Accepted Solutions
Cynthia_sas
SAS Super FREQ

Hi:

  I created an example that uses SASHELP.CLASS and does what I think you want:

get_page_numbers.png

I am sorry it is so small, but I have highlighted in yellow the Page X of Y page numbers in each footnote (showing 3 pages) and in the TITLE, I show the name (where you would show ID). You should be able to run this code. As you can see, I did not try to "overcontrol" things by doing my own page numbering or using a %DO loop. Since you did not show all of your macro code and since I find it best to have a working "proof of concept" before macroizing anything, I simplified the program and "hardcoded" the invocation of the macro program for each student inside my ODS RTF "sandwich".

** put the proc report and graph code in a macro program;
%macro makertf(wname=,xx=,xyz=,ffff=);
ods escapechar='^';
proc report data=sashelp.class;
  title j=c "ID/Name is for &wname";
  footnote1 j=l "&xx";
  footnote2 j=l "&xyz";
  footnote3 j=l "&FFFF";
  footnote4 'Page ^{thispage} of ^{lastpage}';  
  where name = "&wname";
  column name sex age height weight;
run;

** make a data label variable for the name of interest;
data graf_class;
  set sashelp.class;
  if name in ("&wname") then dl=Name;
  else dl = ' ';
run;

** if you are using RTF do NOT need to have ODS LISTING statement;
** before PROC SGPLOT;
proc sgplot data=graf_class;
  scatter x=height y=weight / datalabel=dl;
run;
%mend makertf;


** now invoke the macro program 1 time for each student;
options nodate nonumber orientation=portrait;
  
ods rtf file='c:\temp\test_pg_no.rtf' startpage=no nogtitle nogfootnote;
%makertf(wname=Alice, xx=AA1, xyz=AA12, FFFF=AAA123)

ods rtf startpage=now;

%makertf(wname=Alfred, xx=ABC1, xyz=ABC12, FFFF=ABC123)

ods rtf startpage=now;

%makertf(wname=Robert, xx=ABB1, xyz=ABB12, FFFF=AB123)
ods rtf close;

And while you could certainly "macroize" the whole program and the invocation for every student/patient/ID, I'd recommend getting it working like this and then inserting more macro logic of %DO loops. And you have to think about where you would want the %DO loops to be - or whether 1 macro would do the job or whether you'd need more than one macro program to get things done.

 

  At any rate, I do find that ESCAPECHAR and the regular page x of y page numbering work for me in ODS RTF. Hope this points you in the right direction.

 

Cynthia

View solution in original post

8 REPLIES 8
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Yes, look up by group processing.  It should be a fundamental in the learning material but seems to have been removed and replaced with do everything in macro instead.

ods escapechar="^";

title "...";
footnote4 'Page ^{thispage} of ^{lastpage}';

ods rtf file="...";

proc sgplot...;
  by id;
  ...
run;

ods rtf close;
oussema
Obsidian | Level 7

I don't know why it doesn't work. In the output I get 'page of' and not 'page 1 of 1' (for instance).

RW9
Diamond | Level 26 RW9
Diamond | Level 26

You will need to set the option to not have titles/footnotes embedded in the graph:

ods rtf file="..." nogtitle nogfoot;

Then the titles/footers should be in the header/footer section of the output file and be resolved correctly at render time. 

oussema
Obsidian | Level 7

This is a part of the code, the problem remains:

options orientation=portrait papersize='ISO A4' nodate noDate nonumber nobyline;
%let figtit0 = XXX ;
%let figtit1 = YYY ;
%LET gtxt = 'Courier New';
%LET gtxtL = 'Courier New';
goptions reset=all
device=png gunit=pct rotate=portrait
xmax=10 in ymax=12 in
xpixels=1400 ypixels=1800
hsize=20.5 cm vsize=13 cm
ftext= 'Arial' htitle=9.0 pt htext=9.0 pt cback=white gwait=2 ;
goption display noborder ;

options orientation=portrait papersize='ISO A4' nodate noDate nonumber nobyline
bottommargin= 2.4 cm topmargin= 2.2 cm
leftmargin= 2.4 cm rightmargin= 2.0 cm;
ods escapechar='^';
TITLE1 font="Courier New" h=1.8 j=l "&figtit0.";
TITLE2 font="Courier New" h=1.8 j=l "&figtit1.";
footnote1 font="Courier New" h=1.8 j=l "xx";
footnote2 font="Courier New" h=1.8 j=l "xyz";
footnote3 font="Courier New" h=1.8 j=l "FFFF";
footnote4 'Page ^{thispage} of ^{lastpage}';
ods rtf file ="aaa.rtf"
style =normal NOGTITLE nogfootnote bodytitle;
ods listing style=listing;
proc sgplot data=fin2;
by ID;
step x=START_DATE y=aval1 / lineattrs=(color=grey pattern=solid thickness=1.4mm) ;
step x=START_DATE y=aval2 / y2axis lineattrs=(color=green pattern=solid thickness=1.4mm) ;
xaxis label='Study day' minor minorcount=4  type=linear ;
yaxis label='AAA' minor minorcount=4 offsetmin=1 offsetmax=1 type=linear values=(0 to 15 by 1) ;
y2axis label='BB' labelpos=center minor minorcount=4 offsetmin=0 offsetmax=0 type=linear values=(0 to 1600 by 200) ;
keylegend / across=1 down=2 noborder linelength=4mm ;
run;
quit;
ods rtf close;
ods _all_ close;
options ls=120;

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Use a code window to post code - its the {i} above post - as this preserves formatting.

At a guess I would say update this line to this:

ods rtf file="aaa.rtf" style=normal nogtitle nogfoot;

 

And remove the ods listing:
ods listing style=listing; 

 

In fact, ods _all_ close;  before any programming is good as you aren't using listing output.

 

Also note, I can't test this.

Cynthia_sas
SAS Super FREQ
Hi, also, I am not sure why you are using a GOPTIONS statement with the ODS Graphics SGPLOT. GOPTIONS has no impact on SGPLOT, SGPANEL or SGSCATTER procedures.

Also, it is not clear to me what type of page numbering you want or why you are not using the normal ESCAPECHAR page numbering controls.

cynthia
oussema
Obsidian | Level 7

Hello Cynthia,

I tried with escapechar but I don't know why it doesn't work (see the discussion above).

What I want to get is a graphic for each patient in an RTF file (every page contains one figure and a footnote 'page x of y' and a title which contain the id number). I couldn't combine the by group statement and a loop statement to get the required result. 

Cynthia_sas
SAS Super FREQ

Hi:

  I created an example that uses SASHELP.CLASS and does what I think you want:

get_page_numbers.png

I am sorry it is so small, but I have highlighted in yellow the Page X of Y page numbers in each footnote (showing 3 pages) and in the TITLE, I show the name (where you would show ID). You should be able to run this code. As you can see, I did not try to "overcontrol" things by doing my own page numbering or using a %DO loop. Since you did not show all of your macro code and since I find it best to have a working "proof of concept" before macroizing anything, I simplified the program and "hardcoded" the invocation of the macro program for each student inside my ODS RTF "sandwich".

** put the proc report and graph code in a macro program;
%macro makertf(wname=,xx=,xyz=,ffff=);
ods escapechar='^';
proc report data=sashelp.class;
  title j=c "ID/Name is for &wname";
  footnote1 j=l "&xx";
  footnote2 j=l "&xyz";
  footnote3 j=l "&FFFF";
  footnote4 'Page ^{thispage} of ^{lastpage}';  
  where name = "&wname";
  column name sex age height weight;
run;

** make a data label variable for the name of interest;
data graf_class;
  set sashelp.class;
  if name in ("&wname") then dl=Name;
  else dl = ' ';
run;

** if you are using RTF do NOT need to have ODS LISTING statement;
** before PROC SGPLOT;
proc sgplot data=graf_class;
  scatter x=height y=weight / datalabel=dl;
run;
%mend makertf;


** now invoke the macro program 1 time for each student;
options nodate nonumber orientation=portrait;
  
ods rtf file='c:\temp\test_pg_no.rtf' startpage=no nogtitle nogfootnote;
%makertf(wname=Alice, xx=AA1, xyz=AA12, FFFF=AAA123)

ods rtf startpage=now;

%makertf(wname=Alfred, xx=ABC1, xyz=ABC12, FFFF=ABC123)

ods rtf startpage=now;

%makertf(wname=Robert, xx=ABB1, xyz=ABB12, FFFF=AB123)
ods rtf close;

And while you could certainly "macroize" the whole program and the invocation for every student/patient/ID, I'd recommend getting it working like this and then inserting more macro logic of %DO loops. And you have to think about where you would want the %DO loops to be - or whether 1 macro would do the job or whether you'd need more than one macro program to get things done.

 

  At any rate, I do find that ESCAPECHAR and the regular page x of y page numbering work for me in ODS RTF. Hope this points you in the right direction.

 

Cynthia

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 8 replies
  • 4622 views
  • 0 likes
  • 3 in conversation