(I am using SAS Enterprise Guide Version 7.15 HF7)
Hi, I have tried to debug this code for hours without luck. The error message I am getting is: "ERROR: Expected close parenthesis after macro function invocation not found."
The code %if %sysfunc(anyalpha(&MyVar.)) ge 1 %then %do;
is where the error stems from. I believe it has to do with the fact that I am using %sysfunc and anyalpha together. On a separate post I read, I believe the error might be from the fact that there is "usage of macro statements where normal data-step-statements are required." I am no SAS expert, and I do not know what that means. I would appreciate any help. Thanks!
%let input_var2 = group;
data _NULL_;
if 0 then set work.test3 nobs=n;
call symputx('num_obs',n);
stop;
run;
%put no. of observations = &num_obs;
%MACRO SPLIT;
%DO I = 1 %TO &num_obs;
/* creating a dataset for each unique entry from the input_var2 list */
data _null_;
set work.test3(obs=&I. firstobs=&I. keep = &input_var2.);
call symputx('MyVar', &input_var2.);
stop;
run;
%put &MyVar.;
%if %sysfunc(anyalpha(&MyVar.)) ge 1 %then %do;
%let MyVar2 = "&MyVar.";
%end;
%else %do;
%let MyVar2 = &MyVar.;
%end;
%put &MyVar2.;
data work.&input_var2.&I.;
set work.test;
where &input_var2 = &MyVar2.;
run;
%END;
%MEND SPLIT;
options mlogic symbolgen MLOGICNEST;
%SPLIT
You have not protected your macro code from unbalanced quotes in the value of the macro variable you created from a dataset variable. Most likely in this line:
%if %sysfunc(anyalpha(&MyVar.)) ge 1 %then %do
You could convert to:
%if %sysfunc(anyalpha(%superq(MyVar))) ge 1 %then %do
But really you should just figure out if the variable is numeric or character upfront.
data _NULL_;
if 0 then set work.test3 nobs=n;
call symputx('num_obs',n);
call symputx('var_type',vtype(&input_var2));
stop;
run;
Then your later code becomes:
data work.&input_var2.&I.;
set work.test;
where &input_var2 =
%if &var_type=C %then "&MyVar" ;
%else &MyVar;
;
run;
Hello,
What is the value of &MyVar. when the error occurs ?
For instance, if it contains a semi-column, the generated code may
prematurely terminate the %if instruction.
Also, i don't think the way you define &MyVar2. is correct, that is with or
without double quotes whether &MyVar. contains alphabetic characters or not.
Indeed, you use it in the subsequent where clause, but the group column of the
work.test dataset is either numeric or character so the value of &MyVar2. should
be consistent for all iterations of your %do loop.
Also, why don't you simply use the implicit loop of the data step ?
Hi @sasknewB ,
It's nice to see you've done your research. Upon initial inspection I don't see anything immediately obviously wrong.
Do you have any previous macros that you are calling, as the error indicates an issue with the invocation of a macro? If not then try closing your SAS session and trying again.
I don't see any "usage of macro statements where normal data-step-statements are required." This means a data step contains macro statements, where one would expect only data step statements, e.g., a variable assignment should be var = value;, but instead %let var = value; has been used.
Please also share the relevant section of the log using the "Insert Code" icon as this might yield more clues.
Kind regards,
Amir.
I think you want something as (not tested) :
data _null_;
set work.test3(keep = &input_var2.);
call execute(cats("data work.input_var2.",_N_,"; set work.test; where &input_var2.=",&input_var2.,"; run;"));
run;
EDIT : A more complete macro that checks the column type :
data test3;
input group $ val;
cards;
A 1
B 2
C 3
D 4
;
run;
data test;
input group $ val;
cards;
A 1
C 3
;
run;
%macro split(input_var2);
data _null_;
set work.test3(keep = &input_var2.);
if vtype(&input_var2.)="C" then do;
call execute(cats("data work.&input_var2.",_N_,"; set work.test; where &input_var2.='",&input_var2.,"'; run;"));
end;
else do;
call execute(cats("data work.&input_var2.",_N_,"; set work.test; where &input_var2.=",&input_var2.,"; run;"));
end;
run;
%mend;
%split(group);
%split(val);
I am not sure you really need to do that though. Why do you want to split your datasets this way ?
@sasknewB wrote:
(I am using SAS Enterprise Guide Version 7.15 HF7)
Hi, I have tried to debug this code for hours without luck. The error message I am getting is: "ERROR: Expected close parenthesis after macro function invocation not found."
The code
%if %sysfunc(anyalpha(&MyVar.)) ge 1 %then %do;
is where the error stems from. I believe it has to do with the fact that I am using %sysfunc and anyalpha together. On a separate post I read, I believe the error might be from the fact that there is "usage of macro statements where normal data-step-statements are required." I am no SAS expert, and I do not know what that means. I would appreciate any help. Thanks!
%let input_var2 = group; data _NULL_; if 0 then set work.test3 nobs=n; call symputx('num_obs',n); stop; run; %put no. of observations = &num_obs;
%MACRO SPLIT; %DO I = 1 %TO &num_obs; /* creating a dataset for each unique entry from the input_var2 list */ data _null_; set work.test3(obs=&I. firstobs=&I. keep = &input_var2.); call symputx('MyVar', &input_var2.); stop; run; %put &MyVar.; %if %sysfunc(anyalpha(&MyVar.)) ge 1 %then %do; %let MyVar2 = "&MyVar."; %end; %else %do; %let MyVar2 = &MyVar.; %end; %put &MyVar2.; data work.&input_var2.&I.; set work.test; where &input_var2 = &MyVar2.; run; %END; %MEND SPLIT; options mlogic symbolgen MLOGICNEST; %SPLIT
Creating macros that have macro variables just appear in the middle of code is poor practice. Since you are not explicitly setting them as parameters you can run into scope issues.
And in this case, we have no clue what your macro variables:
&input_var2
&myvar
might actually contain.
Might consider using the OPTION MPRINT to show more of the code generated.
Then share that with us from the log.
There is also the entire question of why you think it is necessary to create a separate data set for each value of a variable. I would say that an extremely high percentage of cases where that my be considered are better off leaving the data in one set and using BY group processing.
Hi everyone, thanks for your prompt replies.
Here is the dataset work.test3:
Here is some output from the log
MLOGIC(SPLIT): Beginning execution.
SYMBOLGEN: Macro variable NUM_OBS resolves to 5
MLOGIC(SPLIT): %DO loop beginning; index variable I; start value is 1; stop value is 5; by value is 1.
MPRINT(SPLIT): data _null_;
SYMBOLGEN: Macro variable I resolves to 1
SYMBOLGEN: Macro variable I resolves to 1
SYMBOLGEN: Macro variable INPUT_VAR2 resolves to group
MPRINT(SPLIT): set work.test3(obs=1 firstobs=1 keep = group);
SYMBOLGEN: Macro variable INPUT_VAR2 resolves to group
MPRINT(SPLIT): call symputx('MyVar', group);
MPRINT(SPLIT): stop;
MPRINT(SPLIT): run;
MLOGIC(SPLIT): %PUT &MyVar.
SYMBOLGEN: Macro variable MYVAR resolves to a:(0to30K]
a:(0to30K]
SYMBOLGEN: Macro variable MYVAR resolves to a:(0to30K]
ERROR: Expected close parenthesis after macro function invocation not found.
MLOGIC(SPLIT): %IF condition %sysfunc(anyalpha(&MyVar.)) ge 1 is TRUE
MLOGIC(SPLIT): %LET (variable name is MYVAR2)
SYMBOLGEN: Macro variable MYVAR resolves to a:(0to30K]
MLOGIC(SPLIT): %PUT &MyVar2.
SYMBOLGEN: Macro variable MYVAR2 resolves to "a:(0to30K]"
"a:(0to30K]"
SYMBOLGEN: Macro variable INPUT_VAR2 resolves to group
SYMBOLGEN: Macro variable I resolves to 1
MPRINT(SPLIT): data work.group1;
MPRINT(SPLIT): set work.test;
SYMBOLGEN: Macro variable INPUT_VAR2 resolves to group
SYMBOLGEN: Macro variable MYVAR2 resolves to "a:(0to30K]"
MPRINT(SPLIT): where group = "a:(0to30K]";
MPRINT(SPLIT): run;
Something to mention, is that work.test3 isn't guaranteed to be those variables. Sometimes it would be different categories such as years: 2012, 2013, ..., 2020. So when the categories are numbers, the where= data statement should be where group = 2020 while with the categories in the image it should be where group = "a:(0to30K]". So there is a difference in quotation marks.
The very obvious question first:
why do you split a dataset into subdatasets, when the variable used for splitting can easily be used for BY group processing?
@sasknewB wrote:
Hi, I am not too familiar with the BY group processing. Would you be able to give an example of how I would be able to use BY group processing to accomplish my goal?
It really depends on what your goal is. So far it looks like you have just presented an XY problem .
If the goal is to analyze TEST3 by different levels of GROUP then just add a BY statement to your analysis step.
proc means data=test3;
by group;
run;
You have not protected your macro code from unbalanced quotes in the value of the macro variable you created from a dataset variable. Most likely in this line:
%if %sysfunc(anyalpha(&MyVar.)) ge 1 %then %do
You could convert to:
%if %sysfunc(anyalpha(%superq(MyVar))) ge 1 %then %do
But really you should just figure out if the variable is numeric or character upfront.
data _NULL_;
if 0 then set work.test3 nobs=n;
call symputx('num_obs',n);
call symputx('var_type',vtype(&input_var2));
stop;
run;
Then your later code becomes:
data work.&input_var2.&I.;
set work.test;
where &input_var2 =
%if &var_type=C %then "&MyVar" ;
%else &MyVar;
;
run;
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.