BookmarkSubscribeRSS Feed
OS2Rules
Obsidian | Level 7

Hi All:

Just a quick question here:

I take great effort to make my code readable, but when programs with imbedded macro programs are executed the macro code in the SAS log is all over the place.  Is there any way to retain the original format to make it more easily readable?

Thanks in advance.

8 REPLIES 8
Tom
Super User Tom
Super User

Do you have examples of what you mean?

In general the issue I have seen is that for long statements the MPRINT lines will be flowed into a single line.  Indentation is also lost.

Is this what you are talking about?  If so I think you are out of luck.

What you can control are your comments.

When writing a macro I distinquish in my comments those that are useful when reviewing the log and those that are useful when editing or reviewing the code.  An example of the latter is and explaination of a particularly tricky piece of code or a special syntax requirement so that I don't break the code code the next time I edit it.

For the first type I use normal *...; comments. These will print with the code lines when MPRINT is on.  For the latter I use %*... ; comments.  I try not to use /* */ comments other than for header blocks and rarely when I need to embed a comment in the middle of a statement.

Placement of your comments are important.

1) Do not put *..; comments at the end of a line after the code because then the comment prints below the statement in the log.

2) Place comments for conditional blocks of code inside the conditional so that they will print only when the condition is true.

%if %sysfunc(exist(mydata)) %then %do;

* Generate summary of MYDATA;

proc summary data=mydata ....

%end;

OS2Rules
Obsidian | Level 7

I'll do the best I can with the code samples....

Here is my code (just a small part of the program):

545    if substr("&imember",11,1) = 'A' and length(account_number) ge 10 then do;

546        if substr(account_number,10,1) = '-' then substr(text,14,12) = account_number;

547        else do;

548            substr(text,14,9) = substr(account_number,1,9);

549            substr(text,23,1) = '-';

550            substr(text,24,2) = substr(account_number,10,2);

551            end;

552        end;

553

554    if substr("&imember",11,1) = 'C' then do;

555        substr(text,14,12) = account_number;

556        substr(text,26,1) = ' ';

557        substr(text,35,1) = ' ';

558        end;

559

560    substr(text,27,8) = trade_date;

561

And this is how my log looks (sort of):

if substr("46TR092911A.xls",11,1) = 'A' and

46  + length(account_number) ge 10 then do;       if substr(account_number,10,1) = '-' then substr(text,14,12) = account_number;       else do;           substr(text,14,9) =

substr(account_number,1,9);           substr(text,23,1) = '-';           substr

47  +(text,24,2) = substr(account_number,10,2);           end;       end;    if substr("46TR092911A.xls",11,1) = 'C' then do;       substr(text,14,12) = account_number;       substr(text,26,1) = ' ';

      substr(text,35,1) = ' ';       end;    substr(text,27,8

48  +) = trade_date;    transaction_type = upcase(transaction_type);        if transaction_type =: 'B' then  trans_type = '100';   else if transaction_type =: 'S' then  trans_type = '690';   else if

transaction_type =: 'E' then  trans_type = '400';   else if

Which makes it rather hard to read.  The text seems to loose all syntax.  It actually goes beyond the right side of my screen in the SAS log window.  (Here it seems to wrap within this window).

It's not a big problem, but it is a pain in the backside.

Tom
Super User Tom
Super User

The + signs are usually an indication of included code and not macro generation. 

Normally I turn off SOURCE2 and turn on MPRINT.

How are you calling the macro?  Are you using SAS/Connect so that macro is generating code that is sent to the remote session?

Tom
Super User Tom
Super User

Are you using CALL EXECUTE to call the macro?

You might try changing that to instead write code to a file and %INC the file.  Here is an example.

275 %macro test;

276 data x;

277  line1='This is testing how long lines of code look';

278  line2='This is testing how long lines of code look';

279  line3='This is testing how long lines of code look';

280 run;

281 %mend test;

282

