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

I use following code in multiple programs. My problem is that if I change any code here then , I need to make same changes in multiple programs to keep it synchronized.

Is there a way to write a macro, insert the following code in that macro and call that macro in all programs? In that way I just if I need to make updates then I just need to makes changes to one macro and need not worry about keeping all programs synched up. 

Data A;

set B;

if prxmatch("m/XXX/oi",Partner1) > 0 then Principa =  'X';

if prxmatch("m/YYYY/oi",Partner1) > 0 then Principal_SDC= 'Y';

if prxmatch("m/ZZ/oi",Partner1) > 0 then Principal_SDC= 'Z';

if prxmatch.....

if prxmatch..

.

.

.

.

run;

Thanks,

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

A few suggestions ...

First, the call to the macro should be simpler:

data want;

   set have;

   %prxmatch

run;

Since your macro contains the statements that should be part of the DATA step, there is no need to add CALL EXECUTE.  This won't solve your current problem, but it will solve the one that would have resulted if your program actually located the macro.

Second, when you say that your folder contains your macro, is it saved in a file named prxmatch.sas?

Third, just as a precaution, get rid of all capital letters.  This probably won't matter on a PC but could easily matter on other operating systems.  So the name of the file that holds the macro definition should be prxmatch.sas, and the %MACRO and %MEND statements should refer to prxmatch, and the call to the macro should read %prxmatch.

Good luck.


View solution in original post

12 REPLIES 12
PaigeMiller
Diamond | Level 26

Yes, you want a macro library, you can create a folde somewhere and then when you launch SAS, you use the SASAUTOS= option to point to this folder. Every SAS macro program in this folder is now available to you for use without you specifically including the macro code.

For example, if you have SASAUTOS=(sasautos "\\myserver\mydir\paiges_macros") then every SAS program in that folder is available to your programming. If you have a program in there called donothing.sas which contains %macro dothing; then in any program you write, %donothing is a recognized macro name.

So, then, if you update this one macro program, every program that calls it gets the updated macro. And of course, you can have as many macros in this folder as you want.

--
Paige Miller
buckeyefisher
Obsidian | Level 7

PaigeMiller,

I followed the step and following is the code.

options sasautos=(sasautos "\\C:\Users\Macro"); * this has my macro  - PRXmatch

Data want;

set have;

call execute('%PRXmatch');

run;

this is the macro

%macro Prxmatch;

if prxmatch("m/XXX/oi",Partner1) > 0 then Principal= 'X';

..

%mend PRXmatch;

It gives me this error - Apparent invocation of macro PRXMATCH not resolved.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

The macro is not being defined until after the datastep where it is used is called.  Put the %macro before the datastep.  However, you could just do away with the macro as that isn't adding anything.  Post some test data/required output if you want a more comprehensive answer. 

buckeyefisher
Obsidian | Level 7

RW9,

My input file has strings on which I want to run PRXmatch command and there are more than 500 Proxmatch commands that I want to run. The 500+ commands are used in multiple programs hence I want to use a macro.

Required output - Extract the 500+ strings into the output file.

Hope this helps.

-----------------------

options sasautos=(sasautos "\\C:\Users\Macro"); * this has my macro  - PRXmatch

Data want;

set have;

call execute('%PRXmatch');

run;

this is the macro

%macro Prxmatch;

if prxmatch("m/XXX/oi",Partner1) > 0 then Principal= 'X';

..

%mend PRXmatch;

-----------------------

RW9
Diamond | Level 26 RW9
Diamond | Level 26

So, you have a file which is full of commands.  The question then is why do you need the macro approach.  At the start of your program just do:

data _null_;

     length cmd $2000;

     infile "xyz.txt" end=eof;

     input cmd $;

     if _n_=1 then call execute('data want; set have;');

     call execute(strip(cmd)||";");

     if eof then call execute('run;');

run;

To add a better example:

I have a file tmp.txt, with two rows: 1) if a=1 then b=1;, 2) if a=2 then b=2;

%macro Get(inds=,outds=);

  data _null_;

    length cmd $200.;

    infile "s:\temp\rob\tmp.txt" dlm="¬" end=eof;

    input cmd;

    if _n_=1 then call execute("data &outds.; set &inds.;");

    call execute(cmd);

    if eof then call execute("run;");

  run;

%mend Get;

data have;

  a=1;output;

  a=2;output;

  a=3;output;

run;

%get (inds=have,outds=want);

Astounding
PROC Star

A few suggestions ...

First, the call to the macro should be simpler:

data want;

   set have;

   %prxmatch

