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

Based on this document:

 

https://support.sas.com/resources/papers/proceedings14/2033-2014.pdf

 

I created the attached result and using the attached code,

figure.png

but I want to produce my own template that creates output as this (tables with multi-rows and partial grids):

figure.png

 

Does anyone know how to achieve this? Or a good source to learn writing the language used in ods template. Much thanks! 

1 ACCEPTED SOLUTION

Accepted Solutions
Cynthia_sas
SAS Super FREQ

Thanks, @Reeza for the shout out on the paper. I actually mocked up some fake (summarized) data for this question and came up with this using PROC REPORT and ODS RTF:

for_latex.png

I put ODS LATEX statements in the code too, but I don't have an application to render the LaTeX files (and I don't do command lines any more).

 

  Anyway, I agree -- writing a template for a table like this seems unnecessary to me when PROC REPORT can do the heavy lifting.

 

  Cynthia

 

Here's all the code, fake data and all:

data forlatex;
  length Grp $5 Type $6  Cat $4;
  infile datalines dlm=' ';
  input Type $ Cat $ value Grp $;
datalines;
Market Low -32.83 EWAVG
Market  2  -3.36  EWAVG
Market  3  12.48  EWAVG
Market  4  31.22  EWAVG
Market High 97.89 EWAVG
Micro Low -34.76 EWAVG
Micro  2  -3.60  EWAVG
Micro  3  12.36  EWAVG
Micro  4  31.29  EWAVG
Micro High 104.34 EWAVG
Small Low -29.12 EWAVG
Small  2  -3.22  EWAVG
Small  3  12.56  EWAVG
Small  4  31.31  EWAVG
Small High 91.90 EWAVG
Big Low -25.21 EWAVG
Big  2  -2.90  EWAVG
Big  3  12.60  EWAVG
Big  4  30.93  EWAVG
Big High 80.46 EWAVG
Market Low 15.56 XSTD
Market  2  4.82  XSTD
Market  3  4.51  XSTD
Market  4  6.81  XSTD
Market High 61.57 XSTD
Micro Low 16.00 XSTD
Micro  2  4.81  XSTD
Micro  3  4.49  XSTD
Micro  4  6.81  XSTD
Micro High 65.95 XSTD
Small Low 13.49 XSTD
Small  2  4.84  XSTD
Small  3  4.52  XSTD
Small  4  6.83  XSTD
Small High 53.43 XSTD
Big Low 11.15 XSTD
Big  2  4.77  XSTD
Big  3  4.50  XSTD
Big  4  6.74  XSTD
Big High 41.73 XSTD
;
run;


proc format ;
  value $grpfmt 'EWAVG'='Average of Annual ^{newline 1}EW Average Values^{newline 1} All Stocks'
                'XSTD' = 'Average of Annual Cross-^{newline 1}Section Standard Deviations^{newline 1} All Stocks';
run;
ods escapechar='^';
 
ods rtf file='c:\temp\try_report.rtf' style=journal;
ods latex path='c:\temp' file='try_report.tex' style=journal;
Title 'Show in RTF and LaTeX';
proc report data=forlatex;
  column Type Grp,Cat,value;
  define Type / group order=data ' ';
  define Grp / across order=data ' ' f=$grpfmt.; 
  define Cat / across order=data ' '  
         style(header)={bordertopcolor=black bordertopstyle=solid bordertopwidth=2px};
  define value / analysis ' ';
  compute before / style={just=l fontweight=bold};
    line 'Sorting on Momentum, ^{style[fontstyle=italic]Mom}';
  endcomp;
run;;
ods latex close;
ods rtf close;
title;

 

 

 

View solution in original post

14 REPLIES 14
Reeza
Super User

Are you looking for a formatted report or do you really need latex?

 

SAS will output nice clean tables to PDF directly with less work than the ODS template. 

 

Page 9 here illustrates an example of clinical reports.