283 data _null_;

284   call execute('%test');

285 run;

MPRINT(TEST):  data x;

MPRINT(TEST):  line1='This is testing how long lines of code look';

MPRINT(TEST):  line2='This is testing how long lines of code look';

MPRINT(TEST):  line3='This is testing how long lines of code look';

MPRINT(TEST):  run;

NOTE: DATA statement used (Total processtime):

     real time           0.00 seconds

     cpu time            0.00 seconds

NOTE: CALL EXECUTE generated line.

1   +data x;  line1='This is testing how longlines of code look';  line2='This istesting how long

lines of code look';  line3='This is testing how long lines of codelook'; run;

NOTE: The data set WORK.X has 1 observationsand 3 variables.

NOTE: DATA statement used (Total processtime):

     real time           0.01 seconds

     cpu time            0.00 seconds

286

287 filename code temp;

288 data _null_;

289   file code;

290   put '%test;';

291 run;

NOTE: The file CODE is:

     Filename=C:\DOCUME~1\ABERNA~1\LOCALS~1\Temp\SAS TemporaryFiles\_TD2288\#LN00010,

     RECFM=V,LRECL=256,File Size (bytes)=0,

     Last Modified=30Sep2011:14:29:38,

     Create Time=30Sep2011:14:29:38

NOTE: 1 record was written to the file CODE.

     The minimum record length was 6.

     The maximum record length was 6.

NOTE: DATA statement used (Total processtime):

     real time           0.00 seconds

     cpu time            0.01 seconds

292 %inc code;

MPRINT(TEST):  data x;

MPRINT(TEST):  line1='This is testing how long lines of code look';

MPRINT(TEST):  line2='This is testing how long lines of code look';

MPRINT(TEST):  line3='This is testing how long lines of code look';

MPRINT(TEST):  run;

NOTE: The data set WORK.X has 1 observationsand 3 variables.

NOTE: DATA statement used (Total processtime):

     real time           0.00 seconds

      cpu time            0.00 seconds

OS2Rules
Obsidian | Level 7

Sorry for the delay - going to be a busy week...

You are correct - i run this code from a CALL EXECUTE.  Unfortunately, I can't change thsi because the code runs against each member of a directory  In cases when I do use the %INCLUDE, I don't have this problem.

I usually turn off SOURCE2 as well, but I need to see what is happening during development.

Tom
Super User Tom
Super User

Why do you think that you cannot change it to not use CALL EXECUTE?

Change a program like this:

data _null_;

  set members ;

  call execute(cats('%nstr(%%mymacro)','(',memname,');'));

run;

to a program like this:

filename code temp;

data _null_;

   set members;

   file code;

   put '%mymacro(' memname ');' ;

run;

%inc code / source2 ;

Tom
Super User Tom
Super User

This is because SAS is expanding the macro and passing the statements onto the command stack.  You can prevent this by using %NRSTR to protect the macro call from executing at that point. Then SAS will push the macro call onto the stack and it will then execute after the current data step has finished.  There are also other timing issues that can be solved by using this technique.

Here is an example to show the difference in how the log will look.

%macro x;

* This is a macro with a few lines of code ;

Data _null_;

  x='Just to see what happens when it is invoked from ';

  y='call execute and see how it looks in the SAS log.';

run;

* end of macro x;

%mend x;

options mprint;

data _null_;

  call execute('%x;');

run;

data _null_;

  call execute('%nrstr(%%x;)');

run;

Peter_C
Rhodochrosite | Level 12

for a development stage, assign fileref mprint to a writeable file and switch on options MPRINT and MFILE. Then re-run your process. The option MFILE passes code generated by macros to the mprint file.

In enterprise guide 4.3 open that mprint file into a code window and "format code" the keyboard equivalent is CTRL+i

It will not be the original source, but will be readable.

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!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

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
  • 8 replies
  • 1201 views
  • 0 likes
  • 3 in conversation