BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
sasknewB
Calcite | Level 5

(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

 

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

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;

 

View solution in original post

10 REPLIES 10
gamotte
Rhodochrosite | Level 12

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.

 

 

gamotte
Rhodochrosite | Level 12

Also, why don't you simply use the implicit loop of the data step ?

Amir
PROC Star

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.

gamotte
Rhodochrosite | Level 12

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 ?

ballardw
Super User

@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.

sasknewB
Calcite | Level 5

Hi everyone, thanks for your prompt replies.

 

Here is the dataset work.test3:

sasknewB_0-1603897582334.png

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.

sasknewB
Calcite | Level 5
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?
Tom
Super User Tom
Super User

@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;
Tom
Super User Tom
Super User

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;

 

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 10 replies
  • 2852 views
  • 1 like
  • 6 in conversation