Search code examples
macrossassas-macro

SAS syntax error 22 and 200 when using variable inside dataset name inside macro


I am trying to sort several datasets in SAS using a loop within a macro, using a list of numbers, some of which have leading zeros, within dataset names (eg., in the example code, a list of 01,02), and this code will also guide some other loops I would like to build.

I used the SAS guidance on looping through a nonsequential list of values with a macro DO loop code as a starting point from here: http://support.sas.com/kb/26/155.html.

data dir1201;
   input compid directorid X;
   format ;
   datalines;
01 12 11  
02 15 5  
;
run;

data dir1202;
   input compid directorid X;
   format ;
   datalines;
01 12 1  
03 18 8  
;
run;

%macro loops1(values);                                                                                                         
     /* Count the number of values in the string */                                                                                                                                   
     %let count=%sysfunc(countw(&values)); 
     /* Loop through the total number of values */                                                                                         
     %do i = 1 %to &count;
      %let value=%qscan(&values,&i,%str(,)); 
      proc sort data=dir12&value out=dir12sorted&value nodupkey;
      by directorid compid;
      run;
      %end;
%mend;
options mprint mlogic;
%loops1(%str(01,02))  

I assume str is needed for nonsequential lists, but that is also useful when I want to retain leading zeros;

I see the macro variable seems to incorporate the 01 or 02 in the log, but then I receive the error 22 and 200 right afterward. Here is a snippet of the log error using this example code:

339  %macro loops1(values);
340       /* Count the number of values in the string */
341       %let count=%sysfunc(countw(&values));
342       /* Loop through the total number of values */
343       %do i = 1 %to &count;
344        %let value=%qscan(&values,&i,%str(,));
345        proc sort data=dir12&value out=dir12sorted&value nodupkey;
346        by directorid compid;
347        run;
348        %end;
349  %mend;
350  options mprint mlogic;
351  %loops1(%str(01,02))
MLOGIC(LOOPS1):  Beginning execution.
MLOGIC(LOOPS1):  Parameter VALUES has value 0102
MLOGIC(LOOPS1):  %LET (variable name is COUNT)
MLOGIC(LOOPS1):  %DO loop beginning; index variable I; start value is 1; stop value is 2; by
      value is 1.
MLOGIC(LOOPS1):  %LET (variable name is VALUE)
NOTE: Line generated by the macro variable "VALUE".
1    dir1201
          --
          22
           --
           200
ERROR: File WORK.DIR12.DATA does not exist.

I don't understand why dir1201 is showing, but then the error is referencing the dataset work.dir12 (ignoring the 01)


Solution

  • The macro quoting is confusing the parser into thinking the macro quoting signals the start of a new token. You can either add %unquote() to remove the macro quoting.

    proc sort data=%unquote(dir12&value) out=%unquote(dir12sorted&value) nodupkey;
    

    Or just don't add the macro quoting to begin with.

    %let value=%scan(&values,&i,%str(,));
    

    It will be much easier to use your macro if you design it to take space delimited values rather than comma delimited. Then there is no need to add macro quoting to the call either.

    %macro loops1(values);
    %local i value ;
    %do i = 1 %to %sysfunc(countw(&values,%str( )));
      %let value=%scan(&values,&i,%str( ));
    proc sort data=dir12&value out=dir12sorted&value nodupkey;
      by directorid compid;
    run;
    %end;
    %mend loops1;
    %loops1(values=01 02)