Search code examples
importsasdata-cleaningsas-macro

SAS macro loop to read csv files with proc import


I have a directory of csv files, each with names that begin with the letter m and end with a number. There are twelve files - m6 to m17.

I'd like to read them in and process them as separate data sets. I've written two macros attempting to do so. Macro1 works. Macro2 breaks. I would prefer Macro2 if I can get it to work, to avoid unnecessary bits like my creation of %rawfiles, invocation of %sysfunc, etc.

Macro 1:

%let rawcsv = C:\ALL\dat\;

%let rawfiles = m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 m16 m17;

%macro1;

%do i = 1 %to %sysfunc(countw(&rawfile));
    %let rawfile = %scan(&rawfiles, &i);

proc import datafile="&&rawcsv.&&rawfile.csv" 
                 out=&rawfile replace
                dbms=csv; 
        guessingrows=500; 
run;
%end;
%mend;

%macro1;

Macro 2:

%let rawcsv = C:\ALL\dat\;

%macro macro2(first=6, last=19);
%do i=&first. %to &last. %by 1;
proc import datafile="&&rawcsv..m&&i.csv" 
                 out=m&i replace 
                dbms=csv; 
        guessingrows=500;
run;
%end;
%mend;

%macro2;

%macro2 is my bad imitation of this solution. It returns the following errors:

MPRINT(MACRO2):   proc import datafile="C:\ALL\dat\m.6.csv" out=m.6 replace 
dbms=csv;
MPRINT(MACRO2):   ADLM;
MPRINT(MACRO2):   guessingrows=500;
MPRINT(MACRO2):   run;

ERROR: Library name is not assigned. /*repeats this error 14 times, once per file*/

Two questions:

  1. What am I missing in %macro2?
  2. Do you see a better solution that I am not using? The files are structured differently and not stackable, just a heads up.

Solution

  • From your log we can see a period is being inserted into the output dataset name. Just remove that extra period in your macro definition.

    MPRINT(MACRO2):   proc import datafile="C:\ALL\dat\m.6.csv" out=m.6 replace dbms=csv;
    

    The extra & in the code is probably confusing you. When the macro processor sees two & it converts them to one and then reprocesses the string to further resolve the resulting macro variable references.

    The period after a macro variable name is not required when the macro processor can tell that the name has ended. But the periods are needed in some places. One place in your code is where it is required to make sure the macro processor knows where the name ends (the macro variable is named readcsv not readcsvm ). Another is where you want to place an actual period after the value of a macro variable. You will need to place two periods there since the first will be used by the macro processor when it evaluates the macro variable value.

    In this version of macro2 I have removed the periods after the macro variable names in the places where they are not required just to emphasize the places where the period is required.

    %let rawcsv = C:\ALL\dat\;
    
    %macro macro2(first, last);
    %local i ;
    %do i=&first %to &last ;
    proc import dbms=csv
      datafile="&rawcsv.m&i..csv" 
      out=m&i replace 
    ; 
      guessingrows=500;
    run;
    %end;
    %mend macro2;
    
    %macro2(first=6, last=19)