SASSAS | The Leader in Business Intelligence -- Superior Software that gives you The Power to Know
  NewsEventsConsultingCareersContact UsResource Center
Home Products and Solutions Customer Success Partners Company Customer Support
Government & Education: Federal: SAS Macros
 
Government
Federal Government
State & Local Government
Data Integration
Business Intelligence
Analytics
 

SAS Macros that Convert a Directory of Transport Files

This is a set of SAS macros that converts a directory of transport files to a directory of SAS data sets and format catalogs (and vice versa). To see how to invoke the macros, look at the test following the last macro. The macros make the assumption that transport files created from data sets have the extension .xpt, and transport files created from format catalogs have the extension .xpf.


/*----------------------------------------------------------------*/
/* This macro will convert an existing format catalog into a      */
/* CNTLOUT= data set in transport format. The parameters are:     */
/*                                                                */
/* %expfmts(fmtlib,outfile);                                      */
/*                                                                */
/* where                                                          */
/*                                                                */
/* fmtlib                Name of format catalog. If only one      */
/*                       level is given, it is assumed that this  */
/*                       is a libref and the catalog name is      */
/*                       FORMATS.                                 */
/* outfile               Filename that will contain the transport */
/*                       file.                                    */
/*                                                                */
/* Note that the macro will first create a temporary CNTLOUT=     */
/* data set, then examine it for variables that are not necessary */
/* for the final transport file. This is done to reduce the size  */
/* of the transport file.                                         */
/*----------------------------------------------------------------*/

%macro expfmts(fmtlib,outfile);

*-----first create the CNTLOUT= data set from the catalog------------*;
proc format library=&fmtlib cntlout=work.temp;
run;

*-----determine variables not needed for the final transport file----*;
data _null_; set temp end=eof;
nend+(end^=start);                 * START/END must be different ;
nfuzz+(fuzz^=1e-12 and fuzz^=.);   * FUZZ must be non-default    ;
if type='P' then do;               * For PICTURE formats:        ;
     nprefix+(prefix^=' ');          *   nonblank prefix           ;
     nmult+(mult^=.);                *   multiplier specified      ;
     nfill+(fill^=' ');              *   nonblank fill             ;
     nnoedit+(noedit=1);             *   NOEDIT specified          ;
     end;
nsexcl+(sexcl='Y');                * start exclusion specified   ;
neexcl+(eexcl='Y');                * end exclusion specified     ;
nhlo+(hlo^=' ');                   * high/low/other etc. specd   ;
if eof;
length todrop $200;
*-----build a DROP= option for all pertinent variables----------*;
if ^nend     then todrop=trim(todrop)||' '||'END';
if ^nfuzz    then todrop=trim(todrop)||' '||'FUZZ';
if ^nprefix  then todrop=trim(todrop)||' '||'PREFIX';
if ^nmult    then todrop=trim(todrop)||' '||'MULT';
if ^nfill    then todrop=trim(todrop)||' '||'FILL';
if ^nnoedit  then todrop=trim(todrop)||' '||'NOEDIT';
if ^nsexcl   then todrop=trim(todrop)||' '||'SEXCL';
if ^neexcl   then todrop=trim(todrop)||' '||'EEXCL';
if ^nhlo     then todrop=trim(todrop)||' '||'HLO';
if todrop^=' '
then todrop='DROP='||todrop;

*-----emit the requested DROP= option---------------------------*;
call symput('dropopt',trim(todrop));
run;

*-----provide a LIBNAME statement for the specified file-------------*;
libname yyy xport "&outfile.";

*-----create the transport file, dropping appropriate variables------*;
data yyy.formats; set temp(&dropopt.);
     run;

*-----clear the libref now that the file is written------------------*;
libname yyy clear;

*-----ensure the temporary data set is deleted-----------------------*;
proc datasets dd=work; delete temp; quit;

%mend;

/*----------------------------------------------------------------*/
/* This macro will convert an existing SAS data set into a        */
/* transport file. The parameters are:                            */
/*                                                                */
/* %expdset(dataset,outfile);                                     */
/*                                                                */
/* where                                                          */
/*                                                                */
/* dataset               Name of SAS data set (one- or two-level) */
/* outfile               Filename that will contain the transport */
/*                       file.                                    */
/*----------------------------------------------------------------*/

%macro expdset(dataset,outfile);
libname yyy xport "&outfile.";
data _null_;
	  i=index("&dataset.",'.')+1;
	  memname=scan(substr("&dataset.",i),1,' .');
	  call execute('data yyy.'||memname||"; set &dataset.; run;");
	  run;
