DATA Step, Macro, Functions and more

How to pass file names as macro prameters?

Reply
Super Contributor
Posts: 426

How to pass file names as macro prameters?

I've  a requirement to pass file names as argument to create a dataset. As of now, I've the code where I read file names from .txt file and then calling macro, but my managements wants me to pass file names as argument by considering the future requirements.

 

My Existing code will be like,

 

data log.output_file ;
  infile "&path/output_file.txt" firstobs=2 truncover ;
  input fname $400. ;
run;

%macro log_analysis;

data log.log_analysis;
set log.output_file;
filename=fname;
length fname $400;
infile dummy dsd truncover FILEVAR = fname END = end_of_file LRECL=32000;
DO WHILE (not end_of_file);
input var : $ 3000.;
..........
..........
%mend log_analysis;

data _null_;
  set log.output_file;
  if fname =: '/usr/sas/SASApp_STPServer' then call execute ('%log_analysis;');
else put 'no log files';
run;

 

With this code, I'm calling the macro based on the filename. Instead of that, I need to create a macro and then pass file names as argument.

 

Although I've referred the example 2 from the following,I could not suceed.

 

https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000210819.htm

 

Kindly seeking someon'e help to achive this task.

 

Thanks!

 

Frequent Contributor
Posts: 144

Re: How to pass file names as macro prameters?

[ Edited ]

If I have understood it properly, you want to use a macro with a parameter. To do that you must do something like that

 


%macro import_file(parameter1);

*to use it you must do something like that; "&path/&parameter1..TXT"; %mend;

%import_file(TEST);

or


%macro import_file(parameter1=);

*to use it you must do something like that;
"&path/&parameter1..TXT";

%mend;

%import_file(parameter1=TEST);

They look really similar, the first if you put multiples parameters, they must be given in the same order of the definition. In the second you could give values to parameter without matter about the order.

 

I recomend use the second one, because if you have a macro with 10 parameters is very difficult to remmember order.

Super Contributor
Posts: 426

Re: How to pass file names as macro prameters?

In your second example, how will you give the filenames to parameter without hardcoding? Can't we get the file reference and file name from .txt file and pass it to the macro parameter?

Frequent Contributor
Posts: 144

Re: How to pass file names as macro prameters?

[ Edited ]

