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,
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.
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.
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.
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.
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;
-----------------------
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);
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.
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.
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.
options sasautos=(sasautos "\\C:\Users\Macro");
I think it should be
options sasautos=(sasautos "C:\Users\Macro");
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.
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 !!!
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 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.