BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
MariaD
Barite | Level 11

Hi Folks,

 

I need to execute a macro inside data step. I made a simple example but the following error appears:

 

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 
       valor_2 
ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition.
ERROR: The %TO value of the %DO I loop is invalid.
ERROR: The macro VALOR will stop executing.

Our example is:

 

%global valor_final;

%macro valor (var_1, var_2);
%let valor_final=;
%do i=1 %to %eval(&var_2);
  %if &i=1 %then %let valor_final = &var_2. ;  
  %else %let valor_final = &valor_final., &var_1. ; 
%end;
%mend valor;


data test;
   valor_1=90; 
   valor_2 = 5;
   %valor(valor_1, valor_2);
   var_final = SUM(&valor_final.);
run;

In this case, our objective is parameter "VALOR_FINAL" will be replace by: "90, 90, 90, 90, 90". So the program will be:

 

data test;
   valor_1=90; 
   valor_2 = 5;
   %valor(valor_1, valor_2);
   var_final = SUM(90, 90, 90, 90, 90);
run;

Regards,

1 ACCEPTED SOLUTION

Accepted Solutions
Oligolas
Barite | Level 11

Hi,

as it has been said you do not Need a macro to perform this Kind of Operation.

For Demonstration purpose there are 2 ways to run a macro inside a data step: dosubl and call execute.

 

dosubl:

%macro valor (var_1, var_2);
   %do i=1 %to %eval(&var_2);
     %if &i=1 %then %let valor_final = &var_1. ;  
     %else %let valor_final = &valor_final., &var_1. ; 
   %end;
   %put &=valor_final;
   %let valor_final = %sysfunc(sum(&valor_final.)); 
   %put &=valor_final;
%mend valor;

data test;
   set sashelp.class;
   valor_1=weight; 
   valor_2 = age;

   rc = dosubl('%global valor_final; %valor('||put(valor_1,best.)||','||put(valor_2,best.)||')');
   var_final=symget('valor_final');
   rc = dosubl('%symdel valor_final');
   keep va: rc:;
run;
proc print;run;

call execute:

%macro valor (var_1, var_2);
   %local valor_final;
   %do i=1 %to %eval(&var_2);
     %if &i=1 %then %let valor_final = &var_1. ;  
     %else %let valor_final = &valor_final., &var_1. ; 
   %end;
   %put &=valor_final;
   %let valor_final = %sysfunc(sum(&valor_final.)); 
   %put &=valor_final;
   &valor_final.
%mend valor;

data test1;
   set sashelp.class end=last;
   valor_1=weight; 
   valor_2 = age;

   if _N_ eq 1 then call execute('data test2;');
   call execute('var_final=%nrstr(%valor('||put(valor_1,best.)||','||put(valor_2,best.)||'));output;');
   if last then call execute('run;');
run;
proc print;run;

Give them a try and have fun with it 🙂

________________________

- Cheers -

View solution in original post

7 REPLIES 7
smantha
Lapis Lazuli | Level 10

Macro resolution is compile time only and not execution time inside a datastep. %let does not work. 

The options you have are sum(of valor_1 -- valor_n) if you have a repeating pattern in your variable names such as valor_: as suggested previously.

Use combination of arrays and sum function.

array x{*} var1 dummy2 someotherthing;

sum(of x:)

 

MariaD
Barite | Level 11

Hi @smantha ,

 

The main objective is not to use with SUM function, was only a sample. Our problem is we have a value 90, por example in a variable and 5 in other variable. We need to create of list of 90 value, separated by ",", 5 times. So, we expected a result of 90, 90, 90, 90, 90 to use in other process. 

 

I know exists REPEAT function, but the if we use REPEAT(90, 5) the result is 9090909090 (without a separated value). 

 

Regards,

smantha
Lapis Lazuli | Level 10

The value of  valor_2 is not resolved at compile time and is symbolically passed as a character string valor_2

MariaD
Barite | Level 11

Yes, @smantha. The macro takes valor_2 as text not the value of the variable called valor_2.

 

Regards, 

ed_sas_member
Meteorite | Level 14

Hi @MariaD 

 

An approach to avoid this:

data test;
   valor_1=2; 
   valor_2 = 5;
   call symputx ("valor_final", prxchange('s/\s+/,/',-1,strip(repeat(valor_1,valor_2-1))));
run;

data want;
	set test;
	var_final = sum(&valor_final.);
run;
LeonidBatkhan
Lapis Lazuli | Level 10

Hi MariaD,

 

If your objective is to replace VALOR_FINAL by: "90, 90, 90, 90, 90", why do you need SUM function and the macro?

 

data test;
   valor_1=90; 
   valor_2 = 5;
   %valor(valor_1, valor_2);
   var_final = SUM(&valor_final.);
run;

Why not just replace your above code with:

data test;
   valor_1=90; 
   valor_2 = 5;
   var_final = valor_1 * valor_2;
run;

?

 

 

Oligolas
Barite | Level 11

Hi,

as it has been said you do not Need a macro to perform this Kind of Operation.

For Demonstration purpose there are 2 ways to run a macro inside a data step: dosubl and call execute.

 

dosubl:

%macro valor (var_1, var_2);
   %do i=1 %to %eval(&var_2);
     %if &i=1 %then %let valor_final = &var_1. ;  
     %else %let valor_final = &valor_final., &var_1. ; 
   %end;
   %put &=valor_final;
   %let valor_final = %sysfunc(sum(&valor_final.)); 
   %put &=valor_final;
%mend valor;

data test;
   set sashelp.class;
   valor_1=weight; 
   valor_2 = age;

   rc = dosubl('%global valor_final; %valor('||put(valor_1,best.)||','||put(valor_2,best.)||')');
   var_final=symget('valor_final');
   rc = dosubl('%symdel valor_final');
   keep va: rc:;
run;
proc print;run;

call execute:

%macro valor (var_1, var_2);
   %local valor_final;
   %do i=1 %to %eval(&var_2);
     %if &i=1 %then %let valor_final = &var_1. ;  
     %else %let valor_final = &valor_final., &var_1. ; 
   %end;
   %put &=valor_final;
   %let valor_final = %sysfunc(sum(&valor_final.)); 
   %put &=valor_final;
   &valor_final.
%mend valor;

data test1;
   set sashelp.class end=last;
   valor_1=weight; 
   valor_2 = age;

   if _N_ eq 1 then call execute('data test2;');
   call execute('var_final=%nrstr(%valor('||put(valor_1,best.)||','||put(valor_2,best.)||'));output;');
   if last then call execute('run;');
run;
proc print;run;

Give them a try and have fun with it 🙂

________________________

- Cheers -

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!

Submit your idea!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

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
  • 7 replies
  • 894 views
  • 0 likes
  • 5 in conversation