Exporting SAS Data into FTP using SAS - sas

I wanted to export SAS dataset from SAS into FTP. I can export csv file (or txt file) using the following command:
%macro export_to_ftp(dsn= ,outfile_name= );
Filename MyFTP ftp "&outfile_name."
HOST='ftp.site.com'
cd= "&DATA_STRM/QC"
USER=&ftp_user.
PASS=&ftp_pass.;
PROC EXPORT DATA= &dsn. OUTFILE= MyFTP DBMS=%SCAN(&outfile_name.,2,.) REPLACE;
RUN; filename MyFTP clear;
%mend;
%export_to_ftp(dsn=lib1.dataset ,outfile_name=dataset.csv);
But couldn't use it to export SAS dataset. Can anybody please help me.
Thank you!

PROC EXPORT is not used to export SAS datasets, it's used to convert SAS datasets to other formats. You normally wouldn't use the FTP filename method to transfer SAS datasets; you would either use SAS/CONNECT if you are intending to transfer from one SAS machine to another (if you license SAS/CONNECT and want help with this, please say so), or use normal (OS) FTP processes to transfer the file. It is technically possible to use the FTP filename method to transfer a SAS file (as a binary file, reading then writing byte-by-byte) but that's error-prone and overly complicated.
The best method if you're using SAS to drive the process is to write a FTP script in your OS, and call that using x or %sysmd, passing the filename as an argument. If you include information about your operating system, something could be easily drawn up to help you out.
Note: if you're on a server, you need to verify that you have 'x' permission; that's often locked down. If you do not, you may not be able to run this entirely from SAS.

As Joe says, you do not use PROC EXPORT to create a file to be transferred using FTP. The safest way to exchange SAS datasets is to use PROC CPORT to create a transport file. Here is a modified version of your original macro:
%macro export_to_ftp(dsn= ,outfile_name= );
%let DBMS=%UPCASE(%SCAN(&outfile_name.,2,.));
%if &DBMS ne CSV and &DBMS ne TXT and &DBMS ne CPT %then %do;
%put &DBMS is not supported.;
%goto getout;
%end;
%if &DBMS=CPT %then %do;
filename MyFTP ftp "&outfile_name."
HOST='ftp.site.com'
cd= "&DATA_STRM/QC"
USER=&ftp_user.
PASS=&ftp_pass.
rcmd='binary';
PROC CPORT DATA= &dsn.
FILE = MyFTP;
RUN;
%end;
%else %do;
filename MyFTP ftp "&outfile_name."
HOST='ftp.site.com'
cd= "&DATA_STRM/QC"
USER=&ftp_user.
PASS=&ftp_pass.
rcmd='ascii';
PROC EXPORT DATA= &dsn.
OUTFILE= MyFTP
DBMS= &dbms REPLACE;
RUN;
%end;
filename MyFTP clear;
%getout:
%mend;
%export_to_ftp(dsn=lib1.dataset ,outfile_name=dataset.csv);
%export_to_ftp(dsn=lib1.dataset ,outfile_name=dataset.cpt);
By convention, this will use a file extension of cpt to identify that you want a SAS transport file created. Whoever receives the file would use PROC CIMPORT to convert the file back to a SAS dataset:
filename xpt 'path-to-transport-file';
proc cimport data=dataset infile=xpt;
run;
filename xpt clear;
Note that SAS transport files should be transferred as binary files; the other two formats are text files; hence the different filename statements.
One of many advantages of using PROC CPORT is that the entire data set is copied, including any indexes that may exist. Also, you are protected against problems related to using the data set on operating systems different from the one that created it.

What OP requires is a Binary transfer to the FTP server. That can be done via a data step.
filename ftpput ftp "<full name of your file with ext>" cd='<DIR>' user='<username>' pass='<password>' host='<ftp host>' recfm=s debug; /*ftp dir stream connection*/
filename myfile '/path/to/your/library/dsfile.sas7bdat' recfm=n; /*local file*/
/*Binary Transfer -- recfm=n*/
data _null_;
n=1;
infile myfile nbyte=n;
input;
file ftpput;
put _infile_ ##;
run;
You can tweak the input/put statements to your specifications. But otherwise, this works for me.
I guess, you can also try the fcopy function with the above filenames. That should work too, with binary transfers.
options nonotes; /*do not want the data step or ftp server notes*/
data _null_;
fcop=fcopy("myfile","ftpput");
if fcop = 0 /*Success code*/ then do;
put '|Successfully copied src file to FTP!|';
end;
else do;
msg=sysmsg();
put fcop= msg=;
end;
run;
options notes;

