Import xlsx file into SAS from static url link - sas

I am new to SAS but used to working in python.
In python, I can read an xlsx file from a static Box.com link by calling pandas read excel function on the Box link.
pd.read_excel("https://box.com/shared/static/<url>.xlsx")
I'm hoping to do something similar in SAS. When I try
PROC IMPORT DATAFILE="https://box.com/shared/static/<url>.xlsx"
OUT=WORK.MYEXCEL
DBMS=XLSX
REPLACE;
RUN;
SAS tries to look for a document with the name "https://box.com/shared/static/.xlsx".
When I try
filename xlsxFile http "https://box.com/shared/static/<url>.xlsx";
PROC IMPORT DATAFILE=xlsxFile
OUT=WORK.MYEXCEL
DBMS=XLSX
REPLACE;
RUN;
I get
ERROR: This "filename URL" access method is not supported by "proc import". Please copy the file to local disk before running the
procedure.
Is there an easy way to have SAS access files from this type of URL? I've checked these few threads:
https://communities.sas.com/t5/General-SAS-Programming/import-excel-file-from-the-web/td-p/134158
https://communities.sas.com/t5/SAS-Programming/Importing-XLSX-from-URL-Issue/td-p/446758
https://communities.sas.com/t5/SAS-Programming/proc-import-xlsx-from-url/td-p/635834
And it seems like I may need to do some work to get SAS to create a file object from the URL but I don't quite understand how the code is working and when I naively try something similar:
filename xlsxFile http "https://box.com/shared/static/<url>.xlsx";
data file;
n=-1;
infile xlsxFile recfm=s nbyte=n length=len;
input;
file "file_name.xlsx" recfm=n;
put _infile_ $varying32767. len;
run;
PROC IMPORT OUT= input DATAFILE= "file_name.xlsx"
DBMS=xls REPLACE;
SHEET="sheet_name";
GETNAMES=YES;
RUN;
I get the following error:
Spreadsheet isn't from Excel V5 or later. Please open it in Excel and Save as V5 or later
Requested Input File Is Invalid
ERROR: Import unsuccessful. See SAS Log for details.
Any help would be appreciated. The reason I'd like to do it this way is because the files at the static links are updated daily and I want to avoid having to copy files to the SAS server every day. So if this won't work I am also interested in other work arounds that would accomplish the same thing.
I can obviously write a script that will fetch the updated files and write them to the server where SAS can access them as needed, but wanted to see if I could get this to work first.
Using the Box API from within SAS would also be another option if anyone has successfully gotten that to work. As I mentioned I am new to SAS so trying to access the API seemed like it would be too difficult at the moment.
Thank you!

