The SAS Output Delivery System and reporting techniques

Different alignment for 2 different spanned headers in PROC REPORT with ODS HTML

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 8
Accepted Solution

Different alignment for 2 different spanned headers in PROC REPORT with ODS HTML

When defining header text using the COLUMN statement in PROC REPORT, I want to separately control the justification of each header. E.g. the first column's header should be left-justified, and the next column right-justified. I want this to work for HTML output.

 

Here's another post on this forum which shows how to do this for RTF output. You can do inline formatting with an escape character, e.g., "^S={just=r}My header". However, this does not work for the default HTML destination.

 

Here's some example code to work with:

 

proc report data=sashelp.classfit(obs=5) nowd;
	columns ('Name' name) ('True/Weight' weight)
		('Predicted/Weight' predict) ('Predicted/95% CI' lower upper);
	define name / '';
	define weight / '';
	define predict / '';
	define lower / '';
	define upper / '';
run;

It produces this table in the default HTML output:

 

Classfit Table with Headers.png

 

How would I, say, make "Name" left-aligned, "True Weight" and "Predicted Weight" right-aligned, and "Predicted 95%CI" center-aligned? To be clear, I'm not referring to the values in the table body, just to the headers at the top (in blue).


Accepted Solutions
Solution
‎02-21-2018 02:07 PM
SAS Super FREQ
Posts: 9,423

Re: Different alignment for 2 different spanned headers in PROC REPORT with ODS HTML

Hi:

  There are 2 ways to do this: 1) use PROC REPORT, but you'll also need to make some "helper" variables so you can apply differing justification to each header or 2) switch to the Report Writing Interface. Both methods are illustrated in this program.

** make "helper" variables for method #1;
data classfit;
  length nhd twhd pwhd pci $20;
  set sashelp.classfit;
  nhd =  'Name';
  twhd = 'True/Weight';
  pwhd = 'Predicted/Weight';
  pci =  'Predicted/95% CI';
  dummyvar = 1;
run;

ods html path='c:\temp' file='two_methods.html';

proc report data=classfit(obs=5) nowd split='/'
   style(column)={width=1.0in};
   title '1) Use helper variables for headers';
	columns dummyvar nhd,name  
             twhd,weight 
		     pwhd,predict  
             pci,(lower upper );
	define dummyvar /order noprint;
	define nhd / ' ' across style(header)={just=l vjust=b};
	define name / ' ';
	define twhd / ' ' across style(header)={just=r};
	define weight / ' ';
	define pwhd / ' ' across style(header)={just=r};
	define predict / ' ';
	define pci / ' '  across style(header)={just=c};
	define lower / ' ';
	define upper / ' ';
run;


title '2) Or, use RWI to write report and do column spanning';
data _null_; 
  set SASHELP.CLASSFIT (obs=5) end=last; 
  if _N_ = 1 then do; 
      dcl odsout obj(); 
      obj.table_start(); 
      obj.head_start(); 
	  ** Header row 1;
      obj.row_start(type: "Header"); 
      obj.format_cell(text: "Name", style_attr:"just=l vjust=b width=1in"); 
      obj.format_cell(text: "True/Weight", split:'/',style_attr:"just=r width=1in"); 
      obj.format_cell(text: "Predicted/Weight", split:'/', style_attr:"just=r width=1in"); 
      obj.format_cell(text: "Predicted/95% CI",split:'/', column_span:2, style_attr:"just=c"); 
      obj.row_end(); 
      obj.head_end(); 
    end;
  ** row for every obs;
      obj.row_start(); 
      obj.format_cell(data: name , style_attr: "just=l" ); 
      obj.format_cell(data: weight, style_attr: "just=r"); 
      obj.format_cell(data: predict, style_attr: "just=r"); 
      obj.format_cell(data: lower, style_attr: "just=r width=1in"); 
      obj.format_cell(data: upper, style_attr: "just=r width=1in"); 
      obj.row_end(); 
   
  if last then do; 
      obj.table_end(); 
    end; 
run; 
ods html close;