Looking at your code, you seem to have forgotten the quotes (") around &ftp_user. and &ftp_pass.
Otherwise your code looks okay to me.
If that does not do the trick, some error message would come in handy.
Also note that your use of scan to determine the dbms is tricky: what if a future filename has (multiple) dots in it? you are better of putting -1 (part after last dot) instead of 2 (part after second dot) as a parameter to your scan function.

I would actually do it the other way around
Export your file locally and then upload it with the FTP program
something like this: (note I used CSV.. but please use what ever file format)
You may need to edit that a little more but the base logic is there
%macro export_to_ftp(dsn= ,outfile_name= );
PROC EXPORT DATA= &dsn. OUTFILE= &file_to_FTP..CSV DBMS=%SCAN(&outfile_name.,2,.) REPLACE;
RUN;
Filename MyFTP ftp "c:\FTP_command.bat"
put "ftp &ftp_user.:&ftp_pass.#ftp.site.com "
put "cd &DATA_STRM./QC"
put "c:\&file_to_FTP..CSV ";
x "c:\FTP_command.bat";
%mend;
%export_to_ftp(dsn=lib1.dataset ,outfile_name=dataset.csv);

Related

list all SAS members in a ZOS libray from remote sas session

On our ZOS (mainframe) we have a library called
USER.PGM.WEEKLY
where several sas programs(members) are located
I am trying to retrieve a list of all the member from my PCSAS with following code
rsubmit;
proc source indd='C009BSA.BSA.BIBHLP.SAS' select *; print;run;
endrsubmit;
signoff;
But it errors out with
ERROR 22-322: Syntax error, expecting one of the following: ;, DIRDD, INDD, MAXIOERROR, NOALIAS,
NODATA, NOMEM, NOPRINT, NOSUMMARY, NOTSORTED, NULL, OUTBLK, OUTDD, PAGE, PRINT,
SEARCH.
ERROR 180-322: Statement is not valid or it is used out of proper order.
I have tried to google around to find the solution but haven't been able to sort it out.
How ever i am able to download one member at the time by running
filename inpds 'USER.PGM.WEEKLY' shr;
proc download infile =inpds(PPRINT_TO_PDF)
outfile='L:\Work\PPRINT_TO_PDF';
run;
Try something like this. You might need to use an actual physical file instead of using the TEMP filename engine on ZOS.
filename dirlist temp;
rsubmit;
filename dirlist temp;
proc source indd='C009BSA.BSA.BIBHLP.SAS' dirdd=dirlist; run;
proc download infile=dirlist outfile=dirlist; run;
endrsubmit;
https://v8doc.sas.com/sashtml/os390/z0217440.htm
If you just want to download all of the members of the PDS then PROC DOWNLOAD can do that for you without you needing to have the list of members.
filename outdir '/where/I/want/to/write/';
rsubmit;
filename indir 'C009BSA.BSA.BIBHLP.SAS';
proc download infile=indir(*) outfile=outdir; run;
endrsubmit;

SAS Rename file on SFTP

my task in SAS is to upload a file via SFTP with extension tmp and after the upload is finished to rename it to csv. As I am no adminstrator of the server my debugging output is limited and I am struggeling with the correct implementation. The following code generates no error in the SAS Log but does not rename the file:
%let host=...;
%let sftpUser = ...;
%let filename_tmp=20160301-test01-sas.tmp;
%let filename=20160301-test01-sas.csv;
%let sftpPath=...;
FILENAME test SFTP "&sftpPath.&filename_tmp."
HOST="&host."
USER="&sftpUser."
DEBUG;
proc export data=.... outfile=test dbms=csv replace;
run;
data _null_;
rc=rename("test&sftpPath.&filename_tmp.", "test&sftpPath.&filename.", 'file');
run;
I already read the docs for filename and rename but I could not get a clue on how to combine both statements - any help or hints or alternatives are greatly appreciated.
Thanks
Stephan
There is a script running on the destination server scanning for csv files and move them every minute so there is the danger that a file is moved when the upload is not completed.
I'm pretty sure that there's no danger of the file being moved, as it should be locked until the upload completes. Just try it.

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.

SAS+files compatibilty between Linux and Windows

Is it possible to make the files (.csv or .xls or .txt) created in Linux to windows compatibility mode. Here all the files are routed to result_path location and they should be in windows compatibility mode.
I am using the following SAS code to create files in Linux.
%let result_pth = abc/test_folder/test_nas_loc;
filename outref "&result_pth./&sysuserid..linux_file.txt";
PROC PRINTTO PRINT =outref new;run;
data new;
set sashelp.class;
run;
proc print noobs;run;
proc printto;
run;
Assuming you're referring to making a file with the correct line termination character(s), you can do this with the TERMSTR option on the file statement. This only works when using put in the data step to write to a file.
data _null_;
set have;
file "myfile.txt" termstr=crlf dlm=',';
put _all_;
run;
XLS or XLSX files should be binary files and shouldn't require line terminators.

CSV document import by using filename statement

I want to read a CSV document by using a filename statement in SAS but Excel already included variable names as the first line when I input variable names by using an input statement--there is going to be a mistake. How can I deal with this situation?
filename outdata "C:\Users\Xiang\Desktop\crime2005.csv";
data crime;
infile outdata dlm="," dsd ;
run;
proc means mean std maxdec=1 ;
run;
proc print;
run;
First off - you're confusing things a bit by saying 'via the filename statement'. This is via datastep. The filename statement happens to be a relatively small component of this.
Second, let's get this into proper SAS indenting so we can see what's going on:
filename outdata "C:\Users\Xiang\Desktop\crime2005.csv";
data crime;
infile outdata dlm="," dsd ;
input [your-variable-list];
run;
proc means data=crime mean std maxdec=1 ;
run;
proc print data=crime;
run;
Data steps and Procs end with run (except for Procs that end in quit). Each of these is a separate step, so always include the run. Always include data= , unless you're using some fancy programming trick. 'data' always is in the first column, not indented - data step is the master statement, not filename.
These make your code readable, and protect you from mistakes. Readable code is important, even if you work alone; it means you understand what you wrote five years ago, five years from now.
Your original question - how do I avoid the errors from the header row?
filename outdata "C:\Users\Xiang\Desktop\crime2005.csv";
data crime;
infile outdata dlm="," dsd firstobs=2;
input [your-variable-list];
run;
There you go. FIRSTOBS=2 tells SAS to skip the first line [ie, the header row].
One thing you might try is a PROC IMPORT. PROC IMPORT with DBMS=CSV will do something really handy for you - it will put in the log a complete data step with all of the code to read the file in yourself. So while I don't actually recommend PROC IMPORT for production code [as it often makes poor decisions as to character/numeric formatting and lengths, among other things], it is very helpful to see how to get started with an input statement.
proc import file=outdata out=crime dbms=csv replace;
run;
Then look at your log, and copy that code out (removing line numbers); now you can modify it to your heart's content.