I would wish to invoke a macro inside my data step for determining what value should the new variable, that I am creating, receive.
I know that I don't necessarily need a macro for this, that I can just include the code in the data step. The problem is that the problem I am working with is quite convoluted, and there are more than 5 similar if-else statements. However, essentially only thing that changes is what goes inside the macro function.
Hence the need for the macro. Below is the code and the error log. I believe the problem should not be in the macro, I have tested it and it succesfully works. For some reason, though, it does not when invoking it in data step with reference to a variable and a local macro variable.
I read that it is because one should use %sysfunc or %execute call sort of things but I cannot use sysfunc with self-defined macros and execute call also didn't work, or at least I couldn't get it to work, because I want to assign the value of that macro to a temp local variable.
I.E. something like %let temp = execute call(CalculatePayment(args)) but this doesn't work.
%let preliminary_1 = 288;
%let preliminary_2 = 115;
%let preliminary_3 = 58;
data __temp__;
set sashelp.cars;
run;
%macro CalculatePayment(initialPayment, paymentLimit);
%let temp = %sysfunc(min(&initialPayment,&paymentLimit));
%let candidate = %eval(&temp. - 27);
%if( &candidate >= 0) %then %let rValue = &temp;
%else %let rValue = 0;
&rValue
%mend;
data _temp_;
set __temp__;
if weight <= 100 then do;
preliminary = 0;
end;
else if (find(Model,"2")) then do;
%let fstCase = %CalculatePayment(weight,&preliminary_1);
%let seCase = %CalculatePayment(weight,&preliminary_1);
preliminary = %eval(&fstCase. + &seCase.);
end;
/*
else if (find(Model,"g") & find(Model,"1")) then do;
%let fstCase = %CalculatePayment(weight,&preliminary_1);
%let seCase = %CalculatePayment(0.2 * weight,&preliminary_2);
%let thirCase = %CalculatePayment(0.8 * weight,&preliminary_3);
preliminary = %eval(&fstCase. + &seCase. + &thirCase.);
end;
*MORE SIMILAR IF-STATEMENTS BELOW with the values to the macro changing;
*/
else do; preliminary = 0;
end;
run;
Note here is a small snippet of the error log. I did not put it here fully because you can reproduce the same exact log by just running the code.
ERROR LOG:
54 %let fstCase = %CalculatePayment(weight,&preliminary_1);
ERROR: Argument 1 to function MIN referenced by the %SYSFUNC or %QSYSFUNC macro function is not a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC argument list. Execution of %SYSCALL statement or %SYSFUNC
or %QSYSFUNC function reference is terminated.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
. - 27
ERROR: The macro CALCULATEPAYMENT will stop executing.
55 %let seCase = %CalculatePayment(weight,&preliminary_1);
ERROR: Argument 1 to function MIN referenced by the %SYSFUNC or %QSYSFUNC macro function is not a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC argument list. Execution of %SYSCALL statement or %SYSFUNC
or %QSYSFUNC function reference is terminated.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
. - 27
ERROR: The macro CALCULATEPAYMENT will stop executing.
56 preliminary = %eval(&fstCase. + &seCase.);
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
+
56 preliminary = %eval(&fstCase. + &seCase.);
_
22
ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string, a numeric constant, a datetime constant,
a missing value, INPUT, PUT.