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;
Related
I'm looking for getting the total number of rows (count) from a sas dataset file using SAS code.
I tried this code
data _null_; infile "C:\myfiles\sample.sas7bdat" end=eof; input; if eof then put "Lines read=====:" ; run;
This is the results OUTput I get(does not show the number of lines).Obviously, I did not get any actual number of lines in the file
Lines read=====:
NOTE: 1 record was read from the infile
"C:\myfiles\sample.sas7bdat".
However, I know the number of lines in that sample.sas7dat file is more than 1.
Please help!
The INFILE statement is for reading a file as raw TEXT. If you have a SAS dataset then you can just SET the dataset to read it into a data step.
So the equivalent for your attempted method would be something like:
data _null_;
set "C:\myfiles\sample.sas7bdat" end=eof;
if eof then put "Observations read=====:" _n_ ;
run;
One cool thing about sas7bdat files is the amount of metadata stored with them. The row count of that file is already known by SAS as an attribute. You can use proc contents to read it. Observations is the number of rows in the table.
libname files "C:\myfiles";
proc contents data=files.sample;
run;
A more advanced way is to open the file directly using macro functions.
%let dsid = %sysfunc(open(files.sample) ); /* Open the file */
%let nobs = %sysfunc(attrn(&dsid, nlobs) ); /* Get the number of observations */
%let rc = %sysfunc(close(&dsid) ); /* Close the file */
%put Total observations: &nobs
I am going to analyze a batch of SAS program file and I am stucked in getting the last modified time of program files. I have thought about X command but it was too inefficient.
I just find when I use infile statement:
data test;
infile 'D:\test.txt' truncover;
input ;
run;
Log shows the last modified time:
NOTE: The infile 'D:\test.txt' is:
Filename=D:\test.txt,
RECFM=V,LRECL=32767,File Size (bytes)=7,
Last Modified=2021/1/26 15:25:48,
Create Time=2021/1/26 15:25:42
As you can see, log window shows the infomation of file as a NOTE. However, my wish output is a variable filled with Last Modified Time.
Is there some option to get it while using infile statement?
Surely, Other efficient ways are welcomed, too.
Use functions FOPEN and FINFO
Example:
Show all available information items and their value for a sample data file.
filename datafile 'c:\temp\datafile.txt';
data _null_;
file datafile;
put 'Me data';
run;
data _null_;
fid = fopen('datafile');
if fid then do;
do index = 1 to foptnum(fid);
info_name = foptname(fid,index);
info_value = finfo(fid, info_name);
put index= info_name= #40 info_value=;
end;
rc = fclose(fid);
end;
run;
Will log information such as
index=1 info_name=Filename info_value=c:\temp\datafile.txt
index=2 info_name=RECFM info_value=V
index=3 info_name=LRECL info_value=32767
index=4 info_name=File Size (bytes) info_value=9
index=5 info_name=Last Modified info_value=26Jan2021:06:29:47
index=6 info_name=Create Time info_value=26Jan2021:06:28:23
I have some problems when I'm trying to generate a JSON file from dataset on SAS GUIDE. I generated a TEST.JSON:
{"TP_SMS":"1" "NM_REMETENTESMS":"00000159"},
{"TP_SMS":"2" "NM_REMETENTESMS":"00000159"},
{"TP_SMS":"3" "NM_REMETENTESMS":"00000159"},
{"TP_SMS":"4" "NM_REMETENTESMS":"00000159"},
{"TP_SMS":"5" "NM_REMETENTESMS":"00000159"},
.
.
.
{"TP_SMS":"9" "NM_REMETENTESMS":"00000159"},
The field TP_SMS is filled correct, but the second field is wrong - they are considering just the last position from my table.
Below there is my code white macro:
data teste30;
set MATABLES.EXIT_DATA;
RESP=cat(CD_CLIENTE,"|",ANWER_DATA);
ID=_N_;
call symputx('ID',ID);
call symputx('CD_CLIENTE',CD_CLIENTE);
call symputx('NM_PRIMNOMECLIENTE',NM_PRIMNOMECLIENTE);
call symputx('RESP',RESP);
call symputx('msgtext',msgtext);
run;
%macro MontaJSON(ID);
WRITE OPEN OBJECT;
WRITE VALUES "TP_SMS" "&ID";
WRITE VALUES "NM_REMETENTESMS" "&CD_CLIENTE";
WRITE CLOSE;
%mend MontaJSON(ID);
%macro SMSRecords;
%do i = 1 %to &dim_IDs;
%MontaJSON(&&&ID_&i);
%end;
%mend SMSRecords;
proc sql;
select id, CD_CLIENTE into :ID_1 - :ID_&SysMaxLong from work.teste30;
%let dim_IDs = &sqlObs;
quit;
proc json out="C:\TEMP\TEST.json" pretty nokeys nosastags;
write open array; /* container for all the data */
%SMSRecords;
write close; /* container for all the data */
run;
I expect this macro get all datas on sequence, as TP_SMS code:
{"TP_SMS":"1" "NM_REMETENTESMS":"00014578"},
{"TP_SMS":"2" "NM_REMETENTESMS":"21323445"},
{"TP_SMS":"3" "NM_REMETENTESMS":"23456753"},
{"TP_SMS":"4" "NM_REMETENTESMS":"00457663"},
{"TP_SMS":"5" "NM_REMETENTESMS":"00014795"},
{"TP_SMS":"6" "NM_REMETENTESMS":"00014566"},
{"TP_SMS":"7" "NM_REMETENTESMS":"00014578"},
{"TP_SMS":"8" "NM_REMETENTESMS":"00000122"},
{"TP_SMS":"9" "NM_REMETENTESMS":"00000159"}
Does anyone has some idea to solve it?
Tks
I would avoid generating all of those macro variables that are confusing your code.
Instead for that simple format you can just write the file directly instead of using PROC JSON.
data _null_;
set MATABLES.EXIT_DATA end=eof;
file "C:\TEMP\TEST.json" ;
if _n_=1 then put '[';
if not eof then delim=',';
put '{"TP_SMS":' id :$quote. ' "NM_REMETENTESMS":' CD_CLIENTE :$quote. '}' delim ;
if eof then put ']';
run;
Or if you really find that PROC JSON helps then use a similar data step to write the lines of code and use %INCLUDE to run the generated code.
filename code temp;
data _null_;
set MATABLES.EXIT_DATA ;
file code ;
put 'WRITE OPEN OBJECT;'
/ 'WRITE VALUES "TP_SMS" ' ID :$quote. ';'
/ 'WRITE VALUES "NM_REMETENTESMS" ' CD_CLIENTE :$quote. ';'
/ 'WRITE CLOSE;'
;
run;
proc json out="C:\TEMP\TEST.json" pretty nokeys nosastags;
write open array; /* container for all the data */
%include code;
write close; /* container for all the data */
run;
This line is your problem, it will only hold the last data point.
call symputx('CD_CLIENTE',CD_CLIENTE);
Instead, create a value for each ID, similar to how you created the IDs.
call symputx(catx('_', 'CD_CLIENTE', put(i, 8.-l)), CD_CLIENTE);
Then use it later on as &&&CD_CLIENTE&i
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;
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.).