libname yyy clear;
%mend;

/*----------------------------------------------------------------*/
/* This macro will convert a transport CNTLOUT data set into      */
/* a native format catalog. The parameters are:                   */
/*                                                                */
/* %impfmts(xpffile);                                             */
/*                                                                */
/* where                                                          */
/*                                                                */
/* xpffile               Name of transport CNTLOUT data set       */
/*                                                                */
/* The macro will create the formats in LIBRARY.FORMATS. It       */
/* assumes that the libref LIBRARY has already been defined.      */
/*----------------------------------------------------------------*/

%macro impfmts(xpffile);
libname xxx xport "&xpffile.";
proc format library=library.formats cntlin=xxx.formats;
run;
libname xxx clear;
%mend;

/*----------------------------------------------------------------*/
/* This macro will convert a transport data set into a native SAS */
/* data set. The parameters are:                                  */
/*                                                                */
/* %impdset(xptfile);                                             */
/*                                                                */
/* where                                                          */
/*                                                                */
/* xptfile               Name of transport data set               */
/*                                                                */
/* The macro will create the native SAS data set in the directory */
/* defined by the libref LIBRARY, which it assumes has already    */
/* been defined.                                                  */
/*----------------------------------------------------------------*/

%macro impdset(xptfile);
libname xxx xport "&xptfile.";
proc copy in=xxx out=library;
run;
libname xxx clear;
run;
%mend;

/*----------------------------------------------------------------*/
/* This macro will create a SAS data set consisting of a variable */
/* called FILENAME. There will be one observation for each file   */
/* in the specified directory with the specified extension. The   */
/* parameters are:                                                */
/*                                                                */
/* %getnames(dataset,directry,extensn);                           */
/*                                                                */
/* where                                                          */
/*                                                                */
/* dataset               Name of SAS data set to create           */
/* directry              Directory to find files                  */
/* extensn               Specified extension to look for          */
/*                                                                */
/*----------------------------------------------------------------*/

%macro getnames(dataset,directry,extensn);
filename xxx pipe "&dircmd. &directry.&delim.*.&extensn.";
data &dataset.;
  infile xxx length=l;
  length filename $200;
  input @;
  input @1 filename $varying200. l;
  if index(filename,"&delim.")=0
	 then filename="&directry.&delim."||filename;
  keep filename;
  run;
filename xxx clear;
%mend;

/*----------------------------------------------------------------*/
/* This macro will determine the proper directory command and     */
/* delimiter. For UNIX, the command is ls -1, and the delimiter   */
/* is a forward slash. For PC, the command is dir/b, and the      */
/* delimiter is a backslash.                                      */
/*----------------------------------------------------------------*/

%macro dirdelim;
%global dircmd delim;
data _null_;
  *-----determine if we are on UNIX-----*;
  unix = "&sysscp" in ('RS6000  ', /* AIX */
			   'SUN 4   ', /* Solaris I and II */
			   'HP 800  ', /* HP-UX */
			   'DEVHOST ', /* SAS Institute Internal */
			   'ALXOSF  ', /* Digital UNIX */
			   '386 ABI ', /* Intel ABI */
			   'MIPS ABI'  /* MIPS ABI */
			  );

  *-----determine if we are on a PC-----*;
  PCX = "&sysscp" in ('OS2','WIN','WIN_NTSV');

  *-----if on UNIX, use ls -1 and forward slash delimiter-----*;
  if unix then do;
	 dircmd='ls -1';
	 delim='/';
	 end;

  *-----if on PC, use DIR/B and backslash delimiter-----*;
  else if pcx then do;
	 dircmd='DIR/B';
	 delim='\';
	 end;

  *-----otherwise not supported-----*;
  else do;
	 abort abend 999;
	 end;

  *-----save macro variables for command and delimiter-----*;
  call symput('dircmd',trim(dircmd));
  call symput('delim',delim);
  run;
%mend;

/*----------------------------------------------------------------*/
/* This macro will create native SAS data sets in the specified   */
/* directory, using transport files from another directory. The   */
/* transport files include those with .xpf extensions and .xpt    */
/* extensions. .xpf files are transport versions of CNTLOUT= data */
/* sets from PROC FORMAT. These will be read into PROC FORMAT via */
/* the CNTLIN= option. The .xpt files are regular transport data  */
/* sets that may refer to formats in the .xpf files. Therefore, we*/
/* use the LIBRARY libref and use LIBRARY.FORMATS as the format   */
/* catalog to ensure that the catalog is searched. (The FMTSEARCH=*/
/* option, by default, references LIBRARY.FORMATS as a catalog to */
/* search in). The parameters are:                                */
/*                                                                */
/* %fromexp(indir,outdir);                                        */
/*                                                                */
/* where                                                          */
/*                                                                */
/* indir                 directory containing transport files     */
/* outdir                directory to contain SAS data sets       */
/*----------------------------------------------------------------*/

