I have code, generates 4 macro variables and print them out into a file.
The code works fine, not in a MACRO. When inside MACRO it always complains[see below].
Anyone?!
%macro macroit();
proc sql noprint;
select round(md3,0.001) into: val_md3 from &plotds. having ind=max(ind);
select round(md3_ema_e,0.001) into: val_md3_ema from &plotds. having ind=max(ind);
select round(md3y,0.001) into: val_md3y from &plotds. having ind=max(ind);
select round(md3y_ema_e,0.001) into: val_md3y_ema from &plotds. having ind=max(ind);
quit;
%put "val_md3=&val_md3. val_md3y=&val_md3y.";
data _out_c;
input mvar $20.;
val_out_=dequote(resolve(quote(mvar)));
ind=_N_;
datalines;
&val_md3
&val_md3_ema
&val_md3y
&val_md3y_ema
run;quit;
data _out_c(keep=val_out_final);
set _out_c;
if ind>0 then val_out_2=substr(mvar,2,length(mvar));
else val_out_2=mvar;
if ind>0 then val_out_final=trim(val_out_2)||"="||strip(val_out_);
else val_out_final=mvar;
run;quit;
data _out_c_0;
input val_out_final $80.;
datalines;
[value]
run;quit;
data _out_c; set _out_c_0 _out_c; run;quit;
proc export data=_out_c(keep=val_out_final)
OUTFILE='C:\\sinx_out.ini'
DBMS=DLM REPLACE;
DELIMITER=',';
PUTNAMES=NO;
RUN;
%mend;
%macroit();
MPRINT(MACROIT): proc sql noprint;
MPRINT(MACROIT): select round(md3,0.001) into: val_md3 from _ECL_MD_sin having ind=max(ind);
NOTE: The query requires remerging summary statistics back with the original data.
MPRINT(MACROIT): select round(md3_ema_e,0.001) into: val_md3_ema from _ECL_MD_sin having ind=max(ind);
NOTE: The query requires remerging summary statistics back with the original data.
MPRINT(MACROIT): select round(md3y,0.001) into: val_md3y from _ECL_MD_sin having ind=max(ind);
NOTE: The query requires remerging summary statistics back with the original data.
MPRINT(MACROIT): select round(md3y_ema_e,0.001) into: val_md3y_ema from _ECL_MD_sin having ind=max(ind);
NOTE: The query requires remerging summary statistics back with the original data.
MPRINT(MACROIT): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
MLOGIC(MACROIT): %PUT "val_md3=&val_md3. val_md3y=&val_md3y."
"val_md3= -1.193 val_md3y= -0.884"
MPRINT(MACROIT): data _out_c;
MPRINT(MACROIT): input mvar $20.;
MPRINT(MACROIT): val_out_=dequote(resolve(quote(mvar)));
MPRINT(MACROIT): ind=_N_;
MPRINT(MACROIT): datalines;
ERROR: The macro MACROIT generated CARDS (data lines) for the DATA step, which could cause incorrect results. The DATA step and the macro
will stop executing.
NOTE: The data set WORK._OUT_C has 0 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
MPRINT(MACROIT): - -1.053 -0.884 -0.769 run;
NOTE: Line generated by the macro variable "VAL_MD3".
1 -1.193
------
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
MPRINT(MACROIT): quit;
MPRINT(MACROIT): data _out_c(keep=val_out_final);
MPRINT(MACROIT): set _out_c;
MPRINT(MACROIT): if ind>0;
MPRINT(MACROIT): ;
MPRINT(MACROIT): ;
MPRINT(MACROIT): ;
ERROR: The macro MACROIT will stop executing.
MLOGIC(MACROIT): Ending execution.
You cannot use datalines inside a macro (the compiled macro no longer has "lines").
But what is the purpose of this data step?
Are you just trying to get the values of series of macro variables?
data _out_c;
length ind 8 mvar $32 val_out $200;
do mvar='val_md3','val_md3_ema','val_md3y','val_md3y_ema';
ind+1;
val_out=symget(mvar);
output;
end;
run;
Place the values directly into a data set such as with a CREATE TABLE.
Combine the data sets generated instead of trying to read the macro variables with input.
Expect to spend a great deal of time debugging simple problems if you continue to use code like this inside macros:
data _out_c(keep=val_out_final); set _out_c;
Since the data set _out_c is completely replaced you cannot tell whether problems came from the data in the Set statement version or were created by code that used that data.
And you do that TWICE with _out_c just in this code. So any problems that don't throw syntax errors are going to be nasty to find because you will not have a before set to compare with the after.
You cannot use datalines inside a macro (the compiled macro no longer has "lines").
But what is the purpose of this data step?
Are you just trying to get the values of series of macro variables?
data _out_c;
length ind 8 mvar $32 val_out $200;
do mvar='val_md3','val_md3_ema','val_md3y','val_md3y_ema';
ind+1;
val_out=symget(mvar);
output;
end;
run;
What I need is PERIODICALLY to 1) generate macro variables[or another format] 2) write it out into a file, and another
application will pick it up ...
Does this give you a start:
proc sql noprint; create table t1 as select round(md3,0.001) asal_md3 from &plotds. having ind=max(ind); create table t2 as select round(md3_ema_e,0.001) as val_md3_ema from &plotds. having ind=max(ind); create table t3 as select round(md3y,0.001) as val_md3y from &plotds. having ind=max(ind); create table t4 as select round(md3y_ema_e,0.001) as val_md3y_ema from &plotds. having ind=max(ind); quit; data _out_c; merge t1 t2 t3 t4; run;
But this makes no sense at all because you do not provide anywhere that IND gets a value.
data _out_c(keep=val_out_final); set _out_c; if ind>0 then
Suggestion:
Provide an example of a &Plotds data set and the expected file that should be made from it.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.