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

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.

1 ACCEPTED SOLUTION

Accepted Solutions
Cynthia_sas
SAS Super FREQ

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:

TS_note_example.png  

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:

both_methods.png

Hope this helps,

Cynthia

 

View solution in original post

7 REPLIES 7
Cynthia_sas
SAS Super FREQ

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:

TS_note_example.png  

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:

both_methods.png

Hope this helps,

Cynthia

 

sm4
Quartz | Level 8 sm4
Quartz | Level 8

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.

Cynthia_sas
SAS Super FREQ

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):

template_startpage_no_5obs.png

 

  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:

template_proc_report_striped_one_page.png

 

  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

sm4
Quartz | Level 8 sm4
Quartz | Level 8

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!

 

ballardw
Super User

 

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.

 

Cynthia_sas
SAS Super FREQ
Hi: To @ballardw's point about not overwriting base.template.table. ... that's why I left it my template as template X. Most table templates will implicitly inherit from base.template.table, so if I don't override anything else, then the cellstyle in my template definition essentially gets added to what is in base.template.table.

Cynthia
sm4
Quartz | Level 8 sm4
Quartz | Level 8

Thank you for the suggestion!

SAS Innovate 2025: Register Now

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!

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
  • 7 replies
  • 2751 views
  • 4 likes
  • 3 in conversation