*
;
/*-------------------------------------------------------------------*/
/* Program: DataDoc SAS */
/* Author: George A. Theall */
/* Project: n/a */
/* Purpose: Documents SAS datasets. */
/* Notes: This is a macro. Include this file in your program - */
/* "%include DataDoc.SAS /nosource2 ;" - and invoke */
/* the macro DataDoc(). */
/* Arguments to the macro are as follows: */
/* 1st - name of dataset to document; */
/* 2nd - name of format library; */
/* 3rd - sort order of output ('P' => position of */
/* variables in dataset). */
/* Set the linesize ("options ls=") to at least 121 or */
/* BAD THINGS may happen to your output! */
/* The macro is (I hope) platform-independent. It's been */
/* tested under SAS PC v6.04 and MVS SAS v6.07. */
/* The datasets WORK._DDOC* serve as scratch. */
/* The platform-independent character combination "?/" */
/* is used in place of the vertical bar for the */
/* concatenation operator. NB: There is apparently */
/* a bug in SAS PC v6.04 that affects resolution of */
/* "?/" combinations in IF ... THEN expressions; */
/* one solution is to use them within a DO block. */
/* Updated: 09-Oct-92, GAT */
/* - initial version. */
/*-------------------------------------------------------------------*/
/*------------------------------------------------------*/
/* Set DEBUG to a non-zero value to help squash bugs. */
/*------------------------------------------------------*/
%let Debug = 1 ;
/*-------------------------------------------------*/
/* DS holds the name of the dataset to document; */
/* FMTLIB names the library where formats are; */
/* ORDER specifies sort order ('P' for position */
/* in data vector; else alphabetically. */
/*-------------------------------------------------*/
%macro DataDoc(DS, FmtLib, Order) ;
%***************************************************** ;
%* Initialize various options and macro variables. * ;
%***************************************************** ;
options charcode ;
%if (%eval(&sysver > 6.04)) %then
%let mlogic = mlogic ;
%else
%let mlogic = mtrace ;
%* For tracing macro execution. ;
%if (&Debug) %then %do ;
options mprint symbolgen &mlogic ;
%end ;
%else %do ;
options nomprint nosymbolgen no&mlogic ;
%end ;
%* Default dataset and format library names. ;
%if (&DS = '') %then
%let DS = WORK._LAST_ ;
%if (&FmtLib = '') %then
%let FmtLib = WORK ;
%* Sort order for final report. ;
%if (&Order = 'P' or &Order = 'p') %then
%let SortVar = nPos ;
%else
%let SortVar = Name ;
%************************************** ;
%* Create dataset with format info. * ;
%************************************** ;
%let nFmtObs = 0 ;
proc format lib = &FmtLib cntlout = _DDOCF ;
data _DDOCF ;
set _DDOCF end=eof ;
if (eof) then call symput('nFmtObs', left(put(_n_, best.))) ;
if (Start = End) then
FmtRange = compress(Start) ;
else
FmtRange = compress(Start ?/?/ '-' ?/?/ End) ;
FmtLabel = Label ;
keep FmtName FmtRange FmtLabel ;
%if (&Debug) %then %do ;
proc print data = _DDOCF ;
%end ;
%*********************************************** ;
%* Use SAS to determine contents of dataset. * ;
%*********************************************** ;
proc contents data = &DS out = _DDOCD memtype = data noprint ;
data _DDOCN ;
set _DDOCD (keep = MemName) ;
by MemName ;
if (first.MemName) then
nVars = 0 ;
nVars + 1 ;
if (last.MemName) then
output ;
%if (&Debug) %then %do ;
proc print data = _DDOCD ;
proc print data = _DDOCN ;
%end ;
%************************************* ;
%* Merge contents and format info. * ;
%************************************* ;
data _DDOCD ;
length Informat Format $ 28
FmtLabel $ 16
FmtRange $ 12 ;
merge _DDOCD _DDOCN ;
by MemName ;
if (InformL > 0) then do ;
Informat = compress(Informat ?/?/
put(InFormL, best.) ?/?/ '.' ?/?/
put(InFormD, best.)) ;
end ;
FmtLabel = '' ;
FmtRange = '' ;
if (FormatL > 0) then do ;
Format = compress(Format ?/?/
put(FormatL, best.) ?/?/ '.' ?/?/
put(FormatD, best.)) ;
output ;
end ;
else if (Format = '') then do ;
output ;
end ;
else do indx = 1 to &nFmtObs ;
set _DDOCF point=indx ;
if (Format = FmtName) then output ;
end ;
keep LibName MemName MemLabel nObs nVars
Name Type Length Label nPos Informat Format FmtLabel FmtRange ;
proc sort data = _DDOCD ;
by MemName &SortVar ;
%if (&Debug) %then %do ;
proc print data = _DDOCD ;
%end ;
proc format ;
value VarFmt
1 = 'Num '
2 = 'Char' ;
data _null_ ;
set _DDOCD ;
by MemName &SortVar ;
array Cols (*) Col1 - Col8 (1 11 53 59 64 74 92 106) ;
file PRINT header=PutHdr ;
if (first.MemName and _n_ > 1) then put _page_ ;
if (first.&SortVar) then
put @Col1 Name $char8. @Col2 Label $40.
@Col3 Type VarFmt. @Col4 Length 3.
@Col5 Informat $8. @Col6 Format $16.
@Col7 FmtRange $12. @Col8 FmtLabel $16. ;
else
put @Col6 Format $16.
@Col7 FmtRange $12. @Col8 FmtLabel $16. ;
return ;
PutHdr:
/* New member. */
if (first.MemName) then do ;
put //
@Col2 'Library: ' +2 LibName
@Col6 'Variables: ' +2 +3 nVars comma5.
/
@Col2 'Member name: ' +2 MemName
@Col6 'Observations:' +2 nObs comma8.
/
@Col2 'Member label:' +2 MemLabel ;
end ;
put //
@Col1 8*'=' @Col2 40*'=' @Col3 4*'='
@Col4 3*'=' @Col5 8*'=' @Col6 16*'='
@Col7 12*'=' @Col8 16*'='
/
@Col1 'Variable' @Col2 'Label' @Col3 'Type'
@Col4 'Len' @Col5 'Informat' @Col6 'Format'
@Col7 'Format Range' @Col8 'Format Label'
/
@Col1 8*'=' @Col2 40*'=' @Col3 4*'='
@Col4 3*'=' @Col5 8*'=' @Col6 16*'='
@Col7 12*'=' @Col8 16*'=' ;
return ;
%mend DataDoc ;
*;