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

According %bquote() macro function documentation I don't have to mark unpaired "(" with % to assign it to macro variable.

But this code doesn't work for some reason (variable var is blank as a result):

 

%let var=%bquote(();
%put &var;

 

Why? How can I fix code to produce expected result?

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

@DmitryErshov wrote:

I want to write my own macro for updating some table with columns a, b and c.

 

%macro updateTable(set=,where=);
...
%mend;

Business user can use this macro to update the table. Example:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')));

 


The only commonly used characters that really cause havoc in macro calls are commas. And even those are fine if they are enclosed in quotes or parentheses.  Your second parameter is no problem. But if your macro parameters accept lists of values make sure not to use comma as the delimiter in the call.  So use something like | for example. 

 

So your example call just becomes. 

%updateTable
(set=a=a+1|b=b+2
,where=c in ('1','2','3')
);

If you really require quoting to get the macro call to work then consider using regular quoting instead of macro quoting.  That is so much less confusing.  Your macro can then just remove the quotes before using the value.

 

%macro generate_data(in=,out=,where=,statements=);
data &out;
  set &in ;
%if %length(&where) %then %do;
  where &where ;
%end;
  %sysfunc(dequote(&statements)) ;
run;
%mend generate_data;

%generate_data(in=sashelp.class,out=test1
,statements=
'wt_kg = weight/2.2046226218 ;
 ht_cm = 2.54 * height;
 bmi = wt_kg/ht_cm**2;
'
);

View solution in original post

10 REPLIES 10
PaigeMiller
Diamond | Level 26
%let var=(;
%put %bquote(&var);

By the way, I can't think of a good reason to have a macro variable set to a value of an unmatched parenthesis. If you are intending on using this in the building of some string somewhere in your code, there are probably much better ways to handle this ... but of course, then you'd have to tell us what exactly you are trying to do ... and then you'd probably have to kill us <--- that's a joke

 

--
Paige Miller
DmitryErshov
Obsidian | Level 7

Hello! Thanks for fast answer!

 

I want to write my own macro for updating some table with columns a, b and c.

 

%macro updateTable(set=,where=);
...
%mend;

Business user can use this macro to update the table. Example:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')));

Macro updates the table according to user instructions and make some additional transformations.

 

But user can make an error in some parameter. Ex. forget bracket:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')) <-- one bracket has been lost

I want to assign where = c in ('1', '2', '3' in this case and process this exceptional situation with my own algorithm. 

 

Is it possible?

 

Thanks!

Reeza
Super User

@DmitryErshov wrote:

 

Is it possible?

 

Thanks!


Anythings possible. I think the question is it worth the time to deal with such a small mistake rather than having a good error message that tells them what's wrong. Another option entirely is to make a prompt page that allows them to select what they want that is structured so they cannot make those types of mistakes since the interface won't allow it. If you're using SAS EG, you can use prompts. In Base there's %windows which is a bit outdated but still works. 

 

Quentin
Super User

I don't think %BQUOTE can help you.  It's designed to mask characters in a resolved value at macro execution time.

 

Of course you could try using %STR() if you really wanted to, but then you would have to mark the parentheses with %.

 

But big picture, I agree with @Reeza, this doesn't seem like a good road to go down.  If you have people who are writing code that uses your macro, I think it's their responsibility to write a proper macro call.

 

If they accidentally submit a call with unmatched parentheses:

%updateTable(set=(a=a+1, b=b+2)
            ,where=(c in ('1','2','3')
             )

the macro won't even execute. SAS will keep waiting for the final parenthesis to end the macro invocation.   (Well, Display Manager SAS would keep waiting for it, EG might provide an extra close parenthesis in its magic string).   I don't see how you could have SAS make that execute.

 

 

As a SAS programmer, you learn to recognize and deal with unclosed macro calls and unmatched quotes and unclosed macro definitions and blah blah blah.  Even if you don't think of your users as programmers, if they are writing macro calls, they need to learn how to debug macro calls, and recover from bad macro calls.  I don't think you can protect them from this particular mistake, since the mistake prevents the macro from executing.

 

 

 

 

 

BASUG is hosting free webinars Next up: Jane Eslinger presenting PROC REPORT and the ODS EXCEL destination on Mar 27 at noon ET. Register now at the Boston Area SAS Users Group event page: https://www.basug.org/events.
Astounding
PROC Star

Just a gut reaction ...

 

I would feel safer forcing the users to construct a data set:

 

data want;

length action $ 9 rule $100;

action = "calculate";

   rule = "a = a + 1";

   output;

   rule = "b = b + 2";

   output;

action = "subset";

   rule = "c in ('1', '2', '3')";

   output;

run;

 

Then the responsibility falls on you to take the data set contents and parse them, including them in the macro.

 

It's not necessarily simple, but I would imagine it's easier on the users.  And the users can at least test their DATA step to make sure it contains no syntax errors before trying to call the macro.

PaigeMiller
Diamond | Level 26

I agree with the others, trying to fix syntax errors isn't going to be easy. There are many cases, not just forgetting a parenthesis. What if they leave out a single quote, or leave out a double quote, or a semi-colon, then you have a real nightmare, you've got to check for all of these things. I doubt you could get that working in any reasonable amount of time.

--
Paige Miller
Tom
Super User Tom
Super User

@DmitryErshov wrote:

I want to write my own macro for updating some table with columns a, b and c.

 

%macro updateTable(set=,where=);
...
%mend;

Business user can use this macro to update the table. Example:

 

%updateTable(set=%bquote(a=a+1, b=b+2),where=%bquote(c in ('1','2','3')));

 


The only commonly used characters that really cause havoc in macro calls are commas. And even those are fine if they are enclosed in quotes or parentheses.  Your second parameter is no problem. But if your macro parameters accept lists of values make sure not to use comma as the delimiter in the call.  So use something like | for example. 

 

So your example call just becomes. 

%updateTable
(set=a=a+1|b=b+2
,where=c in ('1','2','3')
);

If you really require quoting to get the macro call to work then consider using regular quoting instead of macro quoting.  That is so much less confusing.  Your macro can then just remove the quotes before using the value.

 

%macro generate_data(in=,out=,where=,statements=);
data &out;
  set &in ;
%if %length(&where) %then %do;
  where &where ;
%end;
  %sysfunc(dequote(&statements)) ;
run;
%mend generate_data;

%generate_data(in=sashelp.class,out=test1
,statements=
'wt_kg = weight/2.2046226218 ;
 ht_cm = 2.54 * height;
 bmi = wt_kg/ht_cm**2;
'
);
PaigeMiller
Diamond | Level 26

@Tom wrote:

The only commonly used characters that really cause havoc in macro calls are commas. And even those are fine if they are enclosed in quotes or parentheses.  

I don't view this as being that simple. There are plenty of syntax errors that you'd want to look for, like missing parameters, improperly formed macro arguments, as well as the problem of missing punctuation or punctuation in the wrong place. And who can say if the user is going to properly enclose his commas in quotes or parentheses?

--
Paige Miller
DmitryErshov
Obsidian | Level 7

Thank you very much guys for detailed analisis of my problem and code examples!

 

 

I agree that I can't analize all syntax errors, but approaches suggested by Tom is closest to what I want.

 

 

Ksharp
Super User

Yes. You are right. but %bquote() is usually for macro varibale. if it is a sting like yours , better use %str()

 

%let var=%str(%();
%put &var;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 2408 views
  • 8 likes
  • 7 in conversation