0
votes

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)

3
Are you familiar with CALL EXECUTE? I feel like it may work better here. I also wonder if you're looping over dates here, and if you are then this example may be helpful. documentation.sas.com/…Reeza
I have seen CALL EXECUTE, but I don't recall using it or reading a lot about it. I'll look into it. I am looping over datasets that represent a year's worth of data, but I have not seen any use of two digit standalone year formats in SAS. I think the below answers allow me to work with what I have.mrlcpa

3 Answers

2
votes

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)
1
votes

The macro declaration option /PARMBUFF is used to make the automatic macro variable SYSPBUFF available for scanning an arbitrary number of comma separated values passed as arguments.

%macro loops1/parmbuff;
  %local index token;
  %do index = 1 %to %length(&syspbuff);
    %let token=%scan(&syspbuff,&index);
    %if %Length(&token) = 0 %then %goto leave1;
    proc sort data=dir12&token out=dir12sorted&token nodupkey;
    by directorid compid;
    run;
  %end;
  %leave1:
%mend;
options mprint nomlogic;
%loops1(01,02)

SYSPBUFF
MACRO / PARMBUFF

0
votes

Since you're looping over dates, I think something like this may be more helpful in the long run:

%macro date_loop(start, end);
    %let start=%sysfunc(inputn(&start, anydtdte9.));
    %let end=%sysfunc(inputn(&end, anydtdte9.));
    %let dif=%sysfunc(intck(month, &start, &end));

    %do i=0 %to &dif;
        %let date=%sysfunc(intnx(month, &start, &i, b), yymmdd4.);
        %put &date;
    %end;
%mend date_loop;

%date_loop(01Jan2012, 01Jan2015);

This is a slightly modified version from the one in the SAS documentation (macro Appendix, example 11).

http://documentation.sas.com/?docsetId=mcrolref&docsetTarget=n01vuhy8h909xgn16p0x6rddpoj9.htm&docsetVersion=9.4&locale=en