DATA Step, Macro, Functions and more

Create Dynamic macro variable with Call Symput

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 15
Accepted Solution

Create Dynamic macro variable with Call Symput

Hi team,

 

I am trying to create dynamic macro variable with names in sequence and values as observation.

I have used below code but it is not working. Request you to please review:

data ab;
input id$;
cards;
A1
A2
A3
;
run;

 

%macro rowToMacroVariable(dataSetName,variableName,macroVariableName);

data &dataSetName;

set &dataSetName;

call symput(&macroVariableName||left(_n_),&variableName);

run;

 

%mend;

%rowToMacroVariable(ab,id,id);

%rowToMacroVariable(ab,id,TJ);

 

Now it should have created below macro variabls:

id1 A1

id2 A2

id3 A3

TJ1 A1

TJ2 A2

TJ3 A3

 

but it is not working Smiley Sad

 

 

 


Accepted Solutions
Solution
‎03-01-2017 07:05 AM
Super User
Posts: 5,085

Re: Create Dynamic macro variable with Call Symput

If the only remaining issue is making these macro variables global, switch from CALL SYMPUT to CALL SYMPUTX.  It supports a third argument, that can simply be specified as "G" to make the macro variables global.

 

call symputx("macro_variable_name", "macro_variable_value", "G");

View solution in original post


All Replies
Regular Contributor
Posts: 194

Re: Create Dynamic macro variable with Call Symput

Hello,

 

You forgot to enclose &macroVariableName with double quotes as the first argument to call symput is a string.

 

%macro rowToMacroVariable(dataSetName,variableName,macroVariableName);
data &dataSetName;
	set &dataSetName;
	call symput("&macroVariableName"||left(_n_),&variableName);
run;
%mend;
Occasional Contributor
Posts: 15

Re: Create Dynamic macro variable with Call Symput

Thanks gamotte,

 

But its not working Smiley Sad

Super User
Posts: 6,946

Re: Create Dynamic macro variable with Call Symput

[ Edited ]

Since you create your macro variables in a macro, they are created local to the macro and won't exist in the global table when the macro has finished.

Why do you want to put such a rather simple operation in a macro?

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Super User
Posts: 7,407

Re: Create Dynamic macro variable with Call Symput

[ Edited ]

Well, first off, as always, why.  Macro is not a replacement for Base SAS programming, it is just a find/replace mechanism.  In 99% of the cases I have seen people using macro it is because they don't know Base SAS well enough and try to patch it up, which ends up with messy, unmanigable code.  So the question is what are you trying to do with these macro variables - there are many methods of working with data, and even metadata which require no macro code (arrays, normalisation, variable lists, sashelp tables etc.) all designed to make your coding simple.  

The reason I mention the above is that from your code its clear you don't understand macro programming.  Let me start by suggesting you read up on Variable Scope.  Creating macros witihin the macro means that they are Local to the macro, and not available outside the macro.  Secondly your code needs a few tweaks:

data _null_;
set ab;
call symput("id"||strip(put(_n_,best.)),id);
run;

This code will work, note you don't need to create a dataset (data xyzSmiley Wink to do this, as the data already exists.  Secondly the you need to quote the macro variable to get it to resolve in the above i just put "id", but it would be "&Macrovariable"||...

This will create a whole set of macro variables based on the data, and they will be Global to the area where you run it.

 

However that is all by the by, this is really not the way to proceed.

Occasional Contributor
Posts: 15

Re: Create Dynamic macro variable with Call Symput

Hi RW9,

 

Thanks for such a good explanation. I agree with _null_ even i have used this in programming but while posting it on community i have designed a seperate example. Even my code was working fine with this way but I am not able to make this id1 variable as global. So can you please let me know where i am missing ?

 

Now why I have used this in macro is because in my scripts we have 10 separate datasets and I need to create seperate global macro variables that are already used in further programming. I know we can optimize these things but its an level 2 task so please understand somebody's situation before commenting on there knowledge skills or why they have used those thing.

 

I agree that you must be having wide knowldge and I am happy to have people like you on SAS community because this is how we can learn and enhance our skills on SAS Smiley Happy

 

 

Super User
Super User
Posts: 7,407

Re: Create Dynamic macro variable with Call Symput