%macro fromexp(indir,outdir);

%dirdelim;

*-----establish LIBRARY libref for output directory-----*;
libname library "&outdir.";

*-----obtain the names of the transport files for data sets-----*;
%getnames(xptfiles,&indir,xpt);

*-----obtain the names of the transport files for formats-----*;
%getnames(formats,&indir,xpf);

*-----invoke the %impfmts macro for each format transport file-----*;
data _null_; set formats;
  call execute('%impfmts('||trim(filename)||');');
  run;

*-----invoke the %impdset macro for each data set transport file---*;
data _null_; set xptfiles;
  call execute('%impdset('||trim(filename)||');');
  run;

*-----clear LIBRARY libref now that we are done-----*;
libname library clear;
%mend;

/*----------------------------------------------------------------*/
/* This macro will create transport files in the specified        */
/* directory, using native SAS data sets from another directory.  */
/* Regular SAS data sets will be converted to transport files     */
/* with the .xpt extension, and format catalogs will be converted */
/* to transport data set representations of their corresponding   */
/* CNTLOUT= data sets, using the .xpf extension.                  */
/*                                                                */
/* %fromexp(indir,outdir);                                        */
/*                                                                */
/* where                                                          */
/*                                                                */
/* indir                 directory containing SAS data sets       */
/*                         and format catalogs                    */
/* outdir                directory to contain transport files     */
/*----------------------------------------------------------------*/

%macro toexp(indir,outdir);

*-----use dictionary.members to get all member names---------------*;
libname library "&indir.";
proc sql;
create table names as
 select memname, memtype
 from   dictionary.members
 where  libname = 'LIBRARY';
quit;

%dirdelim;

*-----generate %expfmts or %expdset calls for proper members-------*;
data _null_; set names;
  if memtype='CATALOG' then do;
	 macro='%expfmts';
	 ext='xpf';
	 end;
  else do;
	 macro='%expdset';
	 ext='xpt';
	 end;
  call execute(macro||'(LIBRARY.'||trim(memname)||','||
	   "&outdir.&delim."||trim(memname)||'.'||ext||');');
  run;

*-----delete WORK.NAMES now that we are done-----------------------*;
proc datasets dd=work; delete names; quit;

*-----clear the libref now that we are done------------------------*;
libname library clear;
%mend;

*==================END OF MACRO SET================================*;

*--------------UNIX test of macros---------------------------------*;
options macrogen mlogic mprint;

*-----create fresh directories for testing-------------------------*;
x 'rm -Rf /tmp/fdatest 1> /dev/null 2> /dev/null';
x 'mkdir /tmp/fdatest 1> /dev/null 2> /dev/null';
x 'rm -Rf /tmp/fdatestx 1> /dev/null 2> /dev/null';
x 'mkdir /tmp/fdatestx 1> /dev/null 2> /dev/null';

*-----create format library and test data sets---------------------*;
libname library '/tmp/fdatest';
proc format library=library.formats;
  value abc 1='yes' 2='no';
  value $grade 'A'='great' 'B'='almost great' 'C'='average';
  run;
data library.temp1; x=1; y='A'; format x abc. y $grade.; run;
data library.temp2; x=2; y='B'; format x abc. y $grade.; run;
libname library clear;

*-----create transport files from the directory--------------------*;
%toexp(/tmp/fdatest,/tmp/fdatestx);
run;

*-----reset  original SAS data set directory-----------------------*;
x 'rm -Rf /tmp/fdatest 1> /dev/null 2> /dev/null';
x 'mkdir /tmp/fdatest 1> /dev/null 2> /dev/null';

*-----recreate original SAS data sets and format catalog-----------*;
%fromexp(/tmp/fdatestx,/tmp/fdatest);

*-----verify that all is restored properly-------------------------*;
libname library '/tmp/fdatest';
proc contents data=library._all_; run;
data _null_; set library.temp1; put _all_; run;
data _null_; set library.temp2; put _all_; run;
libname library clear;
	  	 	 

The Power to Know
   Contact Us      Worldwide Sites     Search     Site Map     RSS Feeds     Terms of Use    Privacy Statement   Copyright © SAS Institute Inc. All Rights Reserved