BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
suraj747
Fluorite | Level 6
Hi guys, can someone help me with following situation. I have 3 reports using proc report and 1 gplot.

Now all these reports have to go to one excel workbook in different sheets. I am able to make a single excel file with all of different sheets within it using the ods statement and it works absolutely fine.

However, the goal is to make this under a stored process and whenever that STP is called on a Web app, it should download the excel with all the same formatting and separate sheet names and content, like the way I am getting through ods excel file statement.

With all of my searching and everything, I found that Its easy when there is just one workbook with one sheet but gets difficult when you have give multiple sheets within the same workbook while retaining the formatting and style defined in proc report.

Please help. Thanks in advance.
1 ACCEPTED SOLUTION

Accepted Solutions
Vince_SAS
Rhodochrosite | Level 12

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

View solution in original post

11 REPLIES 11
suraj747
Fluorite | Level 6
I have 3 reports using proc report and 1 gplot.

Now all these reports have to go to one excel workbook in different sheets. I am able to make a single excel file with all of different sheets within it using the ods statement and it works absolutely fine.

However, the goal is to make this under a stored process and whenever that STP is called on a Web app, it should download the excel with all the same formatting and separate sheet names and content, like the way I am getting through ods excel file statement.

With all of my searching and everything, I found that Its easy when there is just one workbook with one sheet but gets difficult when you have give multiple sheets within the same workbook while retaining the formatting and style defined in proc report.

Please help. Thanks in advance.
Quentin
Super User

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?

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
suraj747
Fluorite | Level 6
Thanks for your reply. I have attached the code that I using in the comments below. The ODS excel file statement doesn't seem to work. Tried a couple of times with different methods but it just mess up the style defined and doesnt give me the different sheet in a single workbook output. At best, its giving the out put in the same sheet with messed up formatting.

I am not sure how to check if the SAS server that runs the STP has an older version or not.
AllanBowe
Barite | Level 11

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.

 

 

/Allan
SAS Challenges - SASensei
MacroCore library for app developers
SAS networking events (BeLux, Germany, UK&I)

Data Workflows, Data Contracts, Data Lineage, Drag & drop excel EUCs to SAS 9 & Viya - Data Controller
DevOps and AppDev on SAS 9 / Viya / Base SAS - SASjs
Vince_SAS
Rhodochrosite | Level 12

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

suraj747
Fluorite | Level 6
Thanks for your reply. How can I define different sheet names within the
same excel workbook using the provided code. If its just one sheet I can
simply define it using the ods excel option (sheet_name='...'). However, in
this case there are multiple proc reports that has to be delivered in
different sheet names within the same workbook.

Vince_SAS
Rhodochrosite | Level 12

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

suraj747
Fluorite | Level 6

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;

 

Vince_SAS
Rhodochrosite | Level 12

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

 

suraj747
Fluorite | Level 6
The version of SAS that I am using is 9.4M4. The code above for that version of SAS works. Thanks a lot 🙂

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 11 replies
  • 3935 views
  • 6 likes
  • 5 in conversation