01-08-2016 09:34 AM - edited 01-11-2016 03:47 AM
Hi, i'm new the the fourm and to Sas. So please excuse the simplicity of my question.
Im trying to do the following:
retain delta 0;
infile "&path.\SomeFile.csv" dsd firstobs=2
lrecl=32767 encoding="UTF-8" end=eof;
input modstatus :$12.;
if not(upcase(substr(modstatus,1,3))='NEW') then
if eof then do;
if delta or _n_ le 9999 then
if not(delta) and _n_ gt 9999 then
This code will not evaluate the conditional expression with the Macro Processor, and therefor macro variable loadtype will not be set. So my question is, how can I get the conditional expression to evaluate as expected in this code setup?
Thank you for anwser's, and would really appriciate a explanation concering conditional expressions in this type of situation.
01-08-2016 09:55 AM - edited 01-08-2016 09:57 AM
Its nothing to do with the conditional. It is to do with the process of execution. A program is first sent to the macro pre-processor, this fully expands all the macro to plain base SAS code, this is then fed into the compiler. Think of it this way, at the time the call symput is called, this is part of the macro pre-processor, it is not then going to feed back into the pre-processor, but only get fixed at that one point.
To be honest though I don't see why you put any of that code in a macro anyways, what does dataset dt1 look like, and why would you need to execute the same code for each row in that dataset? There is nothing in the data _null_ step which would require any sort of macro? So, lets start from the beginning, what is it your trying to do? Provide example test data. I would also point out that you miss out the instance where _n_=9999. Also, you can simplfy the code:
if delta or _n_ le 9999 then call symput('loadtype','DELTA'); else call symput('loadtype','FULL');
Finally your logic:
if not(upcase(substr(modstatus,1,2))='NEW') then
Cannot be correct, the first 2 characters of modstatus cannot be the 3 characters of "NEW".
Perhaps this is the type of thing you were looking for, based off the condition, call either delta load or full load:
data have; retain delta 0; infile "somefile.csv" dsd firstobs=2 lrecl=32767 encoding="UTF-8" end=eof; input modstatus :$12.; if not(upcase(substr(modstatus,1,3))='NEW') then delta=1; if eof then do; if delta or _n_ le 9999 then call execute('%Load_Delta;'); else call execute('%LoadFull;'); end; run;
Or if its the same macro with a paramter change:
if delta or _n_ le 9999 then call execute('%LoadData (Type=Delta);'); else call execute('%LoadData (Type=Full);');
01-11-2016 03:41 AM
01-11-2016 04:44 AM
Simply put, no I am afraid. I don't have access to the whole setup, so can't really avise on that, I gave a couple of workarounds, but its really something you need to assess in relation to the big picture. I.e. how things fit together in the functiona design specification. As I mentioned there is no reason why that code needs to be a macro, so why put it in a macro. Your FDS should show a module flow diagram how each part of the program interacts with others, so you pull out the offending module and redesign that. In 99.9% of instances macro language is not required. There are other trechniques - putting parameters in datasets for instance rather than macro variables, which are far more robust and easy to validate and program against.
01-11-2016 05:10 AM
Hi, thanks for reply. Let me get the ball rolling with a ugly example that works, and hopefully some technical explenation to exactly how and why this is working, compared to the original code:
filename kore catalog 'work.catalog.kore.source' lrecl=1024; data _null_; set ds1; file kore; put '%mp;'; run; %inc kore; /*as before*/
Macro program mp is unchanged.
01-11-2016 05:29 AM
However I would still strongly advise that you re-assess your coding. Functional Deisgn Specifications -> Coding in Base SAS (keep it simple smart!) -> Testing -> production lifecycle.
01-08-2016 10:52 AM
If you correct the SUBSTR issue pointed out by @RW9 and replace the colon after "data _null_" (in macro MP) by a semicolon, I think, LOADTYPE should be set (as a global macro variable, because the local symbol table of macro MP is empty). But I share @RW9's opinion that a restructured code will probably make more sense. In particular, LOADTYPE would not be available inside the first data step (if that is where you tried to use it).
01-11-2016 03:46 AM