Using the ANNOTATE= Option (gantte21)

/****************************************************************/
/*          S A S   S A M P L E   L I B R A R Y                 */
/*                                                              */
/*    NAME: GANTTE21                                            */
/*   TITLE: Using the ANNOTATE= Option (gantte21)               */
/* PRODUCT: OR                                                  */
/*  SYSTEM: ALL                                                 */
/*    KEYS: GANTT                                               */
/*   PROCS: CPM, SORT, GANTT                                    */
/*    DATA:                                                     */
/*                                                              */
/* SUPPORT:                             UPDATE:                 */
/*     REF: Example 21 in the GANTT Chapter (PM User's Guide)   */
/*    MISC: Using the ANNOTATE= Option to                       */
/*          a) Print Resource Requirements on a Gantt chart     */
/*          b) Plot Resource Usage and Resource Availability    */
/*               on a Gantt Chart                               */
/*                                                              */
/****************************************************************/

 /* Activity-on-Arc representation of the project */
data widgres;
   input task $ 1-12 days tail head engineer;
   if engineer ^= . then engcost = engineer * 200;
   datalines;
Approve Plan   5   1   2  2
Drawings      10   2   3  1
Study Market   5   2   4  1
Write Specs    5   2   3  2
Prototype     15   3   5  4
Mkt. Strat.   10   4   6  .
Materials     10   5   7  .
Facility      10   5   7  2
Init. Prod.   10   7   8  4
Evaluate      10   8   9  1
Test Market   15   6   9  .
Changes        5   9  10  2
Production     0  10  11  4
Marketing      0   6  12  .
Dummy          0   8   6  .
;

data widgrin;
   input per date7. otype $ 11-18 engineer engcost;
   format per date7.;
   datalines;
.         restype  1  2
.         suplevel 1  .
01dec03   reslevel 3  40000
26dec03   reslevel 4  .
;

data holdata;
   format hol date7.;
   input hol date7. name $ 10-18;
   datalines;
25dec03  Christmas
01jan04  New Year
;

options ls=80;
proc cpm date='01dec03'd interval=weekday
         data=widgres holidata=holdata resin=widgrin
         out=widgsch2 resout=widgrou2;
   tailnode tail;
   duration days;
   headnode head;
   holiday hol;
   resource engineer engcost / period=per obstype=otype
                               rule=lst
                               delayanalysis;
   id task;
   run;

title2 'Resource Constrained Schedule: Rule = LST';
proc print data=widgsch2;
   run;

* set up required pattern statements;
pattern1 c=green v=s;  /* duration of a noncrit. activity  */
pattern2 c=green v=e;  /* slack time for a noncrit. act.   */
pattern3 c=red   v=s;  /* duration of a critical activity  */
pattern4 c=red   v=e;  /* slack time for a supercrit. act. */
pattern5 c=red   v=r2; /* duration of a supercrit. act.    */
pattern6 c=cyan  v=s;  /* actual duration of an activity   */
pattern7 c=black v=x1; /* break due to a holiday           */
pattern8 c=blue  v=s;  /* res. constrained dur of an act.  */

title c=black h=1.75 'Gantt Example 21';
title2 c=black h=1.25 'Displaying Resource Requirements';

* set background to white and text to black;
goptions ctext=black cback=white;

* set graphics options;
goptions vpos=50 hpos=100 htext=1.01;

* begin annotate process;

* compile annotate macros;
%annomac;

* create annotate data set for first chart;
data anno1;
   %dclanno;       /* set length and type for annotate variables */
   %system(2,2,4); /* define annotate reference system           */
   set widgsch2;
   length lab $20;
   length TEXT $ 37;
   Y1 = _n_;
   lab='    ';

   if _n_=1 then do;
      %label('01dec03'd,13,
             'Format: Engineers per day, Total cost',*,0,0,1.2,brush,6);
      end;

   if engineer ^= . then do;
      /* create a text label */
      lab = put(engineer, 1.) || " Engineer";
      if engineer > 1 then lab = trim(lab) || "s";
      if days > 0 then lab = trim(lab) || ", " ||
                                            put(engcost*days, dollar7.);

      /* position the text label */
      if y1 < 10 then do;
         x1 = max(l_finish, s_finish) + 2;
         %label(x1,y1,lab,black,0,0,1.0,brush, 6);
         end;
      else do;
         x1 = e_start - 2;
         %label(x1,y1,lab,black,0,0,1.0,brush, 4);
         end;
      end;
run;

* annotate the Gantt chart;
proc gantt graphics data=widgsch2 holidata=holdata annotate=anno1;
chart / pcompress holiday=(hol) interval=weekday increment=7
        ref='1dec03'd to '21mar04'd by week
        cref=blue lref=2
        dur=days cmile=black caxis=black;
id task;
run;

* calculate scaling factor for cost curve;
data _null_;
   set widgrou2 end=final;
   retain maxcost;
   if aengcost > maxcost then maxcost=aengcost;
   if final then call symput('cscale',14/maxcost);
   run;

* create annotate data set for second chart;
data anno2;
   %dclanno;       /* set length and type for annotate variables */
   %system(2,2,4); /* define annotate reference system           */
   set widgrou2;
   length lab $16;
   length TEXT $27;
   x1=_time_;
   y1=15-aengcost*symget('cscale');
   y2=15-rengineer;
   lab='    ';

   if _n_=1 then do;
      /* print labels */
      do i = 1 to 14 by 1;
         lab=put( (15-i) / symget('cscale'), dollar7.);
         %label('21mar04'd,i,lab,black,0,0,1.0,,4);
         end;
      do i = 0 to 4 by 1;
         lab=put(i,1. );
         %label('01dec03'd,15-i,lab,black,0,0,1.0,,6);
         end;
      %label('01dec03'd,10,
             'Resource Usage: Engineers',*,0,0,1.2,,6);
      %label('02jan04'd,4,
             'Resource Availability: Cost',*,0,0,1.2,,6);
      %move(x1,y1);
      %push;
      end;
   else do;
      /* draw cost availability curve */
      %pop;
      when='a';
      %draw(x1,y1,black,1,2);
      %push;
      /* draw engineer usage barchart */
      when='b';
      if y2 <= 14 then do;
         %bar(x1,15,x1+1,y2,blue,0,l1);
         end;
      end;
   run;

title c=black h=1.75 'Gantt Example 21';
title2 c=black h=1.25
       'Plotting Resource Usage and Resource Availability';

* annotate the Gantt chart;
proc gantt graphics data=widgsch2 holidata=holdata annotate=anno2;
chart / pcompress holiday=(hol) interval=weekday increment=7
        mindate='1dec03'd maxdate='21mar04'd
        ref='1dec03'd to '21mar04'd by week
        cref=blue lref=2
        dur=days cmile=black caxis=black;
id task;
run;