1
votes

This piece of code will not run correctly if there is more than one thing in each list.

%macro loop(list1, list2);

  %let n=%sysfunc(countw(&list1));
  %do i=1 %to &n; 
    %let O_list1 = %scan(&list1, &i, '');
    %let O_list2 = %scan(&list2, &i, '');

data taxes;
   food=3*&O_List1;
   materials = 4*&O_List2

%end;
%mend; 

%loop(1, 4);
/* %loop(1 3, 4 6) */ 

Here the output is 3 and 16. If I make the loop as it is in the commented section the code doesn't run and I can't seem to figure out why. Thanks!

2
Not related to your error, but it's a good idea to add a run; statement to end your DATA step. - Quentin
Because you told %SCAN() that your lists are delimited by single quotes your example only has ONE item in each list. This means that the space embedded into that item makes your macro generate invalid SAS code. Also the overall logic of the macro is flawed as it will just keep overwriting the same output dataset if there were multiple items in the list. What is the overall goal of the macro? - Tom
@Tom thanks for pointing that out I added a_&I to fix the overwriting issue. The goal of the program in my real program is to iterate over two lists at the same time. This way I can get a table out that I need. Now that I have figured this out I need to figure out how to append all of the created tables. - Jessica Warren

2 Answers

2
votes

Try changing the third argument in %scan from '' to %str( ). At the moment it's looking for a ' delimiter character in your input lists, because in the SAS macro language, everything is text and you don't need to quote character constants like you do in procs and data steps. However, you can't just type an unquoted space, as the macro processor trims everything, so you have to use one of the appropriate macro quoting functions.

You might also want to look into the documentation for arrays in SAS, as that's usually the simpler option for running calculations multiple times within a data step.

0
votes

Make sure to use the same delimiter for both the COUNTW() and %SCAN() function calls. Remember that to the macro processor quotes are part of the strings and that to have a space included at the beginning or end of value you will need to macro quote it.

%let n=%sysfunc(countw(&list1,%str( )));
%do i=1 %to &n; 
  %let item1 = %scan(&list1, &i, %str( ));
  %let item2 = %scan(&list2, &i, %str( ));

If your lists are really just being used to create a dataset with &N observations then you probably do not need to use %DO or %SCAN().

%macro taxes(list1, list2);
%local n ;
%let n=%sysfunc(countw(&list1));

data taxes;
  array _1 (&n) _temporary_ (&list1);
  array _2 (&n) _temporary_ (&list2);
  do row=1 to &n ;
    food=3*_1(row);
    materials = 4*_2(row);
    output;
  end;
run;

%mend; 
%taxes(list1=1 3, list2=4 6);
proc print data=taxes;
run;

enter image description here