Download sas2dbf.sas sas2dbf.sasSubmit a comment

%macro sas2dbf(in=,out=,keep=,drop=,dec=0,where=);
%put %str(   ) ;
%put %str(   ) Macro to convert SAS dataset to dbase file Ver 2.0B ;
%put %str(   ) Author: Richard Hockey Sep 1998 ;
%put %str(   ) Email: rhockey@mater.org.au;
%put %str(   ) ;
%if &in= %then %do;
  %put %str(  ) Usage: ;
  %put %str(      ) %nrstr(%SAS2DBF(IN= ,OUT= ,KEEP= ,DROP= ,DEC= ,WHERE=);) ;
  %put %str(  ) Parameters are: ;
  %put %str(      ) IN SAS DATASET without quotes.;
  %put %str(      ) OUT output dbase file. ;
  %put %str(      ) Optional parameters: ;
  %put %str(      ) either KEEP Variables to keep. ;
  %put %str(      ) or DROP Variables to drop. ;
  %put %str(      ) DEC Number of decimal places for numeric variables.
;
  %put %str(      ) WHERE subsetting where clause. ;
  %goto endmacro;
%end;
/* determine byte order */
data _null_;
     if put(input('1234'x,ib2.),hex4.)='1234' then endian='BIG   ';
else if put(input('1234'x,ib2.),hex4.)='3412' then endian='LITTLE';
else put "Can't determine byte order of this computer!!";
call symput('endian',endian);
run;
%if &endian= %then %goto endmacro;
proc contents data=&in
%if %nrbquote(&keep)^=  %then (keep=&keep) ;
%else %if %nrbquote(&drop)^=  %then (drop=&drop) ;
   out=_temp noprint;
proc sort; by varnum;
data _temp;
 set _temp end=eof;
if type=2 then vtype='C';
  else if index(format,'YY')>0 or index(format,'DATE')>0 then vtype='D';
  else vtype='N';
if vtype='D' then length=8;
if vtype='N' then length=12;
fdec=&dec;
if vtype='N' then do;
  if formatl^=0 then length=formatl;
  else if informl^=0 then length=informl;
%if &dec^=  %then %do;
  if formatd^=0 then fdec=formatd;
  else if informd^=0 then fdec=informd;
%end;
end;
flen=put(length,pib1.);
fd=put(fdec,ib1.);
if _n_=1 then do;
  fds=1;
  file "control.sas" ;
  put "DATA _NULL_;";
  put "  SET &in end=eof;";
%if %nrbquote(&where)^= %then
  put "WHERE &where ;";;
  put "FILE '&out' recfm=n lrecl=256 mod;";
  put "PUT ' ' ;  " ;
end;
length fmt $ 8;
if vtype='C' then fmt="$"||trim(left(put(length,8.)))||".";
else if vtype='N' then do;
  if fdec>0 then fmt=trim(left(put(length,8.)))||"."||put(fdec,1.);
  else fmt="12.4";
end;
else if vtype='D' then  fmt="$8.";
fds+length;
vcount+1;
if eof then do;
  vn=3;
  mdate=input(put(modate,datetime7.),date7.);
  day=day(mdate);
  month=month(mdate);
  year=year(mdate)-1900;
  %if &endian=BIG %then %do;
    nr=reverse(put(nobs,ib4.));
    hs=reverse(put((vcount+1)*32+1,ib2.));
    lr=reverse(put((fds),ib2.));
  %end;
  %else %do;
    nr=put(nobs,ib4.);
    hs=put((vcount+1)*32+1,ib2.);
    lr=put((fds),ib2.);
  %end;
  file "&out" recfm=n lrecl=256;
  put @1 vn ib1. year ib1. month ib1. day ib1. nr $4. hs $2. lr $2.  ;
  put '0000000000000000000000000000000000000000'x;
end;
run;
data _null_;
length name $ 11;
 set _temp end=eof;
file "control.sas" mod;
if vtype='D' then do;
  put 'length dvar $ 8.;';
  put '_year=year(' name ');';
  put '_month=month('name ');';
  put '_day=day(' name ');';
  put 'dvar=put(_year,z4.)||put(_month,z2.)||put(_day,z2.);';
  put 'put dvar ' fmt ';';
end;
else put 'put ' name fmt ';';
file "&out" recfm=n mod lrecl=256;
do i=1 to 11-length(name);
  name=trim(name)||'00'x;
end;
put name $11. vtype $1.  '00000000'x flen $1. fd $1.
    '0000000000000000000000000000'x ;
if eof then do;
  put '0d'x ;
  file "control.sas" mod;
  put "if eof then put '1a'x ;";
  put "run;";
end;
run;

%inc control;
%endmacro:
%mend sas2dbf;