10-01-2015 02:10 AM
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.
Kindly seeking someon'e help to achive this task.
10-01-2015 02:40 AM - edited 10-01-2015 02:42 AM
If I have understood it properly, you want to use a macro with a parameter. To do that you must do something like that
*to use it you must do something like that; "&path/¶meter1..TXT"; %mend;
%macro import_file(parameter1=); *to use it you must do something like that; "&path/¶meter1..TXT"; %mend;
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.
10-01-2015 02:50 AM
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?
10-01-2015 03:03 AM - edited 10-01-2015 03:04 AM
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;
10-01-2015 03:13 AM
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?
10-01-2015 03:19 AM
%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
10-01-2015 04:10 AM
From the following line, it seems you're hard coding the file names.
If so, I would like to have a macro without any hardcoding.
10-01-2015 04:32 AM - edited 10-01-2015 04:32 AM
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
10-01-2015 04:50 AM
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?
10-01-2015 09:28 AM
Does this get you what you are looking for?
proc sql noprint;
select distinct memname into :namelist separated by ' '
where libname = 'WORK' and memname ne '_PRODSAVAIL';
10-01-2015 08:51 AM
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);
10-02-2015 12:11 PM
10-02-2015 12:51 PM
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.
10-02-2015 11:48 PM