/*just for reference*/
data a;
length x $20. y$20.;
input x$ y$;
cards;
a b
aaa bbbbbbbbbbbbbbbbbb
;
run;
%macro maxlen(lib=,mem=,out=);
proc sql noprint;
select name into: varlist separated by ' '
from dictionary.columns
where libname=%upcase("&lib.") and memname=%upcase("&mem.");
quit;
%let nvar=%sysfunc(countw(&varList));
%let varlast=%scan(&varList, &nvar.);
proc sql;
create table &out. as
select
%do i =1 %to %eval(&nvar.-1);
%let var =%scan(&varList, &i);
max(length(&var.)) as &var.len,
%end;
max(length(&varlast.)) as &varlast.len
from a;
quit;
%mend maxlen;
proc sql;
select count(name) into: num from (select name,type from dictionary.columns where libname='WORK' and memname='A') where type='char';
quit;
data _null_;
set A end=last;
array var _character_;
array var_length(&num) $;
array _var(&num) $;
retain var_length:;
length varlist $50;
do i=1 to #
if length(var(i))>var_length(i) then var_length(i)=length(var(i));
end;
if last then do;
do i=1 to #
_var(i)=vname(var(i))||' $'||trim(left(var_length(i)));
You have to read the data in twice, one for measuring the proper length for variables, the other for defining the correct length for variables. Here is a simple way,
data _null_;
retain lenx leny;
length x $200 y $200;
infile cards eof=eof;
input x y;
lenx=max(1,length(x));
leny=max(1,length(y));
return;
eof:
call symputx('lenx', catt('$',lenx));
call symputx('leny', catt('$',leny));
cards;
a b
aaa bbbbbbbbbbbbbbbbbb
;
%put &lenx &leny;
data tmp;
length x &lenx y &leny;
infile cards ;
input x y;
cards;
a b
aaa bbbbbbbbbbbbbbbbbb
;