BookmarkSubscribeRSS Feed
WouterKBC
Obsidian | Level 7

How can you use an array in a macro?

I cannot define an array in a macro, so I decided to make the array in a datastep and reference to it:

data _null_;
	x1 = 1;
	x2 = 2;
	array bonds{2} x1-x2;
	call symput('blub', bonds);
run;
%macro test(input=);
	%let var = 1;
	%put 1;
	%put &var;
%mend test;
%test(input=&blub);

It fails at the symput:

ERROR: Illegal reference to the array bonds.

 

16 REPLIES 16
Cynthia_sas
SAS Super FREQ
Hi:
The array reference "bonds" is not something that you can use the way you envision. Let's start by saying that it doesn't matter what you want to do with the token or array reference "bonds" -- it is just reference, not a physical data structure.

A SAS array name is just one way to reference a group of variables that you want to have treated as though it was like an array. So anytime you use the reference BONDS, SAS will expect you to use a subscript or index, such as BONDS(1) (which points to X1) or BONDS(2) (which points to X2).

I guess I don't understand what you are doing in your %TEST macro program. Do you want to pass the values of X1 and X2 to the macro program or do you want to pass the variable names to the macro program?

What is the purpose of your %let var=1; are you thinking that var will be your index to the array?

cynthia
WouterKBC
Obsidian | Level 7

It's just some dummy code.

Let's assume:

%macro test(input=);
	%let var = input{1};
	%put &var;
%mend test;

 

Can I pass my bonds array to this macro?

Shmuel
Garnet | Level 18

Call Symput in data step is equivalent to %LET, that is assing value to a macro variable;

 

In your code "bonds" is a reference name of an array, not a variable value.

 

You can try a macro similar to that:

 

%macro test(array=1 2 3);  

      %let i = 1;

      %do %until(&x = );

             %let   x = %scan(input, &i);  

             %put  I = &i  x = &x;

             %let i = %eval(&i +1);

       %end;

%mend;

%test

      

Shmuel
Garnet | Level 18
I made a mismatch;
use array instead input un the macro
Shmuel
Garnet | Level 18

Here is the repaired code to test:

 

%macro test(array=1 2 3);  

      %let i = 1;

      %do %until(&x = );

             %let   x = %scan(&array, &i);  

             %put  I = &i  x = &x;

             %let i = %eval(&i +1);

       %end;

%mend;

%test;

WouterKBC
Obsidian | Level 7

Thanks for your reply.

 

I still have one problem. The array is defined outside the macro in a data step.

Whenever I try to 'call symput', I get the error 'Illegal reference to the array' so I cannot use it as a parameter.

 

Any suggestions?

WouterKBC
Obsidian | Level 7

Something suboptimal:

array=&var1-&var10

 

Where var... is defined outside the macro (with call symput).

 

In this case, the vars need to be filled with some dummy data which is not what I want.

Shmuel
Garnet | Level 18

Then you can do:

 

data _NULL_;

      x1 = 1; x2=2;

     array bonds{2} x1-x2;

 

      len = length(bonds);

      length array_string = $20;

      array_string = left(x1);

      do i=2 to len;

           array_straing = trim(array_string) || ' '||left(x(i));

      end;

      call symput ('my_array', trim(array));

run;

 

then use the macro test as: 

%test(array = &my_array);

        

WouterKBC
Obsidian | Level 7
177 len = length(bonds);
ERROR: Illegal reference to the array bonds.
Shmuel
Garnet | Level 18

sorry, next code runs without errors:

 

data _NULL_;
      x1 = 1; x2=2;
     array bonds{2} x1-x2;
      len = dim(bonds);
      length array_string $20;
      array_string = left(x1);
      do i=2 to len;
           array_straing = trim(array_string) || ' '||left(bonds(i));
      end;

      call symput ('my_array', trim(array_string));
run;

BrunoMueller
SAS Super FREQ

Hi

To put all values of an array into one string, you can use the CAT... functions together with the OF keyword and an arrayname. See example below.

 

data _NULL_;
  x1 = 1;
  x2 = 2;
  x3 = 3;
  array bonds{*} x1-x3;
  length array_string $20;
  array_string = catx(" ", of bonds{*});
  call symputx('my_array', array_string);
run;
%put NOTE: &=my_array;

Bruno

 

Reeza
Super User

Based on your other question about importing multiple excel workbooks/sheets I can't help but suggest that this is the wrong path to be going down. 

 

You need to provide the file paths. SAS can extract them from a directory or you can provide the path or generate them in some manner, assuming some logic in naming, to pass to your proc import. An array will not help in any way with this process.

 

If you have the paths in a datastep you can  call the import procedure macro via a call execute statement. 

ChrisRodrig
Fluorite | Level 6

Thanks for this!

Let me loop through an array/variable list to execute a nested macro I created. 

i'm sure there are other approaches but this was simple enough.

ChrisRodrig
Fluorite | Level 6

***Since I was using this to execute a nested macro I created, I changed the code a little to only run til the end of the list- instead of when x was null.

 

%macro test(array=Var1 Var2 Var3 .... );
%let i = 1;

%do %until( &i = %eval(%sysfunc(countw(&array.)) +1));
%let x = %scan(&array, &i);
%put I = &i x = &x;
%let i = %eval(&i +1);
%MyNestedMacro(varn= &x);
%end;
%mend;
%test;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 16 replies
  • 16807 views
  • 3 likes
  • 7 in conversation