BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
MaxiHösi
Calcite | Level 5

Hello forum,

 

i have problems using loop statements outside of a data step.

 

I have this data step and want to run it several times (e.g. 8 times) :

 

data new_data;
      set test;
      first_result = find(number, &start, "i");
run;

My variable is &start and i want to define a macro with a range from e.g. 1-8.

 

I tried it like below, but it doesn't work:

%macro test(start=1, end=8)
     %local start end;
     %let start=&start;
     %let end=&end;
     %do &start %to &end;
            data new_data_&start;
                   set test;
                   first_result = find(number, &start, "i");
           run;
          %let start=&start+1;
     %end;
&mend test;
%test(start=1,end=8);

Thanks for your help in advance.

1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

The below macro will generate example DATA step code I posted.  Still not sure this is what you want.  But for a test project, it makes sense to play around with this sort of macro looping.

 

data test ;
  input number $2. ;
  cards ;
00
01
12
;

%macro test(start=1, end=8);
  %local i;
  %do i=&start %to &end;
    data new_data_&i;
      set test;
      first_result = find(number, "&i", "i");
    run;
 %end;
%mend test;

options mprint ;
%test(start=1,end=8)
BASUG is hosting free webinars Next up: Mike Sale presenting Data Warehousing with SAS April 10 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.

View solution in original post

10 REPLIES 10
LinusH
Tourmaline | Level 20

The syntax for macro do loops:

%do var=start %to end;

%do i = &start %to &end;
Data never sleeps
MaxiHösi
Calcite | Level 5
Thx, but when i correct it, the code still runs just one time. The error sais "ERROR 180-322: Statement is not valid or it is used out of proper order" and something that the rows and columns couldnt't be found.
LinusH
Tourmaline | Level 20

Please post the log with

options mlogic mprint symbolgen;
Data never sleeps
MaxiHösi
Calcite | Level 5

      

 73         options mlogic mprint symbolgen;

74        

 75         %macro test (start=1, end=8);

76         %local start end;

77         %let start=&start;

78         %let end=&end;

79         %do i = &start %to &end;

80         data new_data_&start.;

81          set test;

82          first_result = find(number, &start, "i");

83         run;

84         &let start=&start+1;

85         %end;

86         %mend test;

87         %test(start=1, end=8);

MLOGIC(TEST):  Ausführung beginnt.

MLOGIC(TEST):  Parameter START besitzt Wert 1

MLOGIC(TEST):  Parameter END besitzt Wert 8

MLOGIC(TEST):  %LOCAL  START END

MLOGIC(TEST):  %LET (Variablenname ist START)

SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

MLOGIC(TEST):  %LET (Variablenname ist END)

SYMBOLGEN:  Makrovariable END wird in 8 aufgelöst

SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

SYMBOLGEN:  Makrovariable END wird in 8 aufgelöst

MLOGIC(TEST):  %DO Schleife startet; Indexvariable I; Startwert 1; Stoppwert 8; By-Wert 1. 

 SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

MPRINT(TEST):   data new_data_1;

MPRINT(TEST):   set test;

SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

MPRINT(TEST):   first_result = find(number, 1, "i");

MPRINT(TEST):   run;

 NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).

       11578:63   1:2       

 NOTE: Komprimierung für Datei WORK.NEW_DATA_1 deaktiviert, da Komprimierungsoverhead Dateigröße erhöhen würde.

NOTE: There were 100 observations read from the data set WORK.TEST.

NOTE: The data set WORK.NEW_DATA_1 has 100 observations and 3 variables.

NOTE:  Verwendet wurde: DATA statement - (Gesamtverarbeitungszeit):

       real time           0.01 seconds

       cpu time            0.00 seconds

      

 

 WARNING: Apparent symbolic reference LET not resolved.

180: ZEILE und SPALTE können nicht ermittelt werden.

NOTE: NOSPOOL is on. Rerunning with OPTION SPOOL might allow recovery of the LINE and COLUMN where the error has occurred.

ERROR 180-322: Statement is not valid or it is used out of proper order.

SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

MPRINT(TEST):   &let start=1+1;

 MLOGIC(TEST):  %DO Schleife Indexvariable I ist jetzt 2; Schleife wird wiederholt.

SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

MPRINT(TEST):   data new_data_1;

MPRINT(TEST):   set test;

