I recently inherited a SAS program that looks something like this:
%MACRO ComplicatedStuff( GroupId= );
%LET FileId = %SYSFUNC( OPEN( Work.BigDataSet ) );
%PUT 'Doing something really difficult with ' &GroupId.;
%LET CloseRC = %SYSFUNC( CLOSE( &FileId. ) );
%MEND ComplicatedStuff;
%ComplicatedStuff(GroupId=ABC1);
%ComplicatedStuff(GroupId=DEF2);
%ComplicatedStuff(GroupId=3GHI);
%ComplicatedStuff(GroupId=J4KI);
Being a multi-faceted programmer, I looked at this and thought "surely I can make this a least a little bit more dynamic". Sure enough, I was able to develop what I thought was a simple solution using CALL EXECUTE:
DATA Work.IDs;
INPUT ID $4.
;
DATALINES;
ABC1
DEF2
3GHI
J4KI
RUN;
DATA Work.CommandDebug;
SET Work.IDs;
Command = CATS(
'%ComplicatedStuff(GroupId=', ID, ');'
);
CALL EXECUTE( Command );
RUN;
I was happy with this solution until it came time to FTP the files generated by ComplicatedStuff to a different server. Our SAS server is running on Unix and the SAS admins created a helpful little macro for us to call named %sas_sftp (because, I've been told, the x code gets really ugly). Unfortunately, I cannot post the %sas_sftp code - it belongs to my company and I don't think they want it on SO.
I attempted to call the %sas_sftp macro just as I had called the %ComplicatedStuff macro (both as a second CALL EXECUTE within the same data step, and as a second data step), but only the first file (of about 30) would make it to the destination. When I looked at the log, it looked like the second macro started executing before the ftp had finished (the ftp pipe, or whatever it is, hadn't been released before the next ftp started), so the subsequent ftps were simply silently failing due to resource unavailability (I presume).
I thought that the EXECUTE would basically queue up my macro calls and then execute them as if they were sequentially located in the code (as they originally were) - one at a time. Clearly something else is going on because, while the first approach above worked without issue, my dynamic solution failed. I poured over CALL EXECUTE: How and Why and the SAS documentation, but I'm afraid I just don't understand what they are talking about.
I did eventually find a work around (or rather, a colleague found one) which I posted below as an "answer", but I'd really like someone to explain the EXECUTE function and how it works.
Why didn't my first attempt, using CALL EXECUTE, work?
%sas_sftpbut you don't show that in your code. Are you trying to add a secondCALL EXECUTEto the same data step or do you have a second data step that just runs the%sas_sftppart? And BTW, I also have a utility macro of the same name! The problem may be with exactly WHAT that macro is doing. I don't think mind could be run withCALL EXECUTEeither because it creates and executes anexpectscript. - BellevueBobCALL EXECUTEto the data step. When that didn't work, I tried a second DATA NULL step. Same result in both cases. - JDB%nrstrmacro function during the call. In other words, you show code that works but didn't show what does not work. - BellevueBob