|
Chapter Contents |
Previous |
Next |
| The BOM Procedure |
The example of the ABC Lamp Company product structure example from Fogarty, Blackstone, and Hoffmann (1991) illustrates the basic features of PROC BOM. The single-level bill of material data are depicted in Figure 1.1. These consist of a list of each part in the product structure, the components that are directly used in the part, and the quantity of each component needed to make one unit of that particular part. The data set also includes a short description and the unit of measure for each part. The SAS DATA step code to create and display the single-level BOM data set is as follows:
/* single-level BOM data */
data SlBOM0;
input Part $8.
Desc $24.
Unit $8.
Component $8.
QtyPer 8.0
;
datalines;
LA01 Lamp LA Each B100 1
S100 1
A100 1
B100 Base assembly Each 1100 1
1200 1
1300 1
1400 4
S100 Black shade Each .
A100 Socket assembly Each 1500 1
1600 1
1700 1
1100 Finished shaft Each 2100 26
1200 7-Diameter steel plate Each .
1300 Hub Each .
1400 1/4-20 Screw Each .
1500 Steel holder Each 1400 2
1600 One-way socket Each .
1700 Wiring assembly Each 2200 12
2300 1
2100 3/8 Steel tubing Inches .
2200 16-Gauge lamp cord Feet .
2300 Standard plug terminal Each .
;
/* Display the input data set */
proc print data=SlBOM0 noobs;
title 'ABC Lamp Company';
title3 'Single-Level Bill of Material';
run;
The following code invokes PROC BOM to produce the indented bill of material and the summarized bill of material. It also uses PROC NETDRAW to draw a family tree diagram for illustrating the multilevel product structure. For further details about PROC NETDRAW, refer to "The NETDRAW Procedure" chapter in the SAS/OR User's Guide: Project Management, Version 8.
/* Create the indented BOM and the summarized BOM */
proc bom data=SlBOM0 out=IndBOM0 summaryout=SumBOM0;
structure / part=Part
component=Component
quantity=QtyPer
id=(Desc Unit);
run;
/* Draw a tree diagram for illustrating the product structure */
/* Each record denotes a node in the tree */
data IndBOM0a(drop=Part_ID);
set IndBOM0;
Paren_ID=Part_ID;
run;
/* Extract the Parent - Part information */
data IndBOM0b;
set IndBOM0(keep=Paren_ID Part_ID);
run;
/* Prepare the data set for running NETDRAW */
data TreBOM0;
set IndBOM0a IndBOM0b;
run;
/* Specify graphics options */
goptions hpos=32 vpos=80 border;
pattern1 v=s c=blue;
title h=5 j=c 'Multilevel Bill of Material';
footnote h=2 j=l
'Node shows ID Number, Part Number, and Quantity Required';
/* Invoke PROC NETDRAW to display BOM tree */
proc netdraw data=TreBOM0( where=(Paren_ID NE .) );
actnet / act=Paren_ID succ=Part_ID id=(Paren_ID _Part_ QtyPer)
ctext=white font=swiss htext=3 carcs=black
ybetween=3 xbetween=8 centerid
tree pcompress rotatetext rotate
arrowhead=0 rectilinear nodefid nolabel;
run;
|
Figure 1.2 displays the tree structure of the ABC Lamp Company. Corresponding to this tree diagram is the list of indented bill of material for the company as in Figure 1.3. The following code displays the indented BOM:
/* Display the indented BOM data */
proc print data=IndBOM0 noobs;
var _Level_ _Part_ Part_ID Desc QtyPer Qty_Prod
Unit _Parent_ Paren_ID _Prod_;
title 'ABC Lamp Company';
title3 'Indented Bill of Material, Part LA01';
run;
|
Each record in the indented BOM data set is associated with a node in the tree structure, and the node or record is uniquely identified by a sequence number that is assigned to it by the procedure. The Part_ID variable denotes this sequence number of the node or record. The Part_ID information is needed in case some items are required at more than one place in the BOM. For example, the item `1400' (1/4-20 Screw) is required at `B100' (Base assembly) and `1500' (Steel holder). In this situation the part number is not sufficient to identify each node in the tree structure. Thus, the two different nodes are uniquely identified by the values `7' and `10' for the variable Part_ID.
The _Level_ variable denotes the level number of each node. The final product, `LA01', is at level 0, and the level numbers increase as you look down the tree. The Part, QtyPer, and ID variables (Desc and Unit) in the single-level BOM data set, SlBOM0, are also included in the indented BOM data set. Note that the name of the Part variable is changed to _Part_ in the indented BOM data set. There are two variables in the indented BOM data set identifying parent information: the _Parent_ variable denotes the part number for the parent item (next assembly) of the part identified by the _Part_ variable, while the Paren_ID variable specifies the sequence number for the parent node of the current node (record) identified by the Part_ID variable. For example, the indented BOM data set, as shown in Figure 1.3, reveals that the part `1400' has two parent items: part `1500' and part `B100'. Meanwhile, the parent node of node `7' is node `6', and the parent node of node `10' is node `9'.
Finally, the _Prod_ variable denotes the part number of the final product in the production structure. The Qty_Prod variable contains the required quantity of the item identified by the _Part_ variable in order to make one unit of the final product identified by the _Prod_ variable. Note that in this particular example, the values of the Qty_Prod variable are identical to the values of the QtyPer variable. This is because the values of the QtyPer variable for all parent items are 1.
Figure 1.2 and Figure 1.3 show that the Indented BOM data set lists all of the parts of the tree structure in depth-first order (Aho, Hopcroft, and Ullman 1983). Unlike the Single-level BOM data set, the Indented BOM data set provides the "part-parent" information rather than the "part-component" relationship. The part-component information can still be easily retrieved. For example, the following code creates a list of components that are directly used in the part `LA01':
/* Display the components that are directly used */
/* in item LA01 */
proc print data=IndBOM0(where=(_Parent_='LA01')
rename=(_Part_=Component))
noobs;
var Component Desc QtyPer Unit _Prod_;
title 'ABC Lamp Company';
title3 'Single-Level Bill of Material Retrieval, Part LA01';
run;
|
You can also create single-level where-used reports from the Indented BOM data set. For example, the single-level where-used data set Used0b, displayed in Figure 1.5, lists all parent items that directly use the part `1400'. The SAS code that creates the data set Used0b from the Indented BOM data set IndBOM0 is as follows:
/* Create the where-used data set */
data Used0a(keep=_Parent_ Paren_ID QtyPer Unit _Prod_);
set IndBOM0(where=(_Part_='1400'));
run;
/* Get the part description from the IndBOM0 data set */
proc sql;
create table Used0b as
select Used0a._Parent_, IndBOM0.Desc,
Used0a.QtyPer, Used0a.Unit, Used0a._Prod_
from Used0a left join IndBOM0
on Used0a.Paren_ID=IndBOM0.Part_ID;
quit;
/* Display the where-used data set */
proc print data=Used0b noobs;
var _Parent_ Desc QtyPer Unit _Prod_;
title 'ABC Lamp Company';
title3 'Single-Level Where-used Report, Part 1400';
run;
|
The following SAS code sorts and displays the Summarized BOM data set that is produced by the BOM procedure:
/* Sort and display the summarized BOM data */
proc sort data=SumBOM0;
by _Part_;
run;
proc print data=SumBOM0 noobs;
title 'ABC Lamp Company';
title3 'Summarized Bill of Material, Part LA01';
run;
|
The Summarized BOM data set, as displayed in Figure 1.6, lists all the parts and their quantity required in the given ABC Lamp Company product structure. Since the Single-level BOM data set, SlBOM0, does not contain any gross requirement information, PROC BOM assumes that the final product, `LA01', is the only master schedule item. The master schedule items (MSI) are items selected to be planned by the master scheduler. These items are deemed critical in their impact on lower-level components or resources. Therefore, the master scheduler, not the computer, maintains the plan for these items. The BOM procedure also assumes that the gross requirement of `LA01' is 1 unit and that there are no items currently on hand. The net requirement of the part `LA01' is the gross requirement (1) minus the quantity on hand (0). The gross requirements of the other items are then calculated sequentially, level by level, as follows:
| `B100' Base assembly (1 per lamp) | |
| Gross requirement | 1 ×1 = 1 |
| Quantity on hand | - 0 |
| Net requirement | 1 |
| `1100' Finished shaft (1 per base assembly) | |
| Gross requirement | 1 ×1 = 1 |
| Quantity on hand | - 0 |
| Net requirement | 1 |
| `2100' 3/8 Steel tubing (26 inches per shaft) | |
| Gross requirement | 1 ×26 = 26 |
| Quantity on hand | - 0 |
| Net requirement | 26 |
If a part (like item `1400') is required at more than one assembly, the gross requirement is the total needed in all assemblies where it is required.
The Net_Req variable denotes the net requirement, and the Low_Code variable denotes the low-level code of the part. The low-level code is a number that indicates the lowest level in any bill of material at which the item appears. The low-level codes are necessary to make sure that the net requirement for a given item is not calculated until all the gross requirements have been calculated down to that level.
|
Chapter Contents |
Previous |
Next |
Top |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.