Download resize.sas resize.sasSubmit a comment

%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)
*/;