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,
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 -
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:)
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,
The value of valor_2 is not resolved at compile time and is symbolically passed as a character string valor_2
Yes, @smantha. The macro takes valor_2 as text not the value of the variable called valor_2.
Regards,
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;
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;
?
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 -
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 25. Read more here about why you should contribute and what is in it for you!
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.