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

Hi,

 

This is somewhat related to my previous post but the issue is different.

 

Below is the macro I'm working with and some test code.

 

When I run this code with the mprint option, out of a total of four vchk calls I can only see the following two mprint lines for vchk:

MPRINT(VCHK): titi
MPRINT(VCHK): , tata

 

Both calls that deal with the non-existing toto variable don't generate any mprint line.

I'm guessing it's because the macro has nothing to generate in these instances since the variable doesn't exist.

I would like the macro to still generate an mprint line without interfering with any of the codes and I thought if a variable is missing then I could put a space instead. However, for some reason, I cannot have the macro put a simple blank space. It can put a non-break space, but that messes with the keep= code.

 

Is there a way to have my macro put a space when a variable is missing? Or at least generate an mprint line anyway?

Thanks!

 

%macro vchk(in=,var=,lib=work,sql=0,alias=,xcpt=descending,noxist=0);
%if 0<%length(&alias) %then %let alias=&alias..;
%if &sql %then %let coma=%str(,);
%else %let coma=;
%let vchk_lst=;
%let vchk_i=1;
%do %while(%scan(&var,&vchk_i,%str( ))^= );
%let vchk_itm=%scan(&var,&vchk_i,%str( ));
%if %length(&xcpt) and %upcase(&vchk_itm)^=%upcase(&xcpt) %then %do;
%let vchk_dsid=%sysfunc(open(&lib..&in));
%let vchk_vnum=%sysfunc(varnum(&vchk_dsid,&vchk_itm));
%let vchk_dsid=%sysfunc(close(&vchk_dsid));
%if 0<&vchk_vnum and ^&noxist %then %let vchk_lst=&vchk_lst &coma &alias&vchk_itm;
%else %if &vchk_vnum<1 and &noxist %then %let vchk_lst=&vchk_lst &coma &alias&vchk_itm;
%end;
%let vchk_i=%eval(&vchk_i + 1);
%end;
&vchk_lst
%mend vchk;


data titi1; titi=1; run;
data titi2; titi=1; tata=1; run;
data titi3; set titi1(keep=%vchk(in=titi1,var=titi) %vchk(in=titi1,var=toto)); run;
proc sql;
create table titi4 as select a.titi %vchk(in=titi1,var=toto,sql=1,alias=a) %vchk(in=titi2,var=tata,sql=1,alias=b)
from titi1 as a left join titi2 as b on a.titi=b.titi;
quit;

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

You could try mimicking the output of the MPRINT option with %PUT statement.

%put MPRINT(&sysmacroname): ;

But it will probably not appear in the right place since the macro code will evaluate BEFORE the macro has finished generating the other text to be executed. 

View solution in original post

13 REPLIES 13
Tom
Super User Tom
Super User

I doubt it. If there is no code generated then why would MPRINT() print anything?

 

Look into the MEXECNOTE and MFILE options.

tristevoix
Fluorite | Level 6

Indeed.

For some of my other macros I can have them put out a ; and that solves my problem.

But that doesn't work with this macro and others like this one.

That's why I was hoping there would be a way to generate something neutral like a blank space.

It seems that nbsp and " " don't interfere with the sql code, but they do with the data step.

If there's no way to put a blank space, is there some other token or something that would be neutral to both codes?

Otherwise I'll have to deal with this issue in the log rather than at the source.

Tom
Super User Tom
Super User

I don't understand why you would need to see things that don't exist.

tristevoix
Fluorite | Level 6

Because I'm trying to recreate the program with resolved lines.

 

For example, for the following code, I would use the mprint lines to replace the %vchk calls.

The code would go from this:

create table titi4 as select a.titi %vchk(in=titi1,var=toto,sql=1,alias=a) %vchk(in=titi2,var=tata,sql=1,alias=b)
from titi1 as a left join titi2 as b on a.titi=b.titi;
quit;

 

To this, where %vchk(in=titi2,var=tata,sql=1,alias=b) is replaced with the mprint line:

create table titi4 as select a.titi %vchk(in=titi1,var=toto,sql=1,alias=a) , tata
from titi1 as a left join titi2 as b on a.titi=b.titi;
quit;

 

Because I have no mprint line for  %vchk(in=titi1,var=toto,sql=1,alias=a) I cannot replace it with anything that matches that particular macro call.

The option I have left is to assume that if I have nothing to match then it probably means the macro generated nothing. But I don't like to assume.

 