SYMBOLGEN:  Makrovariable START wird in 1 aufgelöst

MPRINT(TEST):   first_result = find(number, 1, "i");

MPRINT(TEST):   run;

 NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).

       11583:64   1:2       

 NOTE: Komprimierung für Datei WORK.NEW_DATA_1 deaktiviert, da Komprimierungsoverhead Dateigröße erhöhen würde.

NOTE: There were 100 observations read from the data set WORK.TEST.

NOTE: The data set WORK.NEW_DATA_1 has 100 observations and 3 variables.

NOTE:  Verwendet wurde: DATA statement - (Gesamtverarbeitungszeit):

LinusH
Tourmaline | Level 20
Remove the code in line 84, it's no needed, the %do will augment &I automatically for each loop.
You now have a working loop.
Then it looks like you have data type problem, is your variable "number" character or numeric?
You can also skip the "i" modifier since you are only looking for numbers.
Also, you need to replace the &start in the function call with &i.
Data never sleeps
Quentin
Super User

When writing a macro, often it's helpful to start by writing working SAS code with no macro statements.  Then after you have that, you can work on writing a macro to generate that code.  I know your loop would run 8 times, but if you were going to write two DATA steps without any macro code, what would they look like? Something like:

 

data new_data_1;
  set test;
  first_result = find(number, "1", "i");
run;

data new_data_2;
  set test;
  first_result = find(number, "2", "i");
run;

?

 

I think the above is syntactically correct, but I doubt it's what you want.  It would make sense if your goal is to search a character variable named NUMBER, to see if it has a "1" or a "2" in it.

 

Before worrying about writing a macro, can you provide a small amount of example data, ideally a DATA step with the CARDS statement to make work.test? And also provide the DATA step code that is working to make the dataset you want. Also describe big picture / goal (what are you doing? why do you want to make 8 datasets?)

 

BASUG is hosting free webinars Next up: Mike Sale presenting Data Warehousing with SAS April 10 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
MaxiHösi
Calcite | Level 5

If i am going to write two DATA steps without any macro code, it would exactly look like yours. It's exactly what i want. In the test-Data are just numbers and letters. Yet it's just a test project for me.

Quentin
Super User

The below macro will generate example DATA step code I posted.  Still not sure this is what you want.  But for a test project, it makes sense to play around with this sort of macro looping.

 

data test ;
  input number $2. ;
  cards ;
00
01
12
;

%macro test(start=1, end=8);
  %local i;
  %do i=&start %to &end;
    data new_data_&i;
      set test;
      first_result = find(number, "&i", "i");
    run;
 %end;
%mend test;

options mprint ;
%test(start=1,end=8)
BASUG is hosting free webinars Next up: Mike Sale presenting Data Warehousing with SAS April 10 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
MaxiHösi
Calcite | Level 5

Your code was exactly what i want and it works well. Thanks a lot. 🙂

 

Reeza
Super User

Just a note that when you do this:

    data new_data_&i;
      set test;

Your starting point is always TEST so that your data from the previous iteration does not affect the new iteration. Sometimes that is what you want and sometimes it's not. 

 

  • Parameters within a macro by definition are local, so defining them as local and re-assigning is redundant
  • For the FIND function, put the second parameter in quotes as FIND requieres character/string parameters
  • DO loop needs to be fixed as others have suggested.

 

%macro test(start=, end=)
     %do i = &start %to &end;
            data new_data_&i;
                   set test;
                   first_result = find(number, "&i", "i");
           run;
     %end;
%mend test;
%test(start=1,end=8);

@MaxiHösi wrote:

Hello forum,

 

i have problems using loop statements outside of a data step.

 

I have this data step and want to run it several times (e.g. 8 times) :

 

data new_data;
      set test;
      first_result = find(number, &start, "i");
run;

My variable is &start and i want to define a macro with a range from e.g. 1-8.

 

I tried it like below, but it doesn't work:

%macro test(start=1, end=8)
     %local start end;
     %let start=&start;
     %let end=&end;
     %do &start %to &end;
            data new_data_&start;
                   set test;
                   first_result = find(number, &start, "i");
           run;
          %let start=&start+1;
     %end;
&mend test;
%test(start=1,end=8);

Thanks for your help in advance.


 

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 10 replies
  • 607 views
  • 1 like
  • 4 in conversation