Hi,
I'm trying to apply the data step (not proc report) version of this SAS tutorial to my needs. I am able to get it to do what I want...more or less..., but it only runs if I don't include my proc odstext statements (I am making a report with text, tables, and graphs).
i.e., this works:
data temp; set sashelp.class ; i=_n_; run; proc template; define table x; column i name age sex height weight; define i; print=off; end; cellstyle mod(i,2) as {background=pink }; end; ods rtf file="hello.rtf"; test data=temp; proc print data= temp; *etc.; run; ods rtf close; run;
But this does not:
data temp; set sashelp.class ; i=_n_; run; proc template; define table x; column i name age sex height weight; define i; print=off; end; cellstyle mod(i,2) as {background=pink }; end; ods rtf file="hello.rtf"; proc odstext; p "hello"; run; test data=temp; *THIS LINE now invalid in Enterprise Guide; proc print data= temp; *etc.; run; ods rtf close; run;
Any idea why this might be happening? I admit I don't have a fantastic grasp of template foundational knowledge, I just keep trying things out until they do what I need.
Hence I'm also wondering whether it's possible to use such a template on two tables (have to have the same columns? either way not working for me) in one document/ make two such templates for two different tables in one document? I can't fully understand how the 'test data=temp' statement connects the template with the table in question.
SAS 9.4 though Unix batch mode.
Thanks very much.
Hi:
That looks like an example that came from this Tech Support note:
http://support.sas.com/kb/23/647.html
and the challenge with that note is that you CANNOT have any kind of step boundary after the PROC TEMPLATE step or else the TEST statement will NOT work. Here's the example from the TS Notes, annotated:
So when you put your PROC step before the run (either PROC ODSTEXT or PROC PRINT, you ended the PROC TEMPLATE step.
Typically, as shown in the screen shot above and in the code segment below, you bind your data to you template using
file print ods=(template='x');
in a DATA _NULL_ program usually.
I like the PROC REPORT method that is shown at the top of that note. I've put both methods below.
data temp;
set sashelp.class ;
i=_n_;
run;
options center;
** Method 1: use PROC REPORT with and without computing i;
ods rtf file="c:\temp\Method1.rtf";
proc report data= temp;
title '1a) Proc Report Method: SASHELP.CLASS Using COMPUTE with I variable';
title2 'NOT using a TABLE template';
column i name age sex height weight;
define i / display noprint;
compute i;
if mod(i,2) ne 0 then
call define(_row_,'style','style={background=pink}');
endcomp;
run;
** can also do alternate highlighting without making variable I;
proc report data=sashelp.classfit;
title '1b) PROC REPORT Method: SASHELP.CLASSFIT Using COMPUTE without I variable';
title2 'NOT using a TABLE template';
column name age sex height weight lower upper;
compute name;
tmpvar + 1;
if mod(tmpvar,2) ne 0 then
call define(_row_,'style','style={background=pink}');
endcomp;
run;
ods rtf close;
** Method 2: Make a TABLE template and use with DATA _NULL_;
** does NOT use a TEST statement;
ods path work.tt(update) sasuser.templat(update) sashelp.tmplmst(read);
proc template;
define table x;
cellstyle mod(_row_, 2) ne 0 as {background=pink},
1 as {background=white};
end;
run;
ods rtf file="c:\temp\Method2.rtf";
title '2a) Template Method: SASHELP.CLASS';
data _null_;
set sashelp.class;
file print ods=
(template='x');
put _ods_;
run;
title '2b) Template Method: SASHELP.CLASSFIT';
data _null_;
set sashelp.classfit(keep=name age sex height weight lower upper);
file print ods=
(template='x');
put _ods_;
run;
ods rtf close;
Here's my output:
Hope this helps,
Cynthia
Hi:
That looks like an example that came from this Tech Support note:
http://support.sas.com/kb/23/647.html
and the challenge with that note is that you CANNOT have any kind of step boundary after the PROC TEMPLATE step or else the TEST statement will NOT work. Here's the example from the TS Notes, annotated:
So when you put your PROC step before the run (either PROC ODSTEXT or PROC PRINT, you ended the PROC TEMPLATE step.
Typically, as shown in the screen shot above and in the code segment below, you bind your data to you template using
file print ods=(template='x');
in a DATA _NULL_ program usually.
I like the PROC REPORT method that is shown at the top of that note. I've put both methods below.
data temp;
set sashelp.class ;
i=_n_;
run;
options center;
** Method 1: use PROC REPORT with and without computing i;
ods rtf file="c:\temp\Method1.rtf";
proc report data= temp;
title '1a) Proc Report Method: SASHELP.CLASS Using COMPUTE with I variable';
title2 'NOT using a TABLE template';
column i name age sex height weight;
define i / display noprint;
compute i;
if mod(i,2) ne 0 then
call define(_row_,'style','style={background=pink}');
endcomp;
run;
** can also do alternate highlighting without making variable I;
proc report data=sashelp.classfit;
title '1b) PROC REPORT Method: SASHELP.CLASSFIT Using COMPUTE without I variable';
title2 'NOT using a TABLE template';
column name age sex height weight lower upper;
compute name;
tmpvar + 1;
if mod(tmpvar,2) ne 0 then
call define(_row_,'style','style={background=pink}');
endcomp;
run;
ods rtf close;
** Method 2: Make a TABLE template and use with DATA _NULL_;
** does NOT use a TEST statement;
ods path work.tt(update) sasuser.templat(update) sashelp.tmplmst(read);
proc template;
define table x;
cellstyle mod(_row_, 2) ne 0 as {background=pink},
1 as {background=white};
end;
run;
ods rtf file="c:\temp\Method2.rtf";
title '2a) Template Method: SASHELP.CLASS';
data _null_;
set sashelp.class;
file print ods=
(template='x');
put _ods_;
run;
title '2b) Template Method: SASHELP.CLASSFIT';
data _null_;
set sashelp.classfit(keep=name age sex height weight lower upper);
file print ods=
(template='x');
put _ods_;
run;
ods rtf close;
Here's my output:
Hope this helps,
Cynthia
Thanks SO much for this extremely detailed reply. Checked out the data _null_ option and it definitely works now. I was really confused about why the template was open in the example and thought maybe that had to be the case for this to work, so thanks for correcting me.
I do have a couple of follow-up questions if that's ok.
I have a class table statement within the template that still seems to be taking effect - I had expected the 'x' to override that so I'm really happy. But there are a couple of things that aren't working that I expected to work:
1. I have another table that I would like to print on the same page as this specially-formatted one. That one doesn't need any special formatting and I'm happy with what I got through proc print. Previously both tables were able to fit on one page as desired with the help of a 'ods startpage=no' statement among other things. But now that the first table uses the 'x' template, the second table has been pushed to the next page.
2. Relatedly, I have included an 'options orientation= landscape topmargin = 0.10in bottommargin = 0.10in leftmargin = 0.20in rightmargin = 0.20in' statement before both of these tables in the rtf code. It worked perfectly before. Now, it is taking effect on the second table's page but not on the first/specially-formatted table's page. Does this mean I must include orientation/margins in the template for the table? I need to keep switching them throughout the document since I've got text, tables, and graphs.
Also, I was previously using formatting statements for each column within proc print - would it be correct to assume that all formatting (different for different columns) I was able to accomplish within proc print is also possible to accomplish in the define table statement or in other parts of the template? For example, using something like http://support.sas.com/documentation/cdl/en/odsug/61723/HTML/default/viewer.htm#a002639079.htm.
Thanks so much for your help. Please let me know if I should post these questions freshly and then I will accept your original as the solution. Just didn't want to do that now since it seems to close the post.
Hi, in all honesty, I would NOT use a custom TABLE template just to get alternate row striping on the report.
I would stick with the PROC REPORT method. If you want to take the time to open a track with Tech Support on your margin and page break issues, that would be the way to resolve those questions. Without your data and your code, it will be nearly impossible for someone to comment on the issues you're seeing in your results.
When I ran a quick test using STARTPAGE=NO and 2 DATA _NULL_ steps, with my template, I got everything on one page (still portrait, using only 5 obs each):
Then with my template/DATA _NULL_ step followed by a PROC REPORT (each only using 5 obs), I got all the output on one page.You can see I did a PROC REPORT because I used a COMPUTE BEFORE to get the title/caption at the top of the table:
So for me, I don't see any problem using STARTPAGE=NO. That's why I recommend either switching to PROC REPORT where you can control the striping directly in the procedure and control the columns and other things you want to do or pursue the Template method, but open a track with Tech Support to investigate your specific issues.
Sorry I can't be of more help.
Cynthia
Thanks for your response! I understand. I'm doing more than just alternate striping - I'm trying to also get the first and last rows to have bigger fontsize and to have top/bottom borders. My rows are different month ranges; I need to emphasize certain month ranges over others.
As long as proc report can accomplish all the formatting I need, it should not be problematic to switch to it at all. Thanks for the tip!
Your issue is more an RTF issue than the template or ods text.
proc template; define table base.template.table; cellstyle mod(_row_, 2) and ^(_style_ like '%Header') as {backgroundcolor=#c6faff}, ^(mod(_row_, 2)) and ^(_style_ like '%Header') as {backgroundcolor=#80e9ff}; end; run;
Change the colors as desired above. This replaces the base table definition and most procedure output will be striped as they inherit from this one. I hope you have your ODS PATH settings such that you are not replacing SAS templates though.
Thank you for the suggestion!
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.