For the kind of control you want over the headers, using the "helper" variables as across items gives you that control just using STYLE overrides in the DEFINE statement. With ACROSS items, you need an ORDER or GROUP item as the left most column, which is what the DUMMYVAR helper variable is doing. The variable is given a value of 1 on each row, so it really just makes the other headers work. And it is a NOPRINT item, so you don't have to see it, you just need it to be there. I made the columns a bit wider than needed so you could see that the justifications were used.

 

Here's the output;

two_method.png

Hope this helps,

cynthia

 

View solution in original post


All Replies
Solution
‎02-21-2018 02:07 PM
SAS Super FREQ
Posts: 9,423

Re: Different alignment for 2 different spanned headers in PROC REPORT with ODS HTML

Hi:

  There are 2 ways to do this: 1) use PROC REPORT, but you'll also need to make some "helper" variables so you can apply differing justification to each header or 2) switch to the Report Writing Interface. Both methods are illustrated in this program.

** make "helper" variables for method #1;
data classfit;
  length nhd twhd pwhd pci $20;
  set sashelp.classfit;
  nhd =  'Name';
  twhd = 'True/Weight';
  pwhd = 'Predicted/Weight';
  pci =  'Predicted/95% CI';
  dummyvar = 1;
run;

ods html path='c:\temp' file='two_methods.html';

proc report data=classfit(obs=5) nowd split='/'
   style(column)={width=1.0in};
   title '1) Use helper variables for headers';
	columns dummyvar nhd,name  
             twhd,weight 
		     pwhd,predict  
             pci,(lower upper );
	define dummyvar /order noprint;
	define nhd / ' ' across style(header)={just=l vjust=b};
	define name / ' ';
	define twhd / ' ' across style(header)={just=r};
	define weight / ' ';
	define pwhd / ' ' across style(header)={just=r};
	define predict / ' ';
	define pci / ' '  across style(header)={just=c};
	define lower / ' ';
	define upper / ' ';
run;


title '2) Or, use RWI to write report and do column spanning';
data _null_; 
  set SASHELP.CLASSFIT (obs=5) end=last; 
  if _N_ = 1 then do; 
      dcl odsout obj(); 
      obj.table_start(); 
      obj.head_start(); 
	  ** Header row 1;
      obj.row_start(type: "Header"); 
      obj.format_cell(text: "Name", style_attr:"just=l vjust=b width=1in"); 
      obj.format_cell(text: "True/Weight", split:'/',style_attr:"just=r width=1in"); 
      obj.format_cell(text: "Predicted/Weight", split:'/', style_attr:"just=r width=1in"); 
      obj.format_cell(text: "Predicted/95% CI",split:'/', column_span:2, style_attr:"just=c"); 
      obj.row_end(); 
      obj.head_end(); 
    end;
  ** row for every obs;
      obj.row_start(); 
      obj.format_cell(data: name , style_attr: "just=l" ); 
      obj.format_cell(data: weight, style_attr: "just=r"); 
      obj.format_cell(data: predict, style_attr: "just=r"); 
      obj.format_cell(data: lower, style_attr: "just=r width=1in"); 
      obj.format_cell(data: upper, style_attr: "just=r width=1in"); 
      obj.row_end(); 
   
  if last then do; 
      obj.table_end(); 
    end; 
run; 
ods html close;

For the kind of control you want over the headers, using the "helper" variables as across items gives you that control just using STYLE overrides in the DEFINE statement. With ACROSS items, you need an ORDER or GROUP item as the left most column, which is what the DUMMYVAR helper variable is doing. The variable is given a value of 1 on each row, so it really just makes the other headers work. And it is a NOPRINT item, so you don't have to see it, you just need it to be there. I made the columns a bit wider than needed so you could see that the justifications were used.

 

Here's the output;

two_method.png

Hope this helps,

cynthia

 

Occasional Contributor
Posts: 8

Re: Different alignment for 2 different spanned headers in PROC REPORT with ODS HTML

Posted in reply to Cynthia_sas
Thank you, Cynthia! I really appreciate your help. And I had never heard of the Report Writing Interface -- looks powerful.
☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 2 replies
  • 269 views
  • 1 like
  • 2 in conversation