In the example below i have created the variables B1, B2, B3, B4 and B5. They have the values 1,5,2,6 and 3 respectively.
I have also created the variables M1, M2, M3, M4 and M5, using an array, which I want to take the following values.
M3=max(of B1-B3) etc...
I need to do this within the do loop for various reasons which I won't go into now. Anyway, this code looks to me like it should work fine. But it doesn't. It looks like the Call Symput doesn't create the global variable &bobno until the datastep has finished running, I need the variable to be created during the do loop to ensure that the correct max(B1-B&bobno) is calculated to give the correct value in M1-M5.
array maxi(5) M1-M5;
do i=1 to 5;
call symput ('bobno',compress('B'||i));
Just as you use CALL SYMPUT to write to the Global Symbol table from a "running" Data Step program, you generally use SYMGET to retrieve values from the Global Symbol table inside a "running" Data Step program.
The reference to &bobno, will only resolve 1 time -- at compile time. So whatever value you are seeing is either left over from the previous DATA step execution or, if there is no value for &bobno at the first compile, then you are probably getting a macro variable not found error.
I am a bit confused over WHY you are trying to generate this using macro variables. Is this really the code you envision:
m1 = max(of B1-B1);
m2 = max(of B1-B2);
m3 = max(of B1-B3);
m4 = max(of B1-B4);
m5 = max(of B1-B5);
I think the statement for M1 will give you problems because B1-B1 is not a proper range of numbers for the OF usage. I just don't see how macro variables fit into the picture.
Linus - that works great in this example - I'll try it in my main code.
Cynthia, in the sample I provided a very basic version of what I am trying to achieve. Basically there are a lot more variables in my working example e.g. M1-M90 and the number changes depending on when the code is run.
I have been asked to design all my code so that the users, who are not technical, can simply open and run without having to input any dates, or amend anything. I have managed to get everything else automated and just need to create the field M1-Mn where I have created n as a global variable based on date.
I think I have everything I need now thanks to these forums.
Great! Glad you have a solution that works for you.
I'd like to clarify something for future reference. CALL SYMPUT executes on every iteration of the DATA step program to CREATE a macro variable -- at execution time (or in your case, for every iteration of the DO loop). An "&macvar" reference only gets resolved at COMPILE time. That means if you use CALL SYMPUT and an &macvar reference, you have a timing issue because the &macvar will be resolved, if possible BEFORE the CALL SYMPUT executes.
This program shows an interesting use of CALL SYMPUT and SYMGET that proves the macro variable 'bobno' is getting set appropriately for every iteration of the DO loop -- it also proves that at the end of the do loop, 'bobno' is set to B5. Usually, when you have a DO loop and a CALL SYMPUT, you are creating numbered macro variables (also shown):
421 data play;
423 do i=1 to 5;
424 call symput ('bobno',compress('B'||i));
425 val = symget('bobno');
426 call symput ('bobno'||put(i,1.0),compress('B'||i));
427 put _all_;
NOTE: Numeric values have been converted to character values at the places given by:
i=1 val=B1 _ERROR_=0 _N_=1
i=2 val=B2 _ERROR_=0 _N_=1
i=3 val=B3 _ERROR_=0 _N_=1
i=4 val=B4 _ERROR_=0 _N_=1
i=5 val=B5 _ERROR_=0 _N_=1
NOTE: The data set WORK.PLAY has 1 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
Note that when using SYMGET to create the variable VAL, VAL changes for every iteration of the DO loop; in a similar fashion VAL
would change on every iteration of a DATA step program. The usual way that macro variables are set in a DO loop are to use i as part of
the macro variable value (as shown). The FINAL value of bobno is B5...because at every iteration of the do loop, you are writing over the
previously set value.