Hi
When I write SAS macros, I want to send plots generated by PROC SGPLOT directly to word document, but SAS returns a blank work document. Below is the detail:
ods rtf file="&outpath.&fname.&sysdate..doc";
options nodate nonumber;
proc sgplot data=_plot;
yaxis values=(0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1.0);
xaxis values= (&xaxisvalue);
step y=CIF x=time /group=status;
run;
I can't find the solution. Thanks
Best
Yaqi
Please post your full code.
At the least there's no ODS RTF Close.
I can get word document, but it is blank. Below is the full code: Thanks
%macro cif_plot(dsn=,grplist=,time=,censor=,event=1,censored=0,title1=,title2=,xaxisvalue=,timelist=,plot=T,units=,compete=T,
outpath=, fname=, debug=F);
/* Prevent case sensitivity */
%let plot = %UPCASE(&plot);
%let debug = %UPCASE(&debug);
%let compete = %UPCASE(&compete);
%if &units ~= %str() %then %let units = %sysfunc(PROPCASE(&units));
/* Count number of time estimates requested */
%let time_cnt = %sysfunc(countw(&timelist,' '));
%let n=1;
%do %until (%scan(&grplist,&n)= );
%let grp=%scan(&grplist,&n);
%put grp=&grp;
DATA _cif_temp;
set &dsn;
/* If group variable is missing then delete it to avoid a missing category being
included in the plots */
%if &grp ~= %STR() %then %do;
if MISSING(&grp)=1 then delete;
%end;
RUN;
%CIF(DATA=_cif_temp, out=_stat1, TIME=&time, STATUS=&censor, EVENT=&event, CENSORED=&censored, group=&grp,
OPTIONS=NOCIFEST NOPRINTTEST NOPLOT);
%if &grp ~= %STR() %then %do;
/* Get Gray's p-value */
PROC SQL noprint;
select pval format=pvalue6.4 into :pval1
from testresult;
QUIT;
PROC DATASETS lib=work noprint;
delete testresult;
QUIT;
%end;
/* If plotting both event of interst and competing event - calculate CIF for competing event */
%if &compete = T %then %do;
/* Extract value(s) of competing risk from censor variable*/
proc sql noprint;
select distinct &censor into: cenval separated by ' ' from _cif_temp;
quit;
%put value of censor = &cenval;
%let n=1;
%let comrisk=; /*macro variable for values of competing risk*/
%do %until (%scan(&cenval,&n)= );
%let cenvaln=%scan(&cenval,&n);
%if &cenvaln ~= &event and &cenvaln ~= &censored
%then %let comrisk= &comrisk &cenvaln;
%let n=%eval(&n+1);
%end;
%put The value(s) of competing risk = &comrisk;/*check the value(s) of competing risk*/
%CIF(DATA=_cif_temp, out=_stat2, TIME=&time, STATUS=&censor, EVENT=&comrisk, CENSORED=&censored, group=&grp,
OPTIONS=NOCIFEST NOPRINTTEST NOPLOT);
%if &grp ~= %STR() %then %do;
/* Get Gray's p-value */
PROC SQL noprint;
select pval format=pvalue6.4 into :pval2
from testresult;
QUIT;
PROC DATASETS lib=work noprint;
delete testresult;
QUIT;
%end;
%end;
/* Get event labels */
PROC SORT DATA = _cif_temp out = _events nodupkey;
by &censor;
where &censor ~= 0;
RUN;
PROC SQL noprint;
select &censor into :event1
from _events
where &censor = 1;
select &censor into :event2
from _events
where &censor = 2;
QUIT;
/* If groups were used */
%if &grp ~= %STR() %then %do;
DATA _NULL_;
set _cif_temp;
/* Group Label */
CALL SYMPUT('grpL',VLABEL(&grp));
RUN;
%end;
/* Create variable to group by in plot */
DATA _stat1plot;
set _stat1plot;
%if &grp ~= %STR() %then %do;
%if &compete = T %then %do;
status = TRIM(&grp) || ": " || "&event1";
%end;
%else %do;
status = TRIM(&grp);
%end;
%end;
%else %do;
status = "&event1";
%end;
RUN;
/* If plotting both event of interst and competing event - calculate CIF for competing event */
%if &compete = T %then %do;
DATA _stat2plot;
set _stat2plot;
%if &grp ~= %STR() %then %do;
status = TRIM(&grp) || ": " || "&event2";
%end;
%else %do;
status = "&event2";
%end;
RUN;
%end;
/* Merge files for plot */
DATA _plot;
length status $256;
set _stat1plot %if &compete = T %then %do; _stat2plot %end;;
time = &time;
%if &grp ~= %STR() %then %do;
LABEL status = "&grpL";
%end;
%else %do;
LABEL status = 'Event';
%end;
LABEL cif = 'Probability'
time = "Time (&units)";
RUN;
/* Sort groups for plotting */
%if &grp ~= %STR() %then %do;
PROC SORT DATA = _plot;
by &grp;
RUN;
%end;
%if &title1 ~= %STR() %then %do; TITLE1 &title1; %end;
%if &title1 ~= %STR() %then %do; TITLE2 &title2; %end;
ods rtf file="&outpath.&fname.&sysdate..doc";
options nodate nonumber;
/* Create plot if requested */
%if &plot = T %then %do;
Title " CIF plot by &grp";
proc sgplot data=_plot;
yaxis values=(0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1.0);
xaxis values= (&xaxisvalue);
step y=CIF x=time /group=status;
%if &grp ~= %STR() %then %do;
/* Report both event of interest and competing risk results */
%if &compete = T %then %do;
inset ("%TRIM(&event1.)="="&PVAL1" "%TRIM(&event2.)="="&PVAL2")/position=topright border
TITLE="Gray's p-value" LABELALIGN=LEFT;
%end;
/* Only report event of interest */
%else %do;
inset ("Gray's p-value="="%TRIM(&PVAL1)")/position=topright border LABELALIGN=LEFT;
%end;
%end;
run;
%end;
/* If time estimates were requested */
%if &time_cnt > 0 %then %do;
DATA _est;
set _plot;
%do i = 1 %to &time_cnt;
%let timept = %SCAN(&timelist,&i,' ');
/* Create indicator if time is less than or equal to time of interest */
if &time <= &timept then _LT&i = 1;
else _LT&i = 0;
%end;
RUN;
PROC SQL;
create table _est2
as select *, max(&time) as max_time, max(&time*_LT1) as _max1
%do i = 2 %to &time_cnt; , max(&time*_LT&i) as _max&i %end;
from _est
group by status;
QUIT;
DATA _est3;
set _est2;
/* Subset on time points of interest */
%do i = 1 %to &time_cnt;
%let timept = %SCAN(&timelist,&i,' ');
if &time = _max&i then do;
_time = &timept;
output;
end;
%end;
RUN;
DATA _est3;
set _est3;
/* Convert to character */
cif_c = PUT(cif,percent8.2);
lcl_c = PUT(LowerCI,percent8.2);
ucl_c = PUT(upperCI,percent8.2);
/* Make sure estimates are not for times beyond the length of the data */
if _time > max_time then do;
cif_c = 'NA';
Lcl_c = 'NA';
Ucl_c = 'NA';
end;
/* Combine estimate and CI */
rate = TRIM(cif_c) || " (" || TRIM(LEFT(LCL_c)) || ", " || TRIM(LEFT(UCL_c)) || ")";
RUN;
PROC SORT DATA = _est3;
by status _time;
RUN;
proc report nowd data=_est3 style(report)={rules=GROUPS}
style(header)={BACKGROUNDCOLOR=none} LS=256 STYLE(COLUMN) = {JUST = C};
col status _time rate;
define status/order style={just=l};
LABEL _time = "Time (&units)"
rate = 'CIF Estimate (95% CI)';
RUN;
%end;
TITLE;
%let n=(&n+1);
%end;
/* If not in debug mode */
%if &debug = F %then %do;
/* Delete intermediate datasets */
PROC DATASETS lib=work noprint;
delete _events _plot _stat1 _stat1plot %if &compete = T %then %do; _stat2 _stat2plot %end;
%if &time_cnt > 0 %then %do; _est _est2 _est3 %end; _cif_temp;
QUIT;
%end;
%mend;
Also check the log to see if you're getting messages about invalid paths or file names.
The naming a file with a different extension, docx for rtf, than Microsoft uses may not help due to the increasingly obnoxious "extension does not match contents" stuff Microsoft has been doing. name as RTF and Save-As to docx if needed.
Hi Ballardw:
I have checked log message several times and there are not any warning or error messages. At the beginning, I tried RTF, but it doesn't work. Then I use doc, sometimes it works, but most of times, it also doesn't work. ' It doesn't work' means I can get work document, then it pop out a message with like " open a read only copy', then I open it, nothing is inside. I don't know why. below is the shortcut.
Make sure to open the RTF file with Word, not a text editor. The graph won't show in a text editor.
For your code - add some put statements to make sure the logic is working the way you intendded.
Test if the following works. If it generates a file that opens and shows a graph then your doing something wrong...most likely in your conditonal logic.
ods rtf file="c:\_localdata\test.rtf" style=meadow;
proc sgplot data=sashelp.class;
scatter x=weight y=height/group=sex;
run;
ods rtf close;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.