Well, there are several factors in this. Let me see if I can elaborate, Global macro variables are for information which can be used anywhere in the session. For instance setting username could be a global variable. The thing to remember about global variables is that they stick around for the whole session, so you need to be careful that you are using one that has correct data for the given situation, for instance if I set a global macro up as TODAYS_DATE=15JUL2014, and then I run my program tomorrow its going to be wrong. Local macro variables are useful for keeping information that is used within the scope of the block of code, e.g. within a macro. This then means that once a macro is completed these temporary variables are automatically removed, meaning they cannot be misused outside the block. There is however a third option, which also has pluses and negatives. That is keeping parameters within a dataset. Say you have a macro which loops over 60 different where clauses printing out a page for each one, you could put 60 macro definitions in the macro statement, or you could have a dataset of where clauses and pass that dataset in. Keeps it nice and simple. The downside is its a bit more complicated to work with this over the normal macro variables. User24feb provides an example above of named parameter passing: %macro xyz (Var1=,Var3=,Var2=,Var7=Something); In this instance it does not matter in which order the variables are used in the macro invocation, as they are named. You can also provide pre-defined values for option parameters, per Var7. The above style - in my opinion - is useful in situations where a macro is placed in a library and used by many people as it fixes input parameters so people don't need to know an order, can provide default data etc. Its easier to document. You also have positional parameters: %macro xyz (Var1,Var3,Var2,Var7); This is less typing and if the order of parameters is know simple syntax. You do however lose the clarity, for instance you need to know to pass the data for Var3 at the second position rather than the third or you will end up with the wrong result. In my opinion this should only be used within the scope of other macros/blocks of code. The reason is clarity. Yes my macro: %macro xyz (Dset=,Data_Order=,Output_location=); Is clear and can be documented easily, user can understand that. This can have several sub macros: %macro xyz (Dset=,Data_Order=,Output_location=); %local some_var=abcd; %macro Do_Loop (DS,LOC); The end user does not need to know what do_loop is, how it operates, what positional parameters are, or if it will remain once they leave xyz. Hence that macro and macro variable are encapsulated. This gets more important when talking about global standard libraries with many programs and programmers, so things like coding standards, documentation, examples, testing all become very important. Too often I see hundreds of sas files contain macros with no documentation examples, macro definitions with no relevance, useless macros (for instance why write a mysort() macro rather than use proc sort, it may save you a character or two to type, but if your not the initial programmer then it is not transparent - look up obfusication), no consistency, and macros which just don't work outside the environment they were initially programmed in. Macros, like Excel, get badly abused There is one other option also, this is code generation. Basically your macro pre-processor function is a find and replace tool. It takes your code and expands it out to a full program by following logic in macros and macro variables. You can do this by hand with a useful function called call execute(string); With this you can generate a string which executes after the completion of the current step (except for macro calls). Thus you can create any amount of code in a datastep and then have that execute afterwards, e.g. data _null_; set my_really_big_list_of_datasets; call execute('proc print data='||strip(dataset)||'; run;'); /* The above line is executed once per line in the dataset with the dataset name */ run; This would generate the code: proc print data=dataset_a; run; proc print data=dataset_b; run; proc print data=dataset_c; run; ... So as you can see there are many different methodologies, styles and theories, but from my side the most important is to think of the next user of your code and how they will need to modify/use it.
... View more