Somehow I missed the second line of your previous post. Yeah, a post of two lines and I only read half.

 

Anyway, mprint simply reroutes the mprint lines in an outside file and so if there was none in the log there won't be any in the outside file.

The other option, mexecnote, generates the following line:

NOTE: The macro VCHK is executing from memory.

 

I see it four times, so that at least tells me vchk was called four times even though I only see two mprint lines. This might help reinforce the assumption above.

 

I'd rather still see an mprint line, though. 😉

Tom
Super User Tom
Super User

I still don't get what the issue is. If you want a copy of what code the macro generates use the MFILE option or your parsing program.

If you want the logic of HOW the program generates that code then use the actual program.

Tom
Super User Tom
Super User

You could try mimicking the output of the MPRINT option with %PUT statement.

%put MPRINT(&sysmacroname): ;

But it will probably not appear in the right place since the macro code will evaluate BEFORE the macro has finished generating the other text to be executed. 

tristevoix
Fluorite | Level 6

Well, it works. 😃

Because of the way I'm subdividing lines in the log I do match the mimicked mprint with the correct code line and thus I end up with two mprint lines where I only got one before.

 

Thanks! =D

PaigeMiller
Diamond | Level 26

Is there a way to have my macro put a space when a variable is missing? Or at least generate an mprint line anyway?

 

%if &macrovariable= %then %do;
    %let blank = %str( );
    %put ***&blank***;
%end;
--
Paige Miller
tristevoix
Fluorite | Level 6

Yes, I tried stuff like that, however, the %put doesn't create an mprint line in the log.

 

What I need instead is something like this where the macro would output a blank space:

%if &macrovariable= %then %do;
%let blank = %str( );
&blank <<<===
%end;

 

However, that doesn't seem to work with whatever %str or %nbquote etc. that I tried. The macro just refuses to put the blank space in the code.

PaigeMiller
Diamond | Level 26

%PUT was never intended to show up in the MPRINT. Why does it have to be in the MPRINT output anyway?

 

However:

 

%macro dothis;
%let abc=;
proc glm data=sashelp.class;
   class sex;
   model height=weight sex;
	%if &abc= %then %do;
	%let blank=%str( );
	%put MPRINT(DOTHIS): &blank;
	%end;
run; quit;
%mend;
%dothis

 

--
Paige Miller
tristevoix
Fluorite | Level 6

Because I'm trying to recreate the program from the log with all macro variables resolved and all macro calls replaced with the code lines they generate in order to send to clients programs they can run independently from macros and other support programs.

 

And %put an mprint line is indeed the solution I wasn't apparently able to come up with on my own.

I still have a lot to learn. 😃

Tom
Super User Tom
Super User

@tristevoix wrote:

Because I'm trying to recreate the program from the log with all macro variables resolved and all macro calls replaced with the code lines they generate in order to send to clients programs they can run independently from macros and other support programs.

 

And %put an mprint line is indeed the solution I wasn't apparently able to come up with on my own.

I still have a lot to learn. 😃


How does having a line in the log with NO code on it help you create a program ?  There is no code there.

tristevoix
Fluorite | Level 6

That's what I tried to explain above.

Let me paste it here and try to expand on it.

---

For example, for the following code, I would use the mprint lines to replace the %vchk calls.

The code would go from this:

create table titi4 as select a.titi %vchk(in=titi1,var=toto,sql=1,alias=a) %vchk(in=titi2,var=tata,sql=1,alias=b)
from titi1 as a left join titi2 as b on a.titi=b.titi;
quit;

 

To this, where %vchk(in=titi2,var=tata,sql=1,alias=b) is replaced with the mprint line:

create table titi4 as select a.titi %vchk(in=titi1,var=toto,sql=1,alias=a) , tata
from titi1 as a left join titi2 as b on a.titi=b.titi;
quit;

 

Because I have no mprint line for  %vchk(in=titi1,var=toto,sql=1,alias=a) I cannot replace it with anything that matches that particular macro call.

The option I have left is to assume that if I have nothing to match then it probably means the macro generated nothing. But I don't like to assume.

---

 

Basically, it's just a question of having a resulting code to match with any macro call.

If I have no resulting code for any one macro call then, as mentioned above, I start assuming that the macro didn't have anything to output. Instead of assuming I'd prefer to be certain by having a one-to-one match between macro calls and resulting codes.

Hopefully that makes sense.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 13 replies
  • 4262 views
  • 1 like
  • 3 in conversation