http://www2.sas.com/proceedings/forum2008/173-2008.pdf

Cynthia_sas
SAS Super FREQ

Thanks, @Reeza for the shout out on the paper. I actually mocked up some fake (summarized) data for this question and came up with this using PROC REPORT and ODS RTF:

for_latex.png

I put ODS LATEX statements in the code too, but I don't have an application to render the LaTeX files (and I don't do command lines any more).

 

  Anyway, I agree -- writing a template for a table like this seems unnecessary to me when PROC REPORT can do the heavy lifting.

 

  Cynthia

 

Here's all the code, fake data and all:

data forlatex;
  length Grp $5 Type $6  Cat $4;
  infile datalines dlm=' ';
  input Type $ Cat $ value Grp $;
datalines;
Market Low -32.83 EWAVG
Market  2  -3.36  EWAVG
Market  3  12.48  EWAVG
Market  4  31.22  EWAVG
Market High 97.89 EWAVG
Micro Low -34.76 EWAVG
Micro  2  -3.60  EWAVG
Micro  3  12.36  EWAVG
Micro  4  31.29  EWAVG
Micro High 104.34 EWAVG
Small Low -29.12 EWAVG
Small  2  -3.22  EWAVG
Small  3  12.56  EWAVG
Small  4  31.31  EWAVG
Small High 91.90 EWAVG
Big Low -25.21 EWAVG
Big  2  -2.90  EWAVG
Big  3  12.60  EWAVG
Big  4  30.93  EWAVG
Big High 80.46 EWAVG
Market Low 15.56 XSTD
Market  2  4.82  XSTD
Market  3  4.51  XSTD
Market  4  6.81  XSTD
Market High 61.57 XSTD
Micro Low 16.00 XSTD
Micro  2  4.81  XSTD
Micro  3  4.49  XSTD
Micro  4  6.81  XSTD
Micro High 65.95 XSTD
Small Low 13.49 XSTD
Small  2  4.84  XSTD
Small  3  4.52  XSTD
Small  4  6.83  XSTD
Small High 53.43 XSTD
Big Low 11.15 XSTD
Big  2  4.77  XSTD
Big  3  4.50  XSTD
Big  4  6.74  XSTD
Big High 41.73 XSTD
;
run;


proc format ;
  value $grpfmt 'EWAVG'='Average of Annual ^{newline 1}EW Average Values^{newline 1} All Stocks'
                'XSTD' = 'Average of Annual Cross-^{newline 1}Section Standard Deviations^{newline 1} All Stocks';
run;
ods escapechar='^';
 
ods rtf file='c:\temp\try_report.rtf' style=journal;
ods latex path='c:\temp' file='try_report.tex' style=journal;
Title 'Show in RTF and LaTeX';
proc report data=forlatex;
  column Type Grp,Cat,value;
  define Type / group order=data ' ';
  define Grp / across order=data ' ' f=$grpfmt.; 
  define Cat / across order=data ' '  
         style(header)={bordertopcolor=black bordertopstyle=solid bordertopwidth=2px};
  define value / analysis ' ';
  compute before / style={just=l fontweight=bold};
    line 'Sorting on Momentum, ^{style[fontstyle=italic]Mom}';
  endcomp;
run;;
ods latex close;
ods rtf close;
title;

 

 

 

Cynthia_sas
SAS Super FREQ

...And, with a slightly different structure to the input data, you can get the break in the line above the 2 groups:

diff_latex.png

 

It just depends on which form of data there is.

 

Cynthia

 

Here's the alternate data and program:

data fakedata;
  length Type $6  Cat $4;
  infile datalines dlm=' ';
  input Type $ Cat $ EWVAL XSVAL  ;
