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:
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).
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;
Hope this helps,
cynthia
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;
Hope this helps,
cynthia
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.