BookmarkSubscribeRSS Feed
JeffMeyers
Barite | Level 11

I'm currently developing a system of macros for creating figures in a component style (meta dataset that eventually writes out the GTL code).  One thing I've been trying to get to is being able to write a derived program including the code prior to the macro(s) being run.  Not to rerun that code, but to collect it so that it can be added to the final derived program.  I'm hoping to make something that's submittable to the FDA with minimal modifications so users don't have to go back and paste in all the macros used.

 

My online searches haven't found too much for me to go on.  Is there a way to grab the code submitted and save it into a dataset character column?  I'm thinking of either having a macro call with one parameter that is the code to be run, or having a start macro to start 'recording' followed by a finish macro to output the dataset.

 

Thanks for any input.

6 REPLIES 6
Tom
Super User Tom
Super User

Not sure I understand.

You are generating SAS code?  And you want to save it?

Why not just use a data step to generate the SAS code to a file directly?

You can do that with or without involving the macro processor.

JeffMeyers
Barite | Level 11

So as an example lets say that we're creating a figure for FDA submission.  I'm developing an in house macro to make something like a line plot.  The program the user runs to create this line plot looks like this:

 

data xx;

  set adam.stuff;

  programming stuff;

run;

other programming statements;

 

%glineplot(parameter stuff to make the plot);

 

My graphing macros will save the code they create (any prep steps, GTL code, SGRENDER code) to a separate file so that when time comes to submit to the FDA we don't have to go back and paste in the graphing macro code into the program.  The FDA requires us to either nest the macro or print the code directly into the program.  I'm trying to save on that step.  What I can't do is collect the code prior to the macro running (data XX.... stuff above).  I'm trying to find a way to extract that code and paste it into the separate file with the generated code so it includes everything in one shot.

Tom
Super User Tom
Super User

You might want to look at the MFILE option as that will store the generated macro code, but it will mean that it ran the code first.

 

But to do what you describe just re-write the macro so that it always generates the code to a file.  And then in the cases where you want it to actually run the generated code have it execute a %INCLUDE of the file it just generated.

Tom
Super User Tom
Super User

For very simple macros (ones where what code they generate later on does not depend on the execution of the code they generated earlier) you might be able to use PROC STREAM to process the program file.

 

Try this simplistic example:

filename program temp;
filename results temp;
options parmcards=program;
parmcards4;
data xx;
  set adam.stuff;
  programming stuff;
run;
other programming statements;
%glineplot(parameter stuff to make the plot);
;;;;

%macro glineplot(parm);
proc sqplot ;
 * &parm ;
run;
%mend glineplot;

proc stream outfile=results prescol; BEGIN
* Generated by PROC STEAM ;
%include program;
;;;;

data _null_;
  infile results;
  input;
  put _infile_;
run;

 

Ksharp
Super User

Why not using a single marcro to wrap all these (any prep steps, GTL code, SGRENDER code)  and following macros together ? Like : %outer macro

https://blogs.sas.com/content/sgf/2022/12/21/decode-your-sas-macro-code/

 

%macro cars;
data cars;
set sashelp.cars;
run;
%mend;

%macro outer;
/*(any prep steps, GTL code, SGRENDER code) */
data xx;
  set sashelp.class;
run;
proc print;run;

/*tool macros*/
%cars
%mend outer;
 


filename mprint "c:\temp\outer.sas";
options mprint mfile;
%outer
Patrick
Opal | Level 21

For macros and included code what could work is using options.

options mautolocdisplay source2;

These two options write the paths to the source code into the log for any code that has been executed. You then could parse the log for these paths and copy the source code to your report.

 

Example: I've stored below attached .sas files under c:\temp and then run below code.

/* add c:\temp to SAS Autocall Facility */
options insert=(sasautos='C:\temp');

/* set option that writes macro source path to SAS log */
options mautolocdisplay;
%demo(Hello World);

/* set option that writes location and code of included scripts to SAS log */
options source2;
%include 'C:\temp\demo3.sas';

 

This will create SAS log that contains the paths to both the macro and included program source code. 

The approach will also work for nested macro calls and for "utility" macros that get compiled as part of a call to another macro.

It will also work for "overlay" macros where the source code exists in more than one location.

And it will also work for nested %include statements (=an included program containing an %include to another program).

31         /* set option that writes macro source path to SAS log */
32         options mautolocdisplay;
MAUTOLOCDISPLAY(DEMO):  This macro was compiled from the autocall file C:\temp\demo.sas
33         %demo(Hello World);


MAUTOLOCDISPLAY(DEMO_UTIL):  This macro was compiled from the autocall file C:\temp\demo.sas
MAUTOLOCDISPLAY(DEMO2):  This macro was compiled from the autocall file C:\temp\demo2.sas

demo:       Hello World
demo_util:  Hello Again
demo2:      Hello from another place
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.01 seconds
      

34         
35         /* set option that writes location and code of included scripts to SAS log */
36         options source2;
37         %include 'C:\temp\demo3.sas';
NOTE: %INCLUDE (level 1) file C:\temp\demo3.sas is file C:\temp\demo3.sas.
38        +%put '2nd call of macro %demo';
'2nd call of macro %demo'
39        +%demo(Hello World once more);
MAUTOLOCDISPLAY(DEMO):  This macro was compiled from the autocall file C:\temp\demo.sas
MAUTOLOCDISPLAY(DEMO_UTIL):  This macro was compiled from the autocall file C:\temp\demo.sas
2                                                          The SAS System                     Thursday, October 10, 2024 11:34:00 AM

MAUTOLOCDISPLAY(DEMO2):  This macro was compiled from the autocall file C:\temp\demo2.sas

demo:       Hello World once more
demo_util:  Hello Again
demo2:      Hello from another place

What you won't get is the path to source code that has been called in code but never has been executed (i.e. a macro call that didn't get executed because the call was within an %IF condition that was false).

 

I can't think of a way how you could directly get the source code of custom formats stored in some permanent library. You could search for the format along the paths stored in option FMTSEARCH and if found use proc format cntlout= to write the format definition to a SAS dataset.

 

If you also got custom functions (proc fcomp) then I believe a similar approach could be possible.

 

 

SAS Innovate 2025: Call for Content

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!

Submit your idea!

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
  • 6 replies
  • 206 views
  • 0 likes
  • 4 in conversation