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 -
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.