datalines;
Market	Low	-32.83	15.56
Market	2	-3.36	4.82
Market	3	12.48	4.51
Market	4	31.22	6.81
Market	High	97.89	61.57
Micro	Low	-34.76	16
Micro	2	-3.6	4.81
Micro	3	12.36	4.49
Micro	4	31.29	6.81
Micro	High	104.34	65.95
Small	Low	-29.12	13.49
Small	2	-3.22	4.84
Small	3	12.56	4.52
Small	4	31.31	6.83
Small	High	91.9	53.43
Big	Low	-25.21	11.15
Big	2	-2.9	4.77
Big	3	12.6	4.5
Big	4	30.93	6.74
Big	High	80.46	41.73
;
run;
  

ods rtf file='c:\temp\diff_data.rtf' style=journal;
ods latex path='c:\temp' file='diff_data.tex' style=journal;
Title 'Show in RTF and LaTeX';
proc report data=fakedata;
  column Type ('Average of Annual ^{newline 1}EW Average Values^{newline 1} All Stocks' Cat,EWVAL) blank 
              ('Average of Annual Cross-^{newline 1}Section Standard Deviations^{newline 1} All Stocks' Cat,XSVAL);
  define Type / group order=data ' ';
  define Cat / across order=data ' '  
         style(header)={bordertopcolor=black bordertopstyle=solid bordertopwidth=2px};
  define ewval / analysis ' ';
  define blank / computed ' '
         style(header)={bordertopcolor=white bordertopstyle=none bordertopwidth=0px};
  define xsval / analysis ' ';
  compute blank;
    blank = ' ';
  endcomp;
  compute before / style={just=l fontweight=bold};
    line 'Sorting on Momentum, ^{style[fontstyle=italic]Mom}';
  endcomp;
run;;
ods latex close;
ods rtf close;
title;
Sasadomo
Calcite | Level 5

Hi Cynthia, 

 

Thank your very much for the detailed solution using Proc Report. This is indeed is a great alternative to directly producing latex tables. Though the .tex produced in this process does not give nice results, the rtf version of the table looks great! But the second version has the table structure but there's no entries on data.

 

Could you point me to guide that breaks down components in the proc report command? I can't really understand the how the code works exactly now. 

 

Thank you very much!

Cynthia_sas
SAS Super FREQ
Hi, How odd...somehow, it looks like you might have used the wrong data with one of my programs. Each program was designed to work with the data structure that I used. Did you run my code unchanged using the data intended for each program?

cynthia
Sasadomo
Calcite | Level 5
Yes, I runned it with everything unchanged. Note that I am using SAS on WRDS
Reeza
Super User

Post the log. 

Sasadomo
Calcite | Level 5

