02-25-2016 04:51 PM - edited 02-25-2016 05:17 PM
As some of you may know, I have a large collection of (legacy) sas macros (http://www.datavis.ca/sasmac/
Some of these need to
create a temporary file and I've used the utility macros below in a quite a few top-level macros. Under Windows, there has always been the problem that it tries to use `drive:\temp` as the directory, and this fails if that directory doesn't exist.
I suppose I could just use `.` (the current directory), but perhaps someone has a better way?
/* --------------------------------------------------------------- TITLE: Handle temporary files in a system- and version-independent way. --------------------------------------------------------------- */ %macro tempfile(fileref,ls,options); %global tempfn; %if %length(&ls)=0 %then %let ls=80; %if %sysevalf(&sysver > 6.10) %then %do; filename &fileref temp &options %if %length(&ls)>0 %then lrecl=&ls; ; %end; %else %do; %if &sysscp = CMS %then %let tempfn=&fileref output a; %else %if &sysscp = WIN %then %let tempfn=&fileref..tmp; %else /* assume unix */ %let tempfn=/tmp/&fileref..tmp; filename &fileref "&tempfn" lrecl=&ls &options; %end; %mend; %macro tempdel(fileref); %global tempfn; %if length(&tempfn)=0 %then %goto done; *-- Avoid annoying flash with X commands; %if %sysevalf(&sysver > 6.10) %then %do; %let rc=%sysfunc(fdelete(&fileref)); %let rc=%sysfunc(filename(&fileref,'')); %end; %else %do; %if &sysscp = CMS %then cms erase &tempfn; %else %if &sysscp = WIN %then %do; options noxsync noxwait; run; %sysexec(erase &tempfn); run; options xsync xwait; run; %end; %else /* assume flavor of UNIX */ %sysexec(rm -f &tempfn); %end; filename &fileref clear; %let tempfn=; %done: %mend;
02-25-2016 05:04 PM
Couldn't you just create it on the fly:
x 'mkdir temp';
That could go right before the FILENAME statement. It might hiccup if that directory already exists, but you can test it to see if you get the result you want.
Of course if you ever want to find the directory, you have to know where it will be located. But that's another story for another day.
02-25-2016 05:26 PM
Well, you could always use %sysexec instead of X.
There are functions to check everything ... does a file exist, does a SAS data set exist ... there must be one that checks whether a folder exists. Since you're in the middle of a macro, assuming you find the proper function, you could use %IF/%THEN to determine whether or not to issue:
%sysexec mkdir temp;
Quotes are no longer needed when you switch from X to %SYSEXEC.
02-26-2016 04:54 AM
@Reeza has the simplest method,
filename your_file "%sysfunc(pathname(work))\your_file.txt";
Would get removed automatically at end of session then.
However, I am sure as part of the ongoing lifecycle management of those macros you would have a plan in place to review the code, identify new technologies/procedures etc. in subsequent releases of SAS and so would need to update these ongoing anyways, if thats the case then perhpaps new technology would remove the need for the temporary files? For instance, the graphs produced, could be created as template files which are stored, then you just put whatever data you want through those, no need to create text files with the code.
02-26-2016 09:17 AM
Just to be clearer: The macro does use filename ... temp ... in
%if %sysevalf(&sysver > 6.10) %then %do; filename &fileref temp &options %if %length(&ls)>0 %then lrecl=&ls; ; %end;
A typical use for this is in my table macro, http://www.datavis.ca/sasmac/table.html where I convert numeric variables to their formatted character strings by printing them to a temporary file and then reading the result back in. (Maybe there is now
an easier way to do this??). The code for this is:
%if %length(&char)>0 %then %do; /* * Force the VAR= variables to character. To do this cleanly, we * resort to printing the &out dataset, then reading it back as * character. * In SAS 9.3, this only works if ODS LISTING is turned on. */ %tempfile(table,&ls); %if %sysevalf(&sysver >9.2) %then %do; ods listing; %end; proc printto new print=table; options nodate nocenter nonumber ls=&ls ps=10000; proc print data=&out; id &var; var count; run; %if &syserr > 4 %then %let abort=1; %if &abort %then %goto DONE; proc printto print=print; %let tvar = %join(&var, $) $; %*put tvar=&tvar; %if %verify(&char, %str(0123456789))=0 %then %let clen=&char; %else %let clen=16; data &out; infile table length=len; length string $&ls &var $&clen; retain skipping 1; drop string skipping; input @1 string $varying. len @; if skipping=0 & string ^= ' ' then do; input @1 &tvar count; output; end; else input; if index(string,'COUNT')>0 then skipping=0; run; *proc contents data=&out; %tempdel(table); %if %sysevalf(&sysver >9.2) %then %do; ods listing close; %end;