resize.sas
%macro resize (data=, out=);
%*----------------------------------------------------------------;
%* Author: Richard DeVenezia
%*
%* Resize a dataset by minimizing the length of each character column.
%*
%* Minimal length is defined as the shortest length that does not
%* lose any data in a column. Note: After minimizing, some columns
%* might be too short to store new values when editing or adding rows.
%*
%* data - data set to resize
%* out - output data set
%*
%* mod:
%* 11/17/98 rad initial coding
%*----------------------------------------------------------------;
%if (%superq(DATA)= or %superQ(OUT)=) %then %do;
%put You must specify both data= and out=;
%goto ByeBye;
%end;
proc contents noprint data=&DATA out=_contnt_(index=(varnum));
run;
%local dsid nvars rc needed;
%let dsid=%sysfunc(open(_contnt_));
%if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NOBS));
%let rc=%sysfunc(close(&dsid));
%end;
%else %goto ByeBye;
%local zero;
%do i=1 %to &nvars;
%local var&i typ&i len&i mln&i;
%end;
data _null_;
set _contnt_;
call symput ('var'||left(_n_), name);
if type=2
then call symput ('typ'||left(_n_), '$');
else call symput ('typ'||left(_n_), ' ');
call symput ('len'||left(_n_), length);
run;
proc sql noprint;
drop table _contnt_;
select
0
%do i=1 %to &nvars;
%if &&typ&i=$ %then ,max(length(&&var&i)) ;
%end;
into
:zero
%do i=1 %to &nvars;
%if &&typ&i=$ %then ,:mln&i ;
%end;
from &DATA
;
quit;
%let needed = 0;
%do i = 1 %to &nvars;
%if &&typ&i=$ %then
%let needed = %eval (&needed OR (&&mln&i < &&len&i));
%end;
%if (%superq(data) ne %superq(out)) or &needed %then %do;
%if not &needed %then
%put NOTE: There is nothing to resize, but OUT is different than DATA;
data &OUT;
retain %do i=1 %to &nvars; &&var&i %end;;
length %do i=1 %to &nvars;
%if &&typ&i=$ %then &&var&i $ &&mln&i ;
%end;;
set &DATA;
run;
%end;
%else %do;
%put NOTE: OUT is same as DATA (&data) and DATA has no slack, resize not done.;
%end;
%ByeBye:
%mend resize;
/*
%resize (data=sashelp.class, out=work.class)
%resize (data=work.class, out=work.class)
%resize (data=work.class, out=work.class2)
*/;