Download hierarch.sas hierarch.sasSubmit a comment

%macro hierarch (ds, vars);

  %* Copyright 1998-2000, Richard A. DeVenezia
  %*
  %* For a given dataset and list of hierarchal variables
  %* make a data view which can be used with AF legacy class
  %* Organizational Chart;
  %*
  %* Arguments:
  %* ds   - source data set name
  %* vars - class variables that define a hierarchy
  %*
  %* Warning:
  %* No error checking is performed to ensure the variables
  %* listed in 'vars' are actually columns in data set 'ds';
  %*
  %* 05/13/98 Initial coding ;
  %* 06/30/00 Comments by Benjamin Guralnik and RAD;

  %local ds vars i N h varlist;

  %* establish the value of macro variable 'varlist' as a
  %* comma delimited list of the hierarchy variables
  %* to be used later a SELECT DISTINCT clause;

  %let i = 1;
  %do %while (%scan(&vars,&i) ne);
    %if &i gt 1
      %then %let varlist = &varlist,%scan(&vars,&i);
      %else %let varlist = %scan(&vars,&i);
    %let i = %eval (&i+1);
  %end;

  %* N is the number of class variables in the hierarchy;

  %let N = %eval (&i-1);

  %* create a view to the source data that contains
  %* the class level values and the number of occurences;

  proc sql;
     create view h as
     select *, count(*) as N from
     (select distinct &varlist from &ds);
  quit;

  %* open the source dataset and get the format of each class variable;
  %* store the class variable format in the indexed macro variable 'vf';

  %let h = %sysfunc(open(&ds));
  %if &h %then %do;
    %do i = 1 %to &N;
      %local vf&i;
      %let vf&i=%sysfunc(varfmt(&h,%sysfunc(varnum(&h,%scan(&vars,&i)))));
    %end;
    %let h = %sysfunc(close(&h));
  %end;

  %* Traverse the view of class level values outputting parent/child relationships;

  data h2 / view = h2;
    set h;
    by &vars notsorted;  %* use notsorted just in case the SQL view 'h' is unsorted;

    length node_val $25;

    format _n_ n 4.; drop n;

	%* every 2% of levels update a display of progress;
    window status rows=6 columns=20
    #1 @4 _n_ ' of ' n;
    if 0 = mod (_n_ , 1+int(n/50)) then display status noinput;

    %* create the "documentElement" node in XML terms (BG);

    if _n_ = 1 then do;
      node_pop = .;
      node_id = 0;
      node_val = 'Drill Down';
      output;
    end;

	%* _Ni are temporary data set variables used to maintain the
	%* value of the parent node ids that must be traversed to reach the current leaf;

    retain _N1-_N&N;
      drop _N1-_N&N;

    %do i = 1 %to &N;
      if first.%scan(&vars,&i) then do;

	    %* a class level value has changed, update the parent node id;

        %if &i=1 %then
          node_pop = 0;
        %else
          node_pop = _N%eval(&i-1);
        ;

		%* the value to show in a node is the class level value;
		%* use the formatted value if the column is formatted;

        %if (&&vf&i=) %then
          node_val =     %scan(&vars,&i);
        %else
          node_val = put(%scan(&vars,&i),&&vf&i);
        ;

		%* Each row in the output data set represents a node,
		%* hence increment node_id, the value that uniquely identifies each node;

		node_id + 1;

		%* make sure the current level node id is updated for this first. condition;
        %* it will be retained for all its children;

        _N&i = node_id;
        output;
      end;
    %end;
  run;
%mend;

Sample code

/* This was an e-mail I sent to Benjamin on how to get started using this
 * macro along with the Organization Chart class;

 * submit these statements;
 data snapshot;
   set sashelp.vcatalg;
   where libname = 'SASHELP'
     and memtype = 'CATALOG'
     and memname in ('FSP','CLASSES');
   ;
 run;

 %include 'hierarch.sas';
 %hierarch (snapshot, libname memname objname);

* now build a sample frame with these commands:
* BUILD WORK.TEST.HIERARCH.FRAME
* make a organizational chart object
* for dataset enter WORK.H2 (created by hierarch macro)

* click on Mapping list
* for parent_node use variable node_pop
* for current_node use variable node_id
* for node variable select TEXT
* for data set variable select NODE_VAL
* click on the Add button under Mapping List
* click OK

* click on Chart appearance
* uncheck Show all levels
* check Use +,- and dotted lines
* click OK

* click on Node appearance
* click on Select action
* check Hide/unhide children
* click OK
* click OK

* In Chart Style radio group, pick Directory
* In Node Spacing group, enter 4 for Vertical

* Now TESTAF to see the meta-data in an explorer like fashion

*/