- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
%let var=abcd;
%macro macro1(&var);
Statement;
%mend macro1;
Looks like it does not resolve the macro variable var.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
You didn’t ask it to do anything….
%let var=abcd;
%macro macro1(myMacroVar=&var);
%put &myMacroVar;
%mend macro1;
*run the macro;
%macro1;
@kumarsandip975 wrote:
Can someone please help how to pass values from outside macro defined variables into Macro parameter. Below is one example.
%let var=abcd;
%macro macro1(&var);
Statement;
%mend macro1;
Looks like it does not resolve the macro variable var.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
What you have between %macro... and %mend is the macro definition. All it does when you run it is to compile the macro.
You have to call the macro if you want it to execute.
Macro definition:
%macro mymac1(myMacroVar);
%put &myMacroVar;
%mend;
Calling the macro:
%let var=abcd;
%mymac1(&var);
%mymac1(some other value just as a hard coded string);
And here how to call the macro once per iteration of a data step:
data _null_;
set sashelp.class;
call execute( cats('%mymac1(',name,');') );
run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Here is the requirement,
If number_of_folders=5 then we should pass like (folder1,folder2,folder3,folder4,folder5) and call macro with hardcoded values , couls be anything (SAS, ABCD, XYZ, KJD, SAS1)
%macro macro2(folder1,folder2,folder3,folder4,folder5);
%do i=1 %to &number_of_folders;
data folderItems1(rename=(name=name&i));
set folderItems1;
run;
proc sql noprint;
select id into: folderId from folderItems1
where name&i="&folder&i";
quit;
filename resp TEMP;
proc http url="https://graph.microsoft.com/v1.0/me/drives/&driveId./items/&folderId./children"
oauth_bearer="&access_token"
out = resp;
run;
libname jresp json fileref=resp;
data folderItems1;
set jresp.value;
run;
%end;
%mend macro2(SAS, ABCD, XYZ, KJD, SAS1);
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@kumarsandip975 Below should show you how this can work.
%macro mymac1(sentence);
%local n_words;
%let n_words=%sysfunc(countw(&sentence,%str( )));
%do i=1 %to &n_words;
%let word=%scan(&sentence,&i,%str( ));
%put The word is: &word;
%end;
%mend;
%mymac1(folder1 folder2 folder3)
The alternative approach would be to use a driver table. I prefer this over parsing a string as it keeps the macro code simpler and keeps the macro call more data driven.
data driver;
input word $;
datalines;
folder1
folder2
folder3
;
%macro mymac1(word);
%put The word is: &word;
%mend;
data _null_;
set driver;
call execute( cats('%mymac1(',word,')') );
run;
And what every experienced SAS developer does: FIRST develop your code for a single case without any macro code involved. Once this code fully works identify the locations in the code that need to by dynamic. That will then guide you how many macro parameters you really need. Taking such an approach makes it also much easier to debug your code as when it works on the single case level but not once "macrotized" then you know where to investigate. If you do everything together at once then you have first to figure out if your Base SAS logic is wrong or just something with the macro that generates this Base SAS code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
The concept of passing a list to a macro is best done by using one parameter. Just use a delimiter to sperate the values. Do NOT use comma as the delimiter because that is already being used by the macro processor.
Normally you would use a space, just like normal SAS code uses spaces between words/tokens.
Or if a space could be part of one of the values use something else. For a list of directories you could use | since that cannot be used in a directory name.
%macro mymacro(folders);
%local i folder ;
%do i=1 %to %sysfunc(countw(&folders,|));
%let folder=%scan(&folders,&i,|);
.... code that uses &folder ....
%end;
%mend mymacro;
Note : The code your macro is trying to create looks incorrect (or at least overly convoluted). For example it kind of looks like you are trying to create or at least reference a series of macro variable, FOLDER1, FOLDER2 etc. But there does not really appear to be any need for so many macro variables. You only are working with one of them at a time. Plus the attempt to indirectly reference them is not valid. &FOLDER&I cannot work. That is referencing macro variables named I and FOLDER. You probably wanted instead to reference I and one of the many FOLDERxx macro variables instead. For that you need to delay resolving FOLDER until the suffix is added. You would use &&FOLDER&I
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
below code works fine, when I hard code ds1,ds2,ds3,ds4 etc....
%let no_of_dataset=4;
%let diff_dataset=SASHELP.CARS,SASHELP.AIR,SASHELP.GAS,SASHELP.CLASS;
%macro mymac1(ds1,ds2,ds3,ds4);
%do i=1 %to &no_of_dataset;
proc print data=&&ds&i(obs=2);
%end;
%mend;
%mymac1(&diff_dataset);
But, below code does not seems to be correct with error.
%let no_of_dataset=4;
%let diff_dataset=SASHELP.CARS,SASHELP.AIR,SASHELP.GAS,SASHELP.CLASS;
%let ds=ds1,ds2,ds3,ds4;
%macro mymac1(&ds);
%do i=1 %to &no_of_dataset;
proc print data=&&ds&i(obs=2);
%end;
%mend;
%mymac1(&diff_dataset);
Error message:
73 %let no_of_dataset=4;
74 %let diff_dataset=SASHELP.CARS,SASHELP.AIR,SASHELP.GAS,SASHELP.CLASS;
75 %let ds=ds1,ds2,ds3,ds4;
76 %macro mymac1(&ds);
ERROR: Invalid macro parameter name &. It should be a valid SAS identifier no longer than 32 characters.
ERROR: A dummy macro will be compiled.
77 %do i=1 %to &no_of_dataset;;
78 proc print data=&&ds&i(obs&ds=2);
79 %end;
80 %mend;
81
82 %mymac1(&diff_dataset);
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
You definitely cannot use the value of a macro variable to generate the list of parameters in the %MACRO statement. You have to actually list the parameter names in the source code.
So instead just use ONE parameter and pass in the list of values in that ONE parameter.
%macro mymac1(dslist);
%local i ds ;
%do i=1 %to %sysfunc(countw(&dslist));
%let ds=%scan(&dslist,&i);
proc print data=&ds(obs=2);
run;
%end;
%mend;
But now commas in the list of values becomes a problem.
If the macro variable DIFF_DATASET is the string
SASHELP.CARS,SASHELP.AIR,SASHELP.GAS,SASHELP.CLASS
And it is then referenced in this statement:
%mymac1(&diff_dataset);
Replacing the reference to DIFF_DATASET with its value you get this macro call
%mymac1(SASHELP.CARS,SASHELP.AIR,SASHELP.GAS,SASHELP.CLASS);
Which the macro processor is going to see as trying to pass values for 4 different parameters because each comma means the start of the next position parameter value.
That is what I mean by saying the using COMMA as the delimiter in your list of values is going to make things HARD.
You could use macro quoting.
When you call the macro:
%mymac1(%superq(diff_dataset));
Or when you define the macro variable.
%let diff_dataset=%str(SASHELP.CARS,SASHELP.AIR,SASHELP.GAS,SASHELP.CLASS);
Or you could use actual quotes or parentheses to protect the commas.
%mymac1("&diff_dataset");
%mymac1((&diff_dataset));
But then the body of the macro will need to remove them. That is easy in the case of quotes by using the dequote() function.
%let dslist=%sysfunc(dequote(&dslist));
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
You could try some trick to generate a %MACRO statement that includes a variable list of parameter names.
data _null_;
list='a,b,c';
call symputx('x',cats('''%macro mymac(',list,');'''));
run;
%put &=x;
%sysfunc(dequote(&x))
%put _local_;
%mend;
%mymac;
But that is really convoluted and prone to total collapse with even a minor mistake.