You'll definitely need to download the file. As Tom notes in comments, make sure to check this is really an xlsx file; but assuming it is, some suggestions for dealing with it.
Copying it over by hand like you're doing is doable, and I'll put some code that works at the bottom of the answer, but it's way overkill nowadays - you're probably reading decade-old papers from before the modern day of SAS. In particular, you should use PROC HTTP to GET the file, rather than using the URL directly - it's just much easier that way.
Another possibility is you could use python for this! Regardless of your SAS setup, you can use python to script SAS, or use SAS to run Python, very easily nowadays. SASPy project (on github) for SAS 9, or the SAS SWAT package (also on github I believe) for connecting to SAS Viya, lets you very easily talk back and forth with Python and SAS, even in production - I do it all the time. And on top of that, you can even write SAS user-written functions in python now - so there're a bunch of ways to get your Python into SAS, if you want. I am a SAS (primary) developer, but I use Python for web-related stuff, since it's just better at it. See my paper for more details, or lots of other resources on the subject.
Assuming you just want to import the file and don't want to keep track of the excel file ultimately, you can just read it from a temp filename, which will clean itself up afterwards:
filename _httpin temp;
proc http method="get"
url="https://github.com/snoopy369/SASL/raw/master/Excel%20Precision.xlsx"
out=_httpin;
run;
proc import file=_httpin out=test dbms=xlsx replace;
run;
If you want the excel file saved somewhere (sounds like you don't, but if you do), then instead of temp assign that httpin filename to a real location.
filename _httpin "c:\temp\whatever.xlsx";
If you really want to do that binary file copy business, do it this way:
filename _httpin temp;
filename _httpout "c:\temp\Excel Precision.xlsx";
proc http method="get"
url="https://github.com/snoopy369/SASL/raw/master/Excel%20Precision.xlsx"
out=_httpin;
run;
data _null_;
_in = fopen('_httpin','I',1,'B');
_out= fopen('_httpout','O',1,'B');
rec='20'x;
do while (Fread(_in) eq 0);
rc = fget(_in,rec,1);
rc = fput(_out,rec);
rc = fwrite(_out);
end;
rc = fclose(_in);
rc = fclose(_out);
run;
proc import file=_httpout out=test dbms=xlsx replace;
run;

Related

SAS xlsx libname engine on Viya 4

I'm trying to access an xlsx file stored on SAS Drive from a SAS Studio session, all on Viya 4.
This piece of SAS documentation suggests that it works on Viya just like in SAS 9.4: https://go.documentation.sas.com/doc/en/pgmsascdc/v_031/acpcref/titlepage.htm
However it doesn't go into any details or examples and when I try this code it runs successfully but the resulting library is empty (and in fact changing the path to a non-existing file won't change anything, so I doubt that the file access was working in the first place):
libname myxls xlsx "/folders/myfolder/file.xlsx";
proc contents data=myxls._all_;
run;
You need to use the filesrvc access method to access files on SAS Drive.
filename myfile filesrvc
folderpath = '/folders/myfolder/'
filename = 'file.xlsx'
;
You cannot have direct libname access to files stored on SAS Drive, but you can import them into SAS using proc import:
proc import
file = myfile
dbms = 'xlsx'
out = myxls
replace;
run;
If you have persistent storage then you certainly can use standard libname access so long as that file is in that storage location.
If you don't and you'd like to still have libname access, one workaround is to physically copy the xlsx file to your WORK directory, then assign a new libname statement:
filename source filesrvc
folderpath = '/folders/myfolder/'
filename = 'file.xlsx'
;
filename dest "%sysfunc(pathname(work))/file.xlsx";
/* Use fcopy to copy from SAS Drive to WORK */
%let rc = %sysfunc(fcopy(source, dest));
libname myxls xlsx "%sysfunc(pathname(work))/file.xlsx";
More information on filesrvc:
https://go.documentation.sas.com/doc/en/pgmsascdc/v_031/lestmtsglobal/p0qapul7pyz9hmn0zfoefj0c278a.htm
You get empty library if the path isn't correct. Or if your system doesn't understand your path. Remember, you have to have your folders on a server and not on your personal disc.
libname myxls "path\myfolder\file.xlsx";
proc contents data=myxls._all_;
run;
This works for me just fine. Maybe your system had issues with using / instead of \ (my setup certainly doesn't work with / ). Or path wasn't correct. Can't be sure unless we get more details about your setup.

SAS Enterprise Guide: How to query library and export results to CSV [duplicate]

This question already has answers here:
SAS proc export to CSV: how to add double quotes
(4 answers)
Closed 2 years ago.
I'm sorry if this question has already been asked but I've searched around and cannot find a clear explanation on this.
I am new to SAS, I am trying to pull out logistic recs, separate by day, and save as date_warehouse#.csv
The data is stored in a library, let's call it 'WH' and referenced table is called 'TX'
This is easy to do in terminal but the outsourced IT guy is stonewalling me about connecting via terminal so I can use PIG/HIVE, so I am being forced to go through SAS.
I import the lib using the command:
libname WH_LIB sasioimp dsn="PDB" user="username" Password="PASSWORD" schema="WH";
I am able to do a
proc sql
*query here*
quit; run;
however these values are being stored then displayed in the UI, I do see an option to then manually export to CSV.
Is there a way I can process skip the display process, and run my query in the back-end to write directly to a CSV file?
I'd like to do something like this pseudo-code in SAS:
for warehouse in warehouses:
for date in dates:
results=*run query with date and warehouse*
filename=date+warehouse+".csv"
write(results, filename)
Is there a straightforward example to accomplish this which someone could please share?
Thanks!
libname myLib ......;
%let path = C:\users\demo\;
*get list of files in your library;
proc sql;
create table list_dsn as
select memname from sashelp.vtable where libname = "MYLIB";
quit;
*function/macro to export a csv file;
%macro export_csv(dsn=);
proc export out=&dsn datafile="&path.\&dsn.csv" dbms=csv replace;run;
%mend;
*execute macro for each name in the list of files;
data _null_;
set list_dsn;
str = catt('%export_csv(dsn=', memname, ');');
call execute (str);
run;
Here's a rough approach. I would not recommend this because you know have to ensure the types for each data set is being properly read into HIVE. SAS provides several methods to use python and connect directly to the SAS data bases using python. Look into saspy and sasswat for examples on how this can be accomplished, especially if you have Viya.
You can then save this as a .sas program and call it from the command line or run it as a stored process so that it executes by default. This could be simplified into a single step but this is straightforward to follow IMO.

Is there a way to import multiple excel sheets using code in SAS Enterprise when DBMS errors occur?

I wrote some code with the hope of importing multiple sheets, but I receive an error:
"ERROR: DBMS type XLSX not valid for import."
I looked into the error and tried XLS etc, and then checked
proc setinit; run;
The output did not include "---SAS/ACCESS Interface to PC Files" in which case I see that the advice is to use a csv file instead. That would be fine, except I am trying to import dozens of sheets in a macro (see below) from a single excel workbook. I'm not sure that it makes sense to save each sheet as a csv so that the macro can pull in all of the files. That would be labor intensive in the future, as these sheets will be updated maybe multiple times a year.
%let path = 'C:/Desktop/Folder';
%macro importsheet(sheet);
proc import out= &sheet
datafile = &path
dbms=XLSX replace;
getnames=yes;
run;
%mend;
%importsheet(sheet1);
My core question is this:
Is the csv option the only/best solution for what I am asking? My back up plan is to just do an autoexec, but I would like to make sure I've thoroughly explored writing a macro and discarded it as an option before I do that.
The fastest and easiest way to import all Excel Sheets is to use a libname reference.
libname myXL xlsx 'path to xlsx file';
proc copy in=myXL out=work; run;
This will not work if you're importing from a specific range.

exporting sas stored process output

I created a stored process but I want to export the output to Excel. My usual export statement doesn't work in the stored process.
%let _ODSDEST=none;
%STPBEGIN();
data x;
set sashelp.class;
run;
proc export data=x outfile = "//my documents/sp_test.xlsx" dbms=xlsx replace;
sheet="table1";
run;
* Begin EG generated code (do not edit this line);
;*';*";*/;quit;
%STPEND;
Is there a way to get this to work in the stored process?
One way to have a stored process return an excel file (actually in this case it's an xml file that excel will happily open) is to use ODS to output tagsets.excelxp (xml).
When you do this, you can use stpsrv_header to modify the HTML header. The first statement tells the browser to open the file with excel, the second tells it the file name. I believe for this header modification to work the stored process needs to deliver streaming results, not package results. But I could be wrong.
When I run below, I get a file download dialog box from the browser, allowing me to open or save the file. I'm running from Stored Process Web App, but should work fine when called from Information Delivery Portal.
%let _odsdest=tagsets.excelxp;
%let rc=%sysfunc(stpsrv_header(Content-type,application/vnd.ms-excel));
%let rc=%sysfunc(stpsrv_header(Content-disposition,attachment%str(;) filename=MyExcelFile.xls));
%stpbegin()
proc print data=sashelp.shoes (obs=&obs);
run;
%stpend()
did u check with your spelling proc exportd and outfile='mypath/my documents/myoutpt.xlsx' dbms=xlsx or outfile='mypath/my documents/myoutpt.xls' dbms=xls?? U can try with ODS also.
You can also try setting your STP up as a streaming web service, removing the %STPBEGIN and %STPEND macros, and sending to _webout using this macro: https://core.sasjs.io/mp__streamfile_8sas.html
The benefit of this, is that your code will subsequently work on Viya as well.

Import data from European Social Survey

I need to import data from European Social Survey databank to SAS.
I'm not very good at using SAS so I just naively tried importing the text file one gets but it stores it all in one variable.
Can someone maybe help me with what to do? Since there doesn't seem to be a guide on their webpage I reckon it has to be pretty easy.
It's free to register (and takes 5 secs) and I need all possible data for Denmark.
Edit: When downloading what they call a SAS file, what i get is a huge proc format and the same text file as one gets by choosing text.
The data in the text file isn't comma separated and the first row does not contain variable names.
Download it in SAS format. Save the text file in a location you can remember, and open the SAS file. It's not just one big proc format; it's a big proc format followed by a datastep with input code. It was probably created by SPSS (it fits the pattern of an SPSS saved .sas file anyhow). Look for:
DATA OUT.ESS1_4e01_0_F1;
Or something like that (that's what it is when I downloaded it). It's probably about 3/4 of the way down the page. You just need to change the code:
INFILE 'ESS1_4e01_0_F1.txt';
or similar, to be the directory you placed the text file in. Create a LIBNAME for OUT that goes to wherever you want to permanently save this, and do that at the start of the .sas file, replacing the top 3 lines like so.
Originally:
LIBNAME LIBRARY '';
LIBNAME OUT '';
PROC FORMAT LIBRARY=LIBRARY ;
Change these to:
libname out "c:\mystuff\"; *but probably not c:\mystuff :);
options fmtsearch=(out);
proc format lib=out;
Then run the entire thing.
This is the best solution if you want the formatted values (value labels) and variable labels. If you don't care about that, then it might be easier to deal with the CSV like Bob shows.
But the website says yu can download SAS format, why don't you?
You need a delimiter if all goes into one column.
data temp;
length ...;
infile 'file.csv' dlm=',';
input ...;
run;
As Dirk says, the web site says you can download a SAS dataset directly. However, if there's some reason you don't want to do that, choose a comma separated file (CSV) and use PROC IMPORT. Here is an example:
proc import out=some_data
datafile='c:\path\somedata.csv'
dbms=csv replace;
getnames=yes;
run;
Of course, this assumes the first row contains column names.