- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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(¯oVariableName||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 😞
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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");
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
You forgot to enclose ¯oVariableName with double quotes as the first argument to call symput is a string.
%macro rowToMacroVariable(dataSetName,variableName,macroVariableName);
data &dataSetName;
set &dataSetName;
call symput("¯oVariableName"||left(_n_),&variableName);
run;
%mend;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks gamotte,
But its not working 😞
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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 xyz;) 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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 🙂
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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 ¯ovariablename;
proc sql noprint;
select &variablename into :¯ovariablename separated by ','
from &datasetname
;
quit;
%mend;
%rowToMacroVariable(sashelp.class,name,test);
%put &test;
Now you have one global macro variable that contains all values.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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");
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Astounding ! It works ... Thanks a lot :smileyhappy
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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