here's the log 

 

 

 
 1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 SYMBOLGEN:  Macro variable _SASWSTEMP_ resolves to 
             /home/columbia/zz71/.sasstudio/.images/9097d6ba-62ba-4ce8-9a3a-bfd78
             519bad7
 SYMBOLGEN:  Some characters in the above value which were subject to macro 
             quoting have been unquoted for printing.
 SYMBOLGEN:  Macro variable GRAPHINIT resolves to GOPTIONS RESET=ALL 
             GSFNAME=_GSFNAME;
 NOTE: ODS statements in the SAS Studio environment may disable some output 
 features.
 73         
 74         options validvarname=V7 symbolgen mprint mlogicnest spool details;
 75         libname mast '/wrdslin/nyse/sasdata/taqs';
 NOTE: Libref MAST was successfully assigned as follows: 
       Engine:        V9 
       Physical Name: /wrdslin/nyse/sasdata/taqs
 76         libname zz02 '/scratch/columbia/zz89';
 NOTE: Libref ZZ02 was successfully assigned as follows: 
       Engine:        V9 
       Physical Name: /scratch/columbia/zz89
 77         libname zz '/home/columbia/zz71/zz';
 NOTE: Libref ZZ was successfully assigned as follows: 
       Engine:        V9 
       Physical Name: /home/columbia/zz71/zz
 78         
 79         data fakedata;
 80           length Type $6  Cat $4;
 81           infile datalines dlm=' ';
 82           input Type $ Cat $ EWVAL XSVAL  ;
 83         datalines;
 
 NOTE: Invalid data for EWVAL in line 86 1-19.
 NOTE: Invalid data for XSVAL in line 87 1-19.
 RULE:      ----+----1----+----2----+----3----+----4----+----5----+----6----+----
 
 87  CHAR   Market.4.31.22.6.81                                                  
     ZONE   467667030332330323322222222222222222222222222222222222222222222222222
     NUMR   D12B5494931E2296E8100000000000000000000000000000000000000000000000000
        70             
 NOTE: Invalid data errors for file CARDS occurred outside the printed range.
 NOTE: Increase available buffer lines with the INFILE n= option.
 Type=Market Cat=Mark EWVAL=. XSVAL=. _ERROR_=1 _N_=1
 NOTE: Invalid data for EWVAL in line 90 1-17.
 NOTE: Invalid data for XSVAL in line 91 1-18.
 
 91  CHAR   Micro.3.12.36.4.49                                                   
     ZONE   466760303323303233222222222222222222222222222222222222222222222222222
     NUMR   D932F93912E3694E49000000000000000000000000000000000000000000000000000
        70             
 NOTE: Invalid data errors for file CARDS occurred outside the printed range.
 NOTE: Increase available buffer lines with the INFILE n= option.
 Type=Market Cat=Micr EWVAL=. XSVAL=. _ERROR_=1 _N_=2
 NOTE: Invalid data for EWVAL in line 94 1-22.
 NOTE: Invalid data for XSVAL in line 95 1-18.
 
 95  CHAR   Small.2.-3.22.4.84                                                   
     ZONE   566660302323303233222222222222222222222222222222222222222222222222222
     NUMR   3D1CC929D3E2294E84000000000000000000000000000000000000000000000000000
        70             
 NOTE: Invalid data errors for file CARDS occurred outside the printed range.
 NOTE: Increase available buffer lines with the INFILE n= option.
 Type=Micro Cat=Micr EWVAL=. XSVAL=. _ERROR_=1 _N_=3
 NOTE: Invalid data for EWVAL in line 98 1-21.
 NOTE: Invalid data for XSVAL in line 99 1-20.
 
 99  CHAR   Big.Low.-25.21.11.15                                                 
     ZONE   466046702332330332332222222222222222222222222222222222222222222222222
     NUMR   2979CF79D25E21911E150000000000000000000000000000000000000000000000000
        70             
 NOTE: Invalid data errors for file CARDS occurred outside the printed range.
 NOTE: Increase available buffer lines with the INFILE n= option.
 Type=Small Cat=Smal EWVAL=. XSVAL=. _ERROR_=1 _N_=4
 NOTE: Invalid data for EWVAL in line 102 1-16.
 NOTE: Invalid data for XSVAL in line 103 1-20.
 
 103 CHAR   Big.High.80.46.41.73                                                 
     ZONE   466046660332330332332222222222222222222222222222222222222222222222222
     NUMR   29798978980E46941E730000000000000000000000000000000000000000000000000
        70             
 NOTE: Invalid data errors for file CARDS occurred outside the printed range.
 NOTE: Increase available buffer lines with the INFILE n= option.
 Type=Big2 Cat=Big EWVAL=. XSVAL=. _ERROR_=1 _N_=5
 NOTE: SAS went to a new line when INPUT statement reached past the end of a 
       line.
 NOTE: The data set WORK.FAKEDATA has 5 observations and 4 variables.
 NOTE: DATA statement used (Total process time):
       real time           0.01 seconds
       cpu time            0.00 seconds
       
 104        ;
 
 105        run;
 106        
 107        
 108        ods rtf file='/scratch/columbia/zz89/diff_data.rtf' style=journal;
 NOTE: Writing RTF Body file: /scratch/columbia/zz89/diff_data.rtf
 109        ods latex path='/scratch/columbia/zz89' file='diff_data.tex'
 109      ! style=journal;
 NOTE: Writing LATEX Body file: diff_data.tex
 110        Title 'Show in RTF and LaTeX';
 111        proc report data=fakedata;
 112          column Type ('Average of Annual ^{newline 1}EW Average
 112      ! Values^{newline 1} All Stocks' Cat,EWVAL) blank
 113                      ('Average of Annual Cross-^{newline 1}Section Standard
 113      ! Deviations^{newline 1} All Stocks' Cat,XSVAL);
 114          define Type / group order=data ' ';
 115          define Cat / across order=data ' '
 116                 style(header)={bordertopcolor=black bordertopstyle=solid
 116      ! bordertopwidth=2px};
 117          define ewval / analysis ' ';
 118          define blank / computed ' '
 119                 style(header)={bordertopcolor=white bordertopstyle=none
 119      ! bordertopwidth=0px};
 120          define xsval / analysis ' ';
 121          compute blank;
 122            blank = ' ';
 123          endcomp;
 124          compute before / style={just=l fontweight=bold};
 125            line 'Sorting on Momentum, ^{style[fontstyle=italic]Mom}';
 126          endcomp;
 127        run;
 
 127      !     ;
 NOTE: Character values have been converted to numeric 
       values at the places given by: (Line):(Column).
       1:10   
 NOTE: There were 5 observations read from the data set WORK.FAKEDATA.
 NOTE: PROCEDURE REPORT used (Total process time):
       real time           0.11 seconds
       cpu time            0.04 seconds
       
 
 128        ods latex close;
 129        ods rtf close;
 130        title;
 131        
 132        OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 SYMBOLGEN:  Macro variable GRAPHTERM resolves to GOPTIONS NOACCESSIBLE;
 145
Cynthia_sas
SAS Super FREQ

Hi:

  It looks like the DATA step program to make the fake data never worked right. Here's a comma-separated version of the fake data file for the second example:

data fakedata;
  length Type $6  Cat $4;
  infile datalines dlm=',' dsd;
  input Type $ Cat $ EWVAL XSVAL  ;
datalines;
Market,Low,-32.83,15.56 
Market,2,-3.36,4.82 
Market,3,12.48,4.51 
Market,4,31.22,6.81 
Market,High,97.89,61.57 
Micro,Low,-34.76,16 
Micro,2,-3.6, 4.81 
Micro,3,12.36,4.49 
Micro,4,31.29,6.81 
Micro,High,104.34,65.95 
Small,Low,-29.12,13.49 
Small,2,-3.22,4.84 
Small,3,12.56,4.52 
Small,4,31.31,6.83 
Small,High,91.9, 53.43
Big,Low,-25.21,11.15 
Big,2,-2.9,4.77 
Big,3,12.6,4.5 
Big,4,30.93,6.74 
Big,High,80.46,41.73
;
run;

The rest of the program is the same.

 

Cynthia

Sasadomo
Calcite | Level 5
That works perfectly! Thank you!
Sasadomo
Calcite | Level 5

Hi Reeza,

 

Thank you for your response.

 

I do need article-ready tables from SAS and since the result will include a large number of tables, it is much easier to do this by some script/template. 

Reeza
Super User

@Sasadomo wrote:

Hi Reeza,

 

Thank you for your response.

 

I do need article-ready tables from SAS and since the result will include a large number of tables, it is much easier to do this by some script/template. 


Agreed, but latex is possible but not worth the effort would be my suggestion. 

ODS PDF and PROC REPORT is enough. If these are clinical reports search lexjansen.com for lots of example code. 

Sasadomo
Calcite | Level 5
Thank you for the information on the website! I will see if I can find anything useful on this site

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 14 replies
  • 4769 views
  • 2 likes
  • 3 in conversation