Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

SAS MACRO not resolving macro variables

Status
Not open for further replies.

bashshar

Programmer
Jan 13, 2011
1
US
Basically, I want to read two columns from a csv file and create a text file for each record. The text file name is the first column and I want to write the second column to this text file.
CSV file records sample:
column1 column2
txtfile1 file1data
txtfile2 file2data
txtfile3 file3data
txtfile4 file4data

<**** start code ****>
%LET CSVFile_FullPath=C:\projects\csvFile.csv;
%LET Directory_FullPath=C:\projects\txtFilesFolders;

data _null_;
infile "&CSVFile_FullPath" dsd dlm=',' firstobs=2 truncover missover;
input col1 :$8. col2 :$9.;
/*build the text file name*/
txtFile="&Directory_FullPath"||"\"||col1||".txt";
/* pass txt file name and data to a macro*/
%WriteTo(txtFile,col2);
run;
/*parms: file name and data*/
%macro WriteTo(fle,dta);
%let f="&fle";
data _null_;
file &f mod;
put &dta;
run;
%mend WriteTo;
<**** end code ****>

The file that is being created is txtFile.txt, instead of txtfile1.txt, txtfile2.txt, txtfile3.txt, txtfile4.txt. It seems that the macro is not resolving the macro variable for some reason.
I appreciate any help.
 
You are mixing the execution times of macro and the datastep in your coding. Before any datastep or other code is executed, macros are resolved and executed - regard it as a "pre-compiler".

Your macro contains a datastep, and it is positioned within a datastep, so the first DS executes up to the macro call and SAS "gently" assumes an invisible "run;" before the one (!) datastep created by the macro call. That datastep gets executed, then you have a final hanging "run;" which you planned for the first datastep.

Why the filename and content is wrong? The macro parameter FLE gets assigned the string "txtFile", the DTA parameter gets "col2" - the macro call does not know the variables from the table or their content, it consumes string and macro variable content as parameter values. As a side note, the macro definition must be placed before the use, so unless you have an AUTOCALL library, you need to submit the macro code before any use of it.

Also careful with not setting length for variable txtFile - it will be defined by the first assignment then, so in case your first col1 isn't the longest of the whole set, you will have corrupted file names.

Off for a solution now. This works if you do not have too many files and content is limited; all is read into memory, a macro variable can hold a string of up to 64KB. Each filename and the content is read into a macro variable in memory, the two are indexed via a counter as part of the macro variable name. The number of files to write is in &NUMFILES. A macro loops over these variables and executes a datastep per file to write content to it. If content is larger or too many files are to created (limited RAM), you could either go via SCL statements or by creating the code in a single SAS file and including the file (%include) - but that is a different story:

[TT]%let numFiles=0;

data _null_;
infile "&CSVFile_FullPath" dsd dlm=',' firstobs=2 truncover missover;
input col1 :$8. col2 :$9.;
/*-- changed as of here... */
length idx $5;
idx = strip (put (_n_, BEST32.));
call symput ('_file' !! idx, strip(col1));
/* this not allows leading/trailing spaces in content */
call symput ('_content' !! idx, strip(col2));
call symput ('numFiles', idx);
run;

%macro writeAll;
%do idx=1 %to &NUMFILES.;
data _null_;
file "&DIRECTORY_FULLPATH.\&&_FILE&idx.." mod;
put "&&_CONTENT&idx..";
run;
%end;
%mend;
%writeAll;[/TT]

Cheers,
Matthias
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top