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

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

1 ACCEPTED SOLUTION

Accepted Solutions
Cynthia_sas
SAS Super FREQ

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

2 REPLIES 2
Cynthia_sas
SAS Super FREQ

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

 

dagremu
Obsidian | Level 7
Thank you, Cynthia! I really appreciate your help. And I had never heard of the Report Writing Interface -- looks powerful.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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
  • 2 replies
  • 5223 views
  • 2 likes
  • 2 in conversation