Here is an example that you can adapt to your data in SAS 9.4M4:
* Close all open destinations;
ods _all_ close;
* Set the MIME headers;
data _null_;
rc = appsrv_header('Content-type', 'application/vnd.ms-excel');
rc = appsrv_header('Content-disposition','attachment; filename="Class.xlsx"');
run;
* Create the file in a temporary location;
filename temp temp;
ods Excel file=temp style=HTMLBlue;
proc print data=sashelp.class; run; quit;
ods Excel close;
* Copy the file to _WEBOUT;
data _null_;
infile temp recfm=f lrecl=1;
file _webout recfm=n;
input;
put _infile_;
run;
This simplified code should work staring in SAS 9.4M5:
* Close all open destinations;
ods _all_ close;
* Set the MIME headers;
data _null_;
rc = appsrv_header('Content-type', 'application/vnd.ms-excel');
rc = appsrv_header('Content-disposition','attachment; filename="Class.xlsx"');
run;
* Create the file and return it to the client;
ods Excel file=_webout style=HTMLBlue;
proc print data=sashelp.class; run; quit;
ods Excel close;
Vince DelGobbo
SAS R&D
Can you show an example of your code, maybe using sashelp.class as an example dataset?
In my experience, if you're using ODS XLSX destination (or ODS EXCEL, or whatever) in a stored process, it works just the same as any other type of SAS session.
Is it possible that your SAS server that runs the stored process is an older version of SAS?
One approach - which will help you to separate the content from the style - is to call the STP from your workbook using VBA.
This way you can combine all of the flexible formatting logic available in excel, with the security and power of SAS for accessing and preparing the data itself.
A guide to this approach is available here: https://www.rawsas.com/2016/11/sas-as-a-service-an-easy-way-to-get-sas-into-excel-power-bi-and-000s-...
Note - if you have more than three tabs then make sure you have increased the number of multibridge connections from the default (3)! This will allow more parallel connections.
Please do not double-post. Everybody should be able to see all the answers already given.
Here is an example that you can adapt to your data in SAS 9.4M4:
* Close all open destinations;
ods _all_ close;
* Set the MIME headers;
data _null_;
rc = appsrv_header('Content-type', 'application/vnd.ms-excel');
rc = appsrv_header('Content-disposition','attachment; filename="Class.xlsx"');
run;
* Create the file in a temporary location;
filename temp temp;
ods Excel file=temp style=HTMLBlue;
proc print data=sashelp.class; run; quit;
ods Excel close;
* Copy the file to _WEBOUT;
data _null_;
infile temp recfm=f lrecl=1;
file _webout recfm=n;
input;
put _infile_;
run;
This simplified code should work staring in SAS 9.4M5:
* Close all open destinations;
ods _all_ close;
* Set the MIME headers;
data _null_;
rc = appsrv_header('Content-type', 'application/vnd.ms-excel');
rc = appsrv_header('Content-disposition','attachment; filename="Class.xlsx"');
run;
* Create the file and return it to the client;
ods Excel file=_webout style=HTMLBlue;
proc print data=sashelp.class; run; quit;
ods Excel close;
Vince DelGobbo
SAS R&D
Here are some examples:
ods Excel file=_webout style=HTMLBlue;
ods Excel options(sheet_name='Full Data');
proc report data=sashelp.class; run; quit;
ods Excel options(sheet_name='Gender=#byval(sex)');
proc report data=work.class;
by sex;
run; quit;
ods Excel close;
I cover this and more in my papers:
http://www.sas.com/reg/gen/corp/867226?page=Resources
http://support.sas.com/rnd/papers/intro-multisheet-excel-with-sas/ExcelXPPaperIndex.pdf
Vince DelGobbo
SAS R&D
Thanks for your response Vince. I tried using the provided code but then it displays the error message in excel (after an excel file gets downloaded) saying that " Excel cannot open the file 'Class.xlsx' because the file format or file extension is not valid. Verify that the file is not corrupted and that the file extension matches the format of the file".
Also, I have attached the code that i am using to generate the output.
data _null_;
rc = appsrv_header('Content-type', 'application/vnd.ms-excel');
rc = appsrv_header('Content-disposition','attachment; filename="Class.xlsx"');
run;
/* In this space are some Proc Sql Queries which derives the proc report data;*/
ods Excel file=_webout style=HTMLBlue;
ods excel options (sheet_name='Pivot Report');
%macro excel_PivotReport();
proc sql noprint;
select count(name) into :nTable from work.variable_names_aml;
quit;
%let ntable= %left(&ntable);
proc sql noprint;
select name into: va1 - :va&nTable. from work.variable_names_aml;
quit;
proc report nowd data=excel_pivot
Style (header)= [foreground=white background=teal];
columns &vlist.;
%do i=1 %to &nTable;
compute &&va&i.;
if &va1. = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
%end;
run;
%mend excel_PivotReport;
%excel_PivotReport ();
options missing=' ';
ods excel options (sheet_name='Sheet3');
proc report nowd data=sheet3_aml
Style (header)= [foreground=white background=teal];
columns SectorDesc TotCIF AvgTxnPerCIF TotAcct AvgTxnPerAcct TotTxns TotReversals TotCredit CRPctTot TotDebits DRPctTot;
compute SectorDesc;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute totcif;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute avgtxnpercif;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute totacct;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute avgtxnperacct;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute tottxns;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute totreversals;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute totcredit;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute crpcttot;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute totdebits;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
compute drpcttot;
if sectordesc = 'Grand Total' then do;
call define (_col_,'style','style={font_weight=bold background=white bordertopwidth=2px BORDERTOPSTYLE=double bordertopcolor=teal}');
end;
endcomp;
run;
Did the sample code that I provided work for you? If so, then which one? The ODS Excel destination can only write to _WEBOUT starting in SAS 9.4M5.
You can add this statement to your SAS code and then examine the SAS log to see the version number:
%put SAS version is &=SYSVLONG;
Vince DelGobbo
SAS R&D
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.