You have hilighted the issue yourself then "we have 10 separate datasets" - if your able to generalise your code, then these datasets will be similar if not the same, structurally.  Thus put those 10 datasets together on under the other, use indsname= to get filename if you need to, then process the data as one file with by groups.

 

You can't define macros witihin a macro as they will be local, unless you explicitly set them as global beforehand - hence you would need to hard code either in the main program as %global, or define them in the main program as I gave earlier.  Even a change to the thinking would mitigate this, rather than have these in a macro, define them in the main program, and have your macro calls just do the function.  

Super User
Posts: 6,946

Re: Create Dynamic macro variable with Call Symput

If you need to keep lists of things from step to step, it's usually better to store them in datasets and use those to create dynamic code or formats or similar. It depends on what you need to do with those lists further on.

Another way to store lists in macro variables is

%macro rowToMacroVariable(dataSetName,variableName,macroVariableName);
%global &macrovariablename;
proc sql noprint;
select &variablename into :&macrovariablename separated by ','
from &datasetname
;
quit;
%mend;

%rowToMacroVariable(sashelp.class,name,test);

%put &test;

Now you have one global macro variable that contains all values.

 

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Posts: 6,946

Re: Create Dynamic macro variable with Call Symput

And keep in mind that all those macro variables have to be kept in memory, and you can run out of RAM space. Or macro variables with lists can exceed the maximum size of macro variables. Datasets are virtually infinite in comparison.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Solution
‎03-01-2017 07:05 AM
Super User
Posts: 5,085

Re: Create Dynamic macro variable with Call Symput

If the only remaining issue is making these macro variables global, switch from CALL SYMPUT to CALL SYMPUTX.  It supports a third argument, that can simply be specified as "G" to make the macro variables global.

 

call symputx("macro_variable_name", "macro_variable_value", "G");

Occasional Contributor
Posts: 15

Re: Create Dynamic macro variable with Call Symput

Thanks Astounding ! It works ... Thanks a lot :smileyhappy

Valued Guide
Posts: 505

Re: Create Dynamic macro variable with Call Symput

Related but does not answer ops question

Defining a large number of global macro variables;

inspired by
https://goo.gl/YRzFGM
https://communities.sas.com/t5/Base-SAS-Programming/Create-Dynamic-macro-variable-with-Call-Symput/m-p/336912

HAVE
====

Up to 40 obs from sashelp.class total obs=19

Obs    NAME       SEX    AGE    HEIGHT    WEIGHT

  1    Alfred      M      14     69.0      112.5

  2    Alice       F      13     56.5       84.0  (turn into macro variables)

  3    Barbara     F      13     65.3       98.0
  4    Carol       F      14     62.8      102.5
  5    Henry       M      14     63.5      102.5
  6    James       M      12     57.3       83.0
  7    Jane        F      12     59.8       84.5
  8    Janet       F      15     62.5      112.5
  9    Jeffrey     M      13     62.5       84.0
 10    John        M      12     59.0       99.5
 11    Joyce       F      11     51.3       50.5
 12    Judy        F      14     64.3       90.0
 13    Louise      F      12     56.3       77.0
 14    Mary        F      15     66.5      112.0
 15    Philip      M      16     72.0      150.0
 16    Robert      M      12     64.8      128.0
 17    Ronald      M      15     67.0      133.0
 18    Thomas      M      11     57.5       85.0
 19    William     M      15     66.5      112.0


WANT macro variables NAME SEX AGE HEIGHT WEIGHT
===============================================

NAME        = Alice
SEX         = F
AGE         = 13
HEIGHT      = 56.5
WEIGHT      = 84

FULL SOLUTION
=============

%symdel name sex age height weight; * just in case you rerun;
%let dsid = %sysfunc(open(sashelp.class(where=(name='Alice')),i));
%syscall    set(dsid);
%let rc   =%sysfunc(fetchobs(&dsid,1));
%let rc   =%sysfunc(close(&dsid));


%put
   &=NAME
   &=SEX
   &=AGE
   &=HEIGHT
   &=WEIGHT
   ;

NAME        = Alice
SEX         = F
AGE         = 13
HEIGHT      = 56.5
WEIGHT      = 84

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 11 replies
  • 276 views
  • 1 like
  • 6 in conversation