So I'm seeing something odd when trying to play with cell borders in a proc report going to an ODS EXCEL output. The client is requesting that some of the cells be merged horizontally--as far as I can tell, I can't do that via SAS, but I figured I could try and fake it with 0-width internal cell borders. This seems to work fine in the internal results viewer, but when transitioned to Excel, any cell with any border attribute defined instead gets completely surrounded.
SAS EG results viewer:
Excel output:
Desired Excel Output:
And my code:
ods excel file="&PDFPath./&&filename_value._&&qvar..xlsx" style=journal
options(embedded_titles='yes' embedded_footnotes='yes' sheet_interval='NONE' sheet_name="&qtrvar. Summary"
absolute_column_width='26,12,26,12' );
proc report data=source spanrows nowd
style(header)={bordertopwidth=.5 borderbottomwidth=.5
borderleftwidth=.5 borderrightwidth=.5 borderstyle=solid
bordercolor=black};
column ("Level 2" (row1 value1 row2 value2));
define row2 / " " style(column)={width=1000%};
define row1 / " " style(column)={width=1000% bordertopwidth=.5 borderbottomwidth=.5
borderleftwidth=.5 borderrightwidth=.5 borderstyle=solid
bordercolor=black};
define value1 / " " style(column)={width=1000% bordertopwidth=.5 borderbottomwidth=.5
borderleftwidth=.5 borderrightwidth=.5 borderstyle=solid
bordercolor=black};
define value2 / " " style(column)={width=1000% bordertopwidth=0 borderbottomwidth=0
borderleftwidth=0 borderrightwidth=.5 borderstyle=solid
bordercolor=black};
compute value1;
if row1 = 'Target Achieved: Y' then do;
call define('row1', 'style', 'style=[background=lightgreen font_weight=bold just=c]');
call define('value1', 'style', 'style=[background=lightgreen font_weight=bold just=c]');
call define('row2', 'style', 'style=[borderbottomwidth=.5]');
call define('value2', 'style', 'style=[borderbottomwidth=.5]');
end;
else if row1 = 'Target Achieved: N' then do;
call define('row1', 'style', 'style=[background=lightred font_weight=bold just=c]');
call define('value1', 'style', 'style=[background=lightred font_weight=bold just=c]');
call define('row2', 'style', 'style=[borderbottomwidth=.5]');
call define('value2', 'style', 'style=[borderbottomwidth=.5]');
end;
endcomp;
quit;
ods excel close;
The width is set to 1000 because I based the code off of another proc report in some code I inherited. The log doesn't show anything useful, unfortunately--no errors, no warnings, only the note telling me that the excel file was written to the output file.
With Excel output you should also show your ODS Excel definition, or Tagsets.Excel , or describe how you get the output to Excel.
There are options that may help with cell width as the body of a report procedure's output may well be controlled by the output from a previous procedure.
Which way are you attempting to mimic merging? It appears that you might be doing a top/bottom merge?
On a row where you have a borderleftwidth=0 the column to the left would also want a borderrightwidth=0 to suppress that border
It would also help to either provide data or provide an example of what you are attempting with one of the SAS supplied data sets like SASHELP.CLASS.
Cell width is not the issue here. It's just something Reeza caught on.
The hypothetical merge would be horizontal, across the first two columns of the bottom row. Every answer I've seen about doing that says it can't be done, which is why I'm trying to fake it with hidden cell borders.
If you look at the example images I posted above, you can see that the borders are coming out correctly in the SAS results viewer, but not when it is exported to excel. You are correct that I forgot to put the ods statement in, which I meant to; I'll go ahead and edit that back in to the original post now, as well as an example of what I'm actually trying to get the Excel to look like.
There isn't really much in the way of underlying data here; because I'm trying to reproduce what the client mocked up in Excel, it's literally just text pushed through a proc stream to an infile that will eventually have values (in the column value1) filled in with macro variables.
The main thing I'm trying to figure out here is why the borders are behaving differently in the Excel export: for whatever reason the rightmost column (the variable value2), which only has a right border in the results viewer, suddenly has a full border in Excel.
PROC PRODUCT_STATUS tells me it's SAS 9.4 M5. I'm accessing it through EG 7.11 HF3, if that matters.
The data set is created as follows:
%let ent_rb = foo;
proc stream outfile=text; begin
Rate: Baseline| &ent_rb| | |
Rate: Current | | | |
Improvement| | | |
Superior Performance| | | |
Target Achieved:| | | |
;;;;
data source;
infile text delimiter="|";
length row1 row2 $150;
input row1 $ value1 $ row2 $ value2 $ @@ ;
run;
This gets a little closer:
%let ent_rb = foo; data work.source; infile datalines dlm='|'; length row1 row2 $150; input row1 $ value1 $ row2 $ value2 $ ; datalines; Rate: Baseline| &ent_rb| | | Rate: Current | | | | Improvement| | | | Superior Performance| | | | Target Achieved:| | | | ; run; ods excel file="x:\data\junk.xlsx" style=journal options(embedded_titles='yes' embedded_footnotes='yes' sheet_interval='NONE' sheet_name="text. Summary"absolute_column_width='26,12,26,12' ); proc report data=work.source spanrows nowd style(header)={bordertopwidth=.5 borderbottomwidth=.5 borderleftwidth=.5 borderrightwidth=.5 borderstyle=solid bordercolor=black} ; column ("Level 2" (row1 value1 row2 value2)); define row2 / " " style(column)={}; define row1 / " " style(column)={ bordertopwidth=.5 borderbottomwidth=.5 borderleftwidth=.5 borderrightwidth=.5 borderstyle=solid bordercolor=black}; define value1 / " " style={ borderwidth=0 borderstyle=solid bordercolor=black}; define value2 / " " style={ borderwidth=0 }; compute value1; if row1 = 'Target Achieved: Y' then do; call define('row1', 'style', 'style=[background=lightgreen font_weight=bold just=c]'); call define('value1', 'style', 'style=[background=lightgreen font_weight=bold just=c]'); call define('row2', 'style', 'style=[borderbottomwidth=.5]'); end; else if row1 = 'Target Achieved: N' then do; call define('row1', 'style', 'style=[background=lightred font_weight=bold just=c]'); call define('value1', 'style', 'style=[background=lightred font_weight=bold just=c]'); call define('row2', 'style', 'style=[borderbottomwidth=.5]'); end; endcomp; quit; ods excel close;
To get your "Target Achieved" to span columns as you show in desired is beyond what I can' do at the moment.
A big cause of your extra lines was in the compute block for Value1.
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.