run;

Since your macro contains the statements that should be part of the DATA step, there is no need to add CALL EXECUTE.  This won't solve your current problem, but it will solve the one that would have resulted if your program actually located the macro.

Second, when you say that your folder contains your macro, is it saved in a file named prxmatch.sas?

Third, just as a precaution, get rid of all capital letters.  This probably won't matter on a PC but could easily matter on other operating systems.  So the name of the file that holds the macro definition should be prxmatch.sas, and the %MACRO and %MEND statements should refer to prxmatch, and the call to the macro should read %prxmatch.

Good luck.


RW9
Diamond | Level 26 RW9
Diamond | Level 26

Yes, I see what your getting at.  Setup the text file so it can just be included, i.e. have the text file:

if a=1 then b=1;

if a=2 then b=2;

Then in the code just do:

data have;

  a=1;output;

  a=2;output;

  a=3;output;

run;

data want;

  set have;

  %include "s:\temp\rob\tmp.txt";

run;

Good shout that, didn't think of the include in the code itself.

PaigeMiller
Diamond | Level 26

While %include will work in some situations, it isn't as flexible or powerful as using SASAUTOS and it has drawbacks. So perhaps in this limited example, %include works as well as SASAUTOS, but I would like to point out some situations where it does not work as well.

For example, if you have a macro with different arguments

%macro mymacro(arg1=0,arg2=100);

and today you want to call it with arg1=0 and arg2=98, and tomorrow you want to call it with arg1=1 and arg2=14, then the %include approach requires you to edit the file to place these arguments into the code somewhere, and the next time you call it, you can (mistakenly) get these arguments again, unless you remember to edit the macro and change the arguments to the new values that they should take on. And I'm thinking that once you have developed a working macro, you don't want to be constantly editing solely for the purpose of changing the arguments.

The other drawback to %include is that you have to constantly type the entire line of text including the exact location of the file (which means you have to remember the exact folder location, and type it without typographical errors) as

%include "s:\temp\rob\mymacro.sas";

instead of just typing the macro name with a % sign in front of it such as (if said macro was defined with no arguments)

%mymacro

or with arguments

%mymacro(arg1=0,arg2=98)

Note: in either case, you don't have to remember the location of the macro, and there is no risk of mistyping the location of the macro.

--
Paige Miller
PaigeMiller
Diamond | Level 26

options sasautos=(sasautos "\\C:\Users\Macro");

I think it should be

options sasautos=(sasautos "C:\Users\Macro");

--
Paige Miller
jakarman
Barite | Level 11

500+ strings as a source. That sounds like the strings are coming from some system and are being stored somewhere.
You do not like to copy/paste that. But you can make a program that read that all and transform those in usable code parts.
The idea of creating source-members (RW9) that are included in the other programs could be the fat and most simple approach for that.

Creating source member is putting them writing them as external files like data and including them later as source. Not too difficult to do.

It is using the behavior of SAS as interpreter language and not using the compilation segregation as with many other languages.   

---->-- ja karman --<-----
buckeyefisher
Obsidian | Level 7

Two solutions worked perfectly. One with including a text file and other with calling a macro (and yes making all small caps and saving it as .SAS file).

data want;

  set have;

  %include "s:\temp\rob\tmp.txt";

run;

data want;

   set have;

   %prxmatch

run;

Thanks you very much !!!

Ron_MacroMaven
Lapis Lazuli | Level 10

There are just a few reasons to use macros

* conditionals: %if

* loops: %do

* %sysfunc, %sysevalf

* write a function to return a value.

In the example you have posted, I see none of the above.

Others have pointed out the %include statement,

which is what I, too, recommend.

The differences, in your situation, where the code is only repetition and has not need of macro statements

* code in the %included program is always compiled in that step.

* a macro call generates a search of the sasautos library (set of folders)

and an %include of the file containing the macro

the code is compiled before being used in the step.

From the way I read your post, you are using this set of prx* statements in multiple programs,

but not more than once in any one program.

If that is true then there is no benefit to using a macro for this suite of statements.

Since I run all my programs in batch,

you may reply that you run several different programs in a session,

in which case the savings gained by the macro being compiled are worthy of consideration.

Caveat: just do not change the macro and expect the changes to show up in your next call of the macro.

you are using the compiled version of the macro

you have to recompile the macro, for which there are two ways to get it updated:

1. options mrecall;

2. %include 'my-macro';

Ron Fehd  macro maven

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
  • 12 replies
  • 1230 views
  • 6 likes
  • 6 in conversation