I have SAS code in which there is following line of code is included
% include "/sas/dev/compare.sas";
it is at location on server
/sas/cpm/dev/code
So, at present what I am doing manually go to above path and open each .sas code(in a Folder, you can say there are 4 codes location at /sas/cpm/dev/code) and check whether %include "/sas/dev/compare.sas" line of code is present or not
Can anyone help me without checking/open manually .sas code how to check whether %include "/sas/dev/compare.sas"; is exist or not
Can anyone , please help me how to write in sas,
We can pass each code through macro right
Thanks
You can do this by:
Listing all the .sas files in each folder,
Create a datasetp / infile statement for each file,
Search each line in the file for % include "/sas/dev/compare.sas";
If line is found, print to the log the file name and line number
Code:
%let extension=sas;
%let FolderPath=\\sas\SASDATA\momo\;
%macro check_file_path(f=);
DATA _null_;
infile "&f" dsd ;
length string $200.;
input string $;
if string=&check. then put "&f. " "includes # line " _N_= ;
run;
%mend;
Data List_files;
rc=FILENAME('FMyRep',"&FolderPath");
did=DOPEN('FMyRep');
memcnt=DNUM(did);
*count number of members - including subfolders;
DO i=1 TO memcnt;
*for each member, test extension and store filename;
filevar=LOWCASE(DREAD(did,i));
file_path=cats("&FolderPath.",filevar);
IF LOWCASE(SCAN(filevar,-1,".")) EQ LOWCASE("&extension") THEN
OUTPUT;
END;
rc=DCLOSE(did);
rc=FILENAME('FMyRep');
KEEP filevar file_path;
RUN;
data _null_;
set List_files;
call execute('%check_file_path(f='||file_path||')');
put file_path=;
run;
Output:
file_path=\\sas\SASDATA\momo\file1.sas
file_path=\\sas\SASDATA\momo\file2.sas
file_path=\\sas\SASDATA\momo\file3.sas
file_path=\\sas\SASDATA\momo\file4.sas
Log: file4.sas is the only one that doesn't have this % include "/sas/dev/compare.sas";
\\sas\SASDATA\momo\file1.sas includes # line _N_=1
\\sas\SASDATA\momo\file2.sas includes # line _N_=1
\\sas\SASDATA\momo\file4.sas includes # line _N_=1
you can do it by using fileexist function
%let myfile = "/sas/dev/compare.sas";
%macro filecheck;
%if %sysfunc(fileexist(&myfile))
%then % include "/sas/dev/compare.sas";
%else %put The external file &myfile does not exist.;
%mend;
%filecheck;
Related
I wanna append string to a text file at beginning and end of proc sql statment, I tried like below
libname DXZ 'libpath';
%macro processlogger(msg);
filename logfile '../Processlog/processlog.txt';
data _null_;
file logfile;
put "%superq(message)";
run;
%mend;
%processlogger ('Begin');
proc sql;
select * from DZ.NoofDaysin_Reje /* Mispelled name */
run;
%processlogger('End');
I seems to messing up in macro variable, is there any other way I can do this, Thanks
If you want to use a data step to append to a text file then you need to add the MOD keyword to the FILE statement.
If you want to print the value of a macro variable that might have quotes and other strange characters in a data step then it is probably best to use symget() to retrieve the value into a datastep variable and print that.
Make sure to reference the macro variable that you created msg and not some other macro variable message.
If you don't want quotes to be included in the value of a macro variable then do not add them.
%macro processlogger(msg);
data _null_;
file '../Processlog/processlog.txt' mod;
length message $32767 ;
message=symget('msg');
put message ;
run;
%mend;
%processlogger(Starting at %sysfunc(datetime(),datetime24.3));
%processlogger(Ending at %sysfunc(datetime(),datetime24.3));
You can also use PRINTTO to redirect your log to a text file. And you have the option to either append to the original file or replace. Example here.
/*Redirect your log file*/
proc printto log='../Processlog/processlog.txt';
run;
/* Your Code Here */
/* Reset log path to default */
proc printto;
run;
I was running the following code:
%LET TIME_INTERVAL='MINUTE15';
/*
* Get the file names of a specific location
*/
%MACRO get_filenames(location,filenames);
filename _dir_ "%bquote(&location.)";
data &filenames(keep=fname);
handle=dopen( '_dir_' );
if handle > 0 then do;
count=dnum(handle);
do i=1 to count;
fname=dread(handle,i);
output &filenames;
end;
end;
rc=dclose(handle);
run;
filename _dir_ clear;
%MEND;
%MACRO NBBO (fname);
DATA TICKERS_NBBO;
INFILE &fname;
INPUT SYMBOL $;
RUN;
%mend;
%MACRO CALCU(DATE_VAR);
%get_filenames('./groups',filenames);
data _null_;
set filenames;
by fname;
if fname =: "&TIME_INTERVAL";
%NBBO(fname);
run;
%mend;
However, I got the error: ERROR: No logical assign for filename FNAME.
I was wondering what is the reason that caused this?
There are lots of csv files in the folder groups. I was trying to run the NBBO macro on each of the files and load each of the files into a dataset with infile statement.
You're mixing up data step code and macro code in a manner that's not permitted. You can't extract the contents of the variable fname and use it to populate a macro variable in this way. Instead you're passing the text fname to that macro variable, which then doesn't work.
You also can't run another data step inside a data step in this manner. You need to use one of the various methods for executing it after the data step terminates or during execution.
Finally, it's entirely unclear to me what you're really doing here: because you're going to end up with just one of those files in the dataset.
I think you may want something like this, which is much easier. I use the FILEVAR option in infile, which uses the value of a variable; I have to make some changes to how you calculate fname (I think you have to do this anyway, it has no directory name in it).
%MACRO get_filenames(location,filenames);
filename _dir_ "%bquote(&location.)";
data &filenames(keep=fname);
length fname $512;
handle=dopen( '_dir_' );
if handle > 0 then do;
count=dnum(handle);
do i=1 to count;
fname=catx('\',"%bquote(&location.)",dread(handle,i));
output &filenames;
end;
end;
rc=dclose(handle);
run;
filename _dir_ clear;
%MEND;
%get_filenames(location=c:\temp\cars, filenames=fnam);
data tickers_nbbo;
set fnam;
infile a filevar=fname dlm=',';
input symbol $;
run;
If you really do need to call a data step separately, you either need to use CALL EXECUTE, DOSUBL, or construct macro calls in another way (PROC SQL SELECT INTO, %INCLUDE, etc.).
data _null_;
%let _EFIRR_=0;
%let _EFIREC_=0;
file '/home/abc/demo/sale.csv' delimiter=',' DSD;
put country=;
run;
I wrote this code but couldn't find anything in the log. Shouldn't I be getting country=xyz in the log?
The FILE statement is used to write out to files. I believe you were attempting to read country values from the file instead.
You need the INFILE statement:
data _null_;
%let _EFIRR_=0;
%let _EFIREC_=0;
/* infile statement points to the file which is being read */
infile '/home/abc/demo/sale.csv' delimiter=',' DSD;
/* Input statement specifies which columns to populate from the file */
input country $;
/* A put statement in a data step without an associated */
/* file statement will output lines in the log */
put country=;
run;
this is my code to read multiple multisheet excel in sas its giving an error which i am attaching in last.i am only reading first sheet named summary of every excel in that particular folder
%macro sks2sas01(input=d:\excels,out=work.tt);
/* read files in directory */
%let dir=%str(%'dir %")&input.%str(\%" /A-D/B/ON%');
filename myfiles pipe %unquote(&dir);
data list1; length fname $256.;
infile myfiles truncover;
input myfiles $100.;
/* put _infile_;*/
fname=quote(upcase(cats("&input",'\',myfiles)));
out="&out";
drop myfiles;
call execute('
PROC IMPORT DBMS=EXCEL2002 OUT= _1
DATAFILE= '||fname||' REPLACE ;
sheet="summary";
RUN;
proc append data=_1 base='||out||' force; run;
proc delete data=_1; run;
');
run;
filename myfiles clear;
%mend sks2sas01;
%sks2sas01(input=c:\sasupload\excels,out=work.tt);
hereby i am attaching error i am getting:
GOPTIONS ACCESSIBLE;
%macro sks2sas01(input=d:\excels,out=work.tt);
/* read files in directory */
%let dir=%str(%'dir %")&input.%str(\%" /A-D/B/ON%');
filename myfiles pipe %unquote(&dir);
data list1; length fname $256.;
infile myfiles truncover;
input myfiles $100.;
/* put _infile_;*/
fname=quote(upcase(cats("&input",'\',myfiles)));
out="&out";
drop myfiles;
call execute('
PROC IMPORT DBMS=EXCEL2002 OUT= _1
DATAFILE= '||fname||' REPLACE ;
sheet="summary";
RUN;
proc append data=_1 base='||out||' force; run;
proc delete data=_1; run;
');
run;
filename myfiles clear;
%mend sks2sas01;
%sks2sas01(input=c:\sasupload\excels,out=work.tt);
ERROR: Insufficient authorization to access PIPE.
ERROR: Error in the FILENAME statement.
I had this exact same problem the other day. I had no authorization for the pipe command, and dir using sftp wasn't working for me either. This alternative solution worked great for me. In a nutshell, you're going to use some oldschool SAS directory commands to read every file within that directory, and save only the ones that end in .xlsx.
You can consider the name of your Excel files .-delimited, scan the filename of each one backwards, and look at just the first word to obtain only those Excel files. For example:
File name.xlsx
Backwards:
Delimiter
v
xlsx.name File
^^^^
First word
Step 1: Read all XLSX files in the directory, and create a dataset of them
filename dir 'C:\MyDirectory';
data XLSX_Files;
DirID = dopen("dir");
do i = 1 to dnum(DirID);
file_name = dread(DirID, i);
if(upcase(scan(file_name, 1, '.', 'b') ) = 'XLSX') then output;
end;
rc=dclose(DirID);
drop i rc DirID;
run;
Step 2: Read all of those names into a pipe-delimited macro variable
proc sql noprint;
select file_name, count(file_name)
into :XLSX_Files separated by '|',
:tot_files
from XLSX_Files;
quit;
Step 3: Import them all in a macro loop
%macro import_all;
%do i = 1 %to &tot_files;
proc import file="C:\MyDirectory\%scan(&XLSX_Files,&i,|)"
out=XLSX_&i
dbms=xlsx replace;
run;
%end;
%mend;
%import_all;
You can then stack or merge them as you need.
data Master_File;
set XLSX_1-XLSX_&tot_files;
run;
OR
data Master_File;
merge XLSX_1-XLSX_&tot_files;
by key;
run;
i m new to sas and studying different ways to do subject line task.
Here is two ways i knew at the moment
Method1: file statement in data step
*DATA _NULL_ / FILE / PUT ;
data _null_;
set engappeal;
file 'C:\Users\1502911\Desktop\exportdata.txt' dlm=',';
put id $ name $ semester scoreEng;
run;
Method2: Proc Export
proc export
data = engappeal
outfile = 'C:\Users\1502911\Desktop\exportdata2.txt'
dbms = dlm;
delimiter = ',';
run;
Question:
1, Is there any alternative way to export raw data files
2, Is it possible to export the header also using the data step method 1
You can also make use of ODS
ods listing file="C:\Users\1502911\Desktop\exportdata3.txt";
proc print data=engappeal noobs;
run;
ods listing close;
You need to use the DSD option on the FILE statement to make sure that delimiters are properly quoted and missing values are not represented by spaces. Make sure you set your record length long enough, including delimiters and inserted quotes. Don't worry about setting it too long as the lines are variable length.
You can use CALL VNEXT to find and output the names. The LINK statement is so the loop is later in the data step to prevent __NAME__ from being included in the (_ALL_) variable list.
data _null_;
set sashelp.class ;
file 'class.csv' dsd dlm=',' lrecl=1000000 ;
if _n_ eq 1 then link names;
put (_all_) (:);
return;
names:
length __name__ $32;
do while(1);
call vnext(__name__);
if upcase(__name__) eq '__NAME__' then leave;
put __name__ #;
end;
put;
return;
run;