Reputation: 19
I have a script to write a SAS program (txt) that looks like this:
/********* Import excel spreadsheet with model sepcs *****************/
proc import file = "&mydir\sample.xls" out = model dbms = xls replace;
run;
/********* Create program model *****************/
data model;
set model;
dlb = resolve(dlb);
dub = resolve(dub);
run;
data model;
set model;
where2 = tranwrd(where,"="," ");
where2 = tranwrd(where2,"<"," ");
where2 = tranwrd(where2,">"," ");
nword = countw(where2);
bounds = trim(dlb)!!" "!!trim(dub);
bounds = tranwrd(bounds,"="," ");
bounds = tranwrd(bounds,"<"," ");
bounds = tranwrd(bounds,">"," ");
nbounds = countw(bounds);
run;
proc sql noprint;
select max(nword) into: max_word from model ;
select max(nbounds) into: max_aux from model ;
select name into: list_var separated by " " from dictionary.columns where libname = "WORK" and memname = "IMP" ;
quit;
/******* Generate Model ********/
%macro generate_model;
data model;
set model;
attrib wherev length = $500.;
do i = 1 to countw(where2);
%do j = 1 %to %sysfunc(countw(&list_var));
if upcase(scan(where2,i)) = "%upcase(%scan(&list_var,&j))" and scan(where2,i) not in ("0","1","2","3","4","5","6","7","8","9") then do;
if missing(wherev) then wherev = trim(scan(where2,i));
else if index(wherev,trim(scan(where2,i))) = 0 then do;
wherev = trim(wherev)!!" "!!trim(scan(where2,i));
end;
end;
%end;
end;
drop i where2;
run;
data model;
set model;
attrib aux length = $500.;
do i = 1 to countw(bounds);
%do j = 1 %to %sysfunc(countw(&list_var));
if upcase(scan(bounds,i)) = "%upcase(%scan(&list_var,&j))" and scan(bounds,i) not in ("0","1","2","3","4","5","6","7","8","9") then do;
if missing(aux) then aux = trim(scan(bounds,i));
else if index(aux,trim(scan(bounds,i))) = 0 then do;
aux = trim(aux)!!" "!!trim(scan(bounds,i));
end;
end;
%end;
end;
drop i bounds;
run;
%mend;
%generate_model;
data outem.bound;
set outem.model;
attrib txt length = $2000.;
txt = "******************Macros for variable"!!trim(dep)!!"******;";
output;
txt = "%"!!"macro bound"!!trim(dep)!!";";
output;
if not missing(lb) then do;
txt ="LB="!!trim(lb)!!";";
output;
end;
if not missing(ub) then do;
txt ="UB="!!trim(ub)!!";";
output;
end;
if not missing(dlb) and not missing(lb) then do;
txt ="LB=MAX(LB,"!!trim(dlb)!!");";
output;
end;
if not missing(dlb) and missing(lb) then do;
txt ="LB="!!trim(dlb)!!";";
output;
end;
if not missing(dub) and not missing(ub) then do;
txt ="UB=MIN(UB,"!!trim(dub)!!");";
output;
end;
if not missing(dub) and missing(ub) then do;
txt ="UB="!!trim(dub)!!";";
output;
end;
txt = "%"!!"mend;";
output;run;
data outem.imp;
set outem.bound;
file "&mydir\3_generate_models\3_model.sas" lrecl = 2000;
put txt;
run;
The program works fine, however i can't manage to put empty space before UB
or LB
.
The output looks like this:
%macro boundHC0340;
LB= 1;
UB= 9;
%mend;
But I would like to get this:
%macro boundHC0340;
LB= 1;
UB= 9;
%mend;
The code already has some attempts to put empty space before UB
and LB
, but so far I couldn't manage.
I can put other characters and strings in there. I just can't put empty space before UB
and LB
in order to produce indented code.
I've tried something like this:
txt =" LB="!!trim(lb)!!";";
But the empty space before LB
does nothing.
However if i write this:
txt ="******LB="!!trim(lb)!!";";
I get the asterisks on my program.
Any idea of what I'm missing here?
Thank you very much for your support.
Best regards
Ps: here's the hyperlink to sample xls file: sample.xls
Upvotes: 1
Views: 1936
Reputation: 51566
Assuming that you have built the variable TXT with the value you want to see you just need to add a format to your final step. To avoid writing a lot of useless trailing blanks use the $VARYING
format. You will need to calculate the length of your string to use that format.
data outem.imp;
set outem.bound;
file "&mydir\3_generate_models\3_model.sas" lrecl = 2000;
length= lengthn(txt);
put txt $varying2000. length;
run;
But it is probably easier to just skip all of the concatenation and just use the power of the PUT statement itself to write the program directly from your data. Then you can use things like pointer controls (@3
) or named value lb=
and other features of the PUT
statement to format your program file.
data _null_;
set outem.model;
file "&mydir\3_generate_models\3_model.sas" ;
put 72*'*' ';'
/ '* Macros for variable ' dep ';'
/ 72*'*' ';'
/ '%macro bound' dep ';'
;
if not missing(lb) then put @3 lb= ';' ;
if not missing(ub) then put @3 ub= ';' ;
if not missing(dlb) and not missing(lb) then put
@3 'LB=MAX(LB,' dlb ');'
;
if not missing(dlb) and missing(lb) then put
@3 'LB=' dlb ';'
;
if not missing(dub) and not missing(ub) then put
@3 'UB=MIN(UB,' dub ');'
;
if not missing(dub) and missing(ub) then put
@3 'UB=' dub ';'
;
put '%mend bound' dep ';';
run;
Although looking at the logic of those IF statement why not reduce them to:
put @3 'LB=MAX(' lb ',' dlb ');' ;
put @3 'UB=MIN(' ub ',' dub ');' ;
Upvotes: 1
Reputation: 9569
I think this is the result of SAS applying left alignment by default for the $w.
format of your variable when you use your put statement. You can override this by applying a format in the put statement and specifying what alignment you want to use:
data _null_;
file "%sysfunc(pathname(work))\example.txt";
a = " text here";
/*Approach 1 - default behaviour*/
/*No leading spaces on this line in output file (default)*/
put a;
/*Approach 2 - $varying + right alignment*/
/*We need to right align text while preserving the number of leading spaces, so use $varying. */
/*If every line is the same length, we can use $w. instead*/
/*Use -r to override the default format alignment*/
varlen = length(a);
put a $varying2000.-r varlen;
/*Approach 3 - manually specify indentation*/
/*Alternatively - ditch the leading spaces and tell SAS which column to start at*/
put @4 a;
run;
Try changing the last part of your code so it looks a bit like this (fix paths and dataset names as appropriate):
data bound;
set model;
attrib txt length = $2000.;
txt = "******************Macros for variable"!!trim(dep)!!"******;";
output;
txt = "%"!!"macro bound"!!trim(dep)!!";";
output;
if not missing(lb) then do;
/* LEADING SPACES ADDED HERE */
/* LEADING SPACES ADDED HERE */
/* LEADING SPACES ADDED HERE */
txt =" LB="!!trim(lb)!!";";
output;
end;
if not missing(ub) then do;
/* LEADING SPACES ADDED HERE */
/* LEADING SPACES ADDED HERE */
/* LEADING SPACES ADDED HERE */
txt =" UB="!!trim(ub)!!";";
output;
end;
if not missing(dlb) and not missing(lb) then do;
txt ="LB=MAX(LB,"!!trim(dlb)!!");";
output;
end;
if not missing(dlb) and missing(lb) then do;
txt ="LB="!!trim(dlb)!!";";
output;
end;
if not missing(dub) and not missing(ub) then do;
txt ="UB=MIN(UB,"!!trim(dub)!!");";
output;
end;
if not missing(dub) and missing(ub) then do;
txt ="UB="!!trim(dub)!!";";
output;
end;
txt = "%"!!"mend;";
output;
run;
data _null_;
set bound;
file "%sysfunc(pathname(work))\example.sas" lrecl = 2000;
varlen = length(txt);
put txt $varying2000.-r varlen;
run;
x "notepad ""%sysfunc(pathname(work))\example.sas""";
Contents of example.sas (based on sample xls):
******************Macros for variableHC0340******;
%macro boundHC0340;
LB= 1;
UB= 9;
%mend;
Upvotes: 1