问题
I have a saved csv_files
SAS Dataset with the following entries:
name path
aapl F:\Data\aapl.csv
msft F:\Data\msft.csv
ibm F:\Data\ibm.csv
goog F:\Data\goog.csv
I then use this SAS dataset to locate the csv files and import them into SAS using the following Macro which has a while
loop:
options symbolgen mlogic nomprint;
/*Leave options on as SAS will issue a message when Do While Loop is false*/
%let dsname = csv_files;
%let libto = l;
%Macro get_data(n,index);
/*n: is a counting macro variable representing the lower limit of the number of CSV files
to be read into SAS. Index: is a variable that can be thought of as
observation number( row number) representing the upper limit
of the number of CSV files to be read into SAS.*/
%DO %WHILE (&n <=&index);
data _NULL_;
set &libto..&dsname end=last;
if _N_ =&n then Do;
call symput('path',path); /* Get file path from CSV_files*/
call symput('dsn',name); /* Get dataset name from CSV_files*/
if not last then index+1; /* Create macro variable Index */
else if last then call symput ('index',index);
End;
run;
proc import datafile= "&path"
out= &libto..&dsn
dbms=dlm
replace;
delimiter="," ;
getnames=yes;
run;
%End;
%Mend get_data;
/* Macro Call*/
%get_data(1,4);
When I execute this Macro I always iterate over the first observation (in this case AAPL). It simply imports the aapl.csv file over and over....what's wrong?
UPDATE
Following the suggestion of Dmitry Shopin I changed my while
for a do
loop:
%let dsname = csv_files;
%let libto = l;
%Macro get_data(n,index);
%let dsname = csv_files;
%let libto = l;
%do i=&n %to &index;
data _NULL_;
set &libto..&dsname end=last;
if _N_ =&i then Do;
call symput('path',path); /* Get file path from CSV_files*/
call symput('dsn',name); /* Get dataset name from CSV_files*/
if not last then index+1; /* Create macro variable Index */
else if last then call symput ('index',index);
End;
run;
proc import datafile= "&path"
out= &libto..&dsn
dbms=dlm
replace;
delimiter="," ;
getnames=yes;
run;
%End;
%End;
%Mend get_data;
/* Macro Call*/
%get_data(1,4);
The errors that I get is the following:
ERROR 180-322: Statement is not valid or it is used out of proper order.
I get this for multiple lines in the code but generates the last 3 out of 4 SAS datasets from my CSV files.
I also get the error for the &dsn
in the code:
ERROR 22-322: Syntax error, expecting one of the following: ;, (, DATAFILE, DATATABLE, DBMS,
DEBUG, FILE, OUT, REPLACE, TABLE, _DEBUG_.
回答1:
Maybe, it's because you don't increment your &n macrovariable with every iteration? I would suggest to replace your
%DO %WHILE...
loop with
%DO i=&n %TO &index;
...
if _N_=&i then ...;
UPDATE
This is what I run and it worked. It's exactly the same updated code from your question, except:
-I added data step to create csv_files dataset
-I deleted the second %END statement
-added LIBNAME to assign l library
-changed F:-drive to C:-drive in the paths (just because I don't have F-drive):
libname l 'C:\Data';
data l.csv_files;
length name $4 path $20;
input name $ path $;
datalines;
aapl C:\Data\aapl.csv
msft C:\Data\msft.csv
ibm C:\Data\ibm.csv
goog C:\Data\goog.csv
;
run;
%let dsname = csv_files;
%let libto = l;
%Macro get_data(n,index);
%let dsname = csv_files;
%let libto = l;
%do i=&n %to &index;
data _NULL_;
set &libto..&dsname end=last;
if _N_ =&i then Do;
call symput('path',path); /* Get file path from CSV_files*/
call symput('dsn',name); /* Get dataset name from CSV_files*/
if not last then index+1; /* Create macro variable Index */
else if last then call symput ('index',index);
End;
run;
proc import datafile= "&path"
out= &libto..&dsn
dbms=dlm
replace;
delimiter="," ;
getnames=yes;
run;
%End;
%Mend get_data;
/* Macro Call*/
%get_data(1,4);
回答2:
If you just want to read them into a SAS data set, you could try using the FILEVAR=
option in the infile
statement. FILEVAR
can read multiple external files when you know their path.
data files;
length path $40;
input name $ path $;
datalines;
sample1 C:\sasdata\sample1.csv
sample2 C:\sasdata\sample2.csv
test C:\Cstuff\test.csv
;
run;
data want(drop=name);
set files;
infile dummy filevar=path DLM=',' length=reclen end=done missover;
do while (not done);
input A B C;
output;
end;
run;
回答3:
While fooling around with the code I found a way to get all four csv files imported in SAS using while
I have no clue why this works relatively to what I did before with either the DO
or While
options symbolgen mlogic nomprint;
%let dsname = csv_files;
%let libto = l;
libname l 'C:\SASDATA\';
%Macro get_data(n,index);
%IF &n <= &index %then %Do;
%DO %WHILE (&n <=&index);
data _NULL_;
set l.csv_files end=last;
if _N_ =&n then Do;
call symput('path',Path); /* Get file path from Datalog*/
call symput('dsn',Name); /* Get dataset name from Datalog*/
if not last then index+1; /* Create macro variable Index */
else if last then call symput ('index',index);
End;
run;
proc import datafile= "&path"
out= &libto..&dsn
dbms=dlm
replace;
delimiter="," ;
getnames=yes;
run;
%End;
%End;
Data _NULL_;
set &libto..&dsname;
%IF &n gt &Index %then %Put ERROR Ending execution: Check values of n and Index (n must be less than or equal to index);
run;
%Mend get_data;
/* Macro Call*/
%get_data(1,1,4);
来源:https://stackoverflow.com/questions/20834839/sas-do-while-loop-not-iterating