You mean how to give a array of files to import and avoid to execute proc import for each parameter? You could define a character as separator of the array (I use to use # because sometimes files have spaces in names).

Uou could do something like

 

%macro import_files(File_names=);

%local i actual_file;
%do i=1 %to %sysfunc(countw(&File_names));
  %let actual_file=%scan(&File_names,&i,%str(#));
*Now you have a parameter Actual_file with the i-th file that could be use as macro parameter in a
data _null_ or proc import; %end; %mend;

%import_files(File_names=File1#File2#OtherFile);

 

Super Contributor
Posts: 426

Re: How to pass file names as macro prameters?

 

Thanks for your coninued support.

 

I can import the file via data step and I've the code to do that. I need to pass file names as parameter while I reading the file to create a dataset.

 

In the code below, could you please tell me the folder where it will search for the file?

Frequent Contributor
Posts: 144

Re: How to pass file names as macro prameters?

%macro import_files(File_names=);

%local i actual_file;
%do i=1 %to %sysfunc(countw(&File_names));
  %let actual_file=%scan(&File_names,&i,%str(#));  *Now you have a parameter Actual_file with the i-th file that could be use as macro parameter in a  data _null_ or proc import;

data log.output_file ;
  infile "&path/&actual_file..txt" firstobs=2 truncover ;
  input fname $400. ;
run;

%end;

%mend;%import_files(File_names=File1#File2#OtherFile);

I think that you want to do something like that, since it use the &path macro variable, it depend on want you put in this macro var

Super Contributor
Posts: 426

Re: How to pass file names as macro prameters?

From the following line, it seems you're hard coding the file names.

 

%import_files(File_names=File1#File2#OtherFile);

If so, I would like to have a macro without any hardcoding.

Frequent Contributor
Posts: 144

Re: How to pass file names as macro prameters?

[ Edited ]

You coud use the macro of http://support.sas.com/kb/45/805.html This macro search all files in a directory


%macro drive(dir,ext); 

	%local filrf rc did memcnt name;
                                                                                                                                        
  %let filrf=mydir;                                                                                                                      
                                                                                                                                        
  /* Assigns the fileref of mydir to the directory and opens the directory */                                                                    
  %let rc=%sysfunc(filename(filrf,&dir));                                                                                                
  %let did=%sysfunc(dopen(&filrf));                                                                                                              
  /* Returns the number of members in the directory */                                                                   
  %let memcnt=%sysfunc(dnum(&did));                                                                                                      
                                                                                                                                        
   /* Loops through entire directory */                                                                                                  
   %do i = 1 %to &memcnt;                                                                                                                
    
     /* Returns the extension from each file */                                                                                                                                    
     %let name=%qscan(%qsysfunc(dread(&did,&i)),-1,.);                                                                                   
                                                                                                                                        
     /* Checks to see if file contains an extension */                                                                                     
     %if %qupcase(%qsysfunc(dread(&did,&i))) ne %qupcase(&name) %then %do;                                                                  
                                                                                                                                        
     /* Checks to see if the extension matches the parameter value */                                                                      
     /* If condition is true prints the full name to the log       */                                                                      
      %if (%superq(ext) ne and %qupcase(&name) = %qupcase(&ext)) or                                                                       
         (%superq(ext) = and %superq(name) ne) %then %do;                                                                                     
         		%qsysfunc(dread(&did,&i))                  
      %end;                                                                               
     %end;                                                                                                                               
   %end;                                                                                                                                                                                                                                                                   
  /* Closes the directory  */                                                                                                            
  %let rc=%sysfunc(dclose(&did));                                                                                                        
                                                                                                                                        
%mend drive; 

%let FILES=%drive(&path);;

This macro return names separated by spaces not by #, so adapt the file

Super Contributor
Posts: 426

Re: How to pass file names as macro prameters?

Thanks a ton.

 

If I'm not wrong, I need to place the code at the begining, before I call the macro %log_analysis from my intial post. I think this time I need to call that macro with parameters something like below.

 

macro %log_analysis (&files);

 Am I right?

Frequent Contributor
Posts: 144

Re: How to pass file names as macro prameters?

yes, something like
%macro %log_analysis(parameter1=&files);
Valued Guide
Posts: 858

Re: How to pass file names as macro prameters?

Does this get you what you are looking for?

 

proc sql noprint;
select distinct memname into :namelist separated by ' '
from dictionary.columns
where libname = 'WORK' and memname ne '_PRODSAVAIL';

%put &namelist;

Super User
Super User
Posts: 6,495

Re: How to pass file names as macro prameters?

One of the nice features of SAS macros is that you can define parameters as positional and still call them by name.  You just can't do the reverse.

 

So if I had a macro defined like this:

%macro divide(numerator,denominator);
...
%mend divide;

I could call it many ways:

 

%divide(10,5);
%divide(numerator=10,denominator=5);
%divide(denominator=5,numerator=10);
%divide(10,denominator=5);
Super Contributor
Posts: 426

Re: How to pass file names as macro prameters?

I agree with you Tom.

However intially I don't know to dynamically pass the filenames as per my initial. I.e. without hardcoding the macro parameter values like yours.

You have any other solutions for my intial post before I try the solution suggested by others?
Super User
Super User
Posts: 6,495

Re: How to pass file names as macro prameters?

I really am not sure I understand the original question.  

 

If you have an existing piece of code and you want to change to a macro with parameters then just additify the pieces that change and make them parameters. Then in the code replace the original hardcoded text with the macro variable reference to the parameter.

 

So if you are talking about the adding a parameter to your original macro then the change should look like this.

 

%macro log_analysis(filename);

data log.log_analysis;
  length fname $400;
   infile "&filename" dsd truncover END = end_of_file LRECL=32000;
   fname="&filename" ;
  DO WHILE (not end_of_file);
    input var : $ 3000.;
..........
..........
%mend log_analysis;

Now this program will have a problem when called multiple times since the name of the data set is now hard coded.  But you could also convert that to a parameter.  Or you could add more complex logic to read thie current file and then append the result to a master dataset that would accumulate the data over multiple macro calls.

Super Contributor
Posts: 426

Re: How to pass file names as macro prameters?

Thanks for your prompt reply.

May I request you to tell me to append the datasets after I modify the datasets names as parameters? E.g. I will get three datasets if the macro is called three times. How to append these three datasets as one master dataset?
Ask a Question
Discussion stats
  • 18 replies
  • 554 views
  • 8 likes
  • 4 in conversation