Graphical BOM Explosion
Graphical BOM Explosion
This coding shows how a BOM can be exploded in ABAP with FUBA CS_BOM_EXPL_MAT_V2 and be displayed in an ALV-Tree. Therefore the SAP-Samle code BCALV_TREE_02 was enhanced.
How to install:
You have to do following to run this report:
Create Report in SE80 and paste code
Create a structure „zbomexplode“ (see bottom of page)
Create Dynpro 0100 with a custom container „CCONTAINER1“
Create a GUI-Status „MAIN100“ with „BACK“, „EXIT“, „CANCEL“
Create a GUI-Title „MAINTITLE“
Activate and Run
OR
Copy report BCALV_TREE_02 into a Z-Report
Delete coding
Paste my coding
Create a structure „zbomexplode“ (see bottom of page)
Activate and Run
What you can „learn“ from this example:
How to use CS_BOM_EXPL_MAT_V2
How to work with the output of CS_BOM_EXPL_MAT_V2
How to use ALV-Tree
How to use Events of ALV-Tree
How to read a column double clicked by the user
REPORT z_mm_bom_explosion_column.
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
* Explosion of Multilevel-BOM and
* Graphical Display in ALV-Tree
*
* M. Fettinger 2012
* Original SAP-Example BCALV_TREE_02 was enhanced for this
* purpose
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
DATA: g_alv_tree TYPE REF TO cl_gui_alv_tree,
g_custom_container TYPE REF TO cl_gui_custom_container.
DATA: gt_outtab TYPE TABLE OF zbomexplode, "Output-Table
gt_fieldcatalog TYPE lvc_t_fcat,
ok_code LIKE sy-ucomm,
save_ok LIKE sy-ucomm.
DATA: gt_stb TYPE roij_stpox_t,
gt_matcat TYPE TABLE OF cscmat,
gs_topmat TYPE cstmat.
*###############################################################
* LOCAL CLASSES
*###############################################################
*§1. Define a (local) class for event handling
CLASS lcl_tree_event_receiver DEFINITION.
PUBLIC SECTION.
*§2. Define an event handler method for each event you want to react to.
METHODS:
handle_node_double_click
FOR EVENT node_double_click OF cl_gui_alv_tree
IMPORTING node_key sender,
* 'sender' is an implicit event parameter that is provided by
* ABAP Objects runtime system. It contains a reference to the
* object that fired the event. You may directly use it to
* call methods of this instance.
handle_item_double_click
FOR EVENT item_double_click OF cl_gui_alv_tree
IMPORTING fieldname
node_key.
ENDCLASS. "lcl_tree_event_receiver DEFINITION
******************************************************************
CLASS lcl_tree_event_receiver IMPLEMENTATION.
*§3. Implement your event handler methods.
METHOD handle_node_double_click.
DATA: lt_children TYPE lvc_t_nkey.
*first check if the node is a leaf, i.e. can not be expanded
CALL METHOD sender->get_children
EXPORTING
i_node_key = node_key
IMPORTING
et_children = lt_children.
IF NOT lt_children IS INITIAL.
CALL METHOD sender->expand_node
EXPORTING
i_node_key = node_key
i_level_count = 2.
ENDIF.
ENDMETHOD. "handle_node_double_click
METHOD handle_item_double_click.
DATA: outtab_line TYPE zbomexplode,
node_text TYPE lvc_value,
item_layout TYPE lvc_t_layi,
node_layout TYPE lvc_s_layn.
CALL METHOD g_alv_tree->get_outtab_line
EXPORTING
i_node_key = node_key
IMPORTING
e_outtab_line = outtab_line
e_node_text = node_text
et_item_layout = item_layout
es_node_layout = node_layout.
CASE fieldname.
WHEN '&Hierarchy'.
WHEN 'STLNR'.
SET PARAMETER ID 'MAT' FIELD outtab_line-idnrk.
SET PARAMETER ID 'WRK' FIELD outtab_line-werks.
SET PARAMETER ID 'CSV' FIELD outtab_line-stlan.
CALL TRANSACTION 'CS03' AND SKIP FIRST SCREEN.
WHEN 'IDNRK'.
SET PARAMETER ID 'MAT' FIELD outtab_line-idnrk.
SET PARAMETER ID 'MXX' FIELD 'K'. "Grunddaten
CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.
ENDCASE.
ENDMETHOD. "handle_ITEM_DOUBLE_CLICK
ENDCLASS. "lcl_tree_event_receiver IMPLEMENTATION
*##################################################################
PARAMETERS: pa_matnr TYPE matnr OBLIGATORY,
pa_werks TYPE werks_d OBLIGATORY,
pa_datum TYPE datuv DEFAULT sy-datlo OBLIGATORY,
pa_stlan TYPE stlan OBLIGATORY,
pa_stlal TYPE stlal DEFAULT '01'.
START-OF-SELECTION.
DATA: ret TYPE sy-subrc.
PERFORM get_bom_data CHANGING ret.
IF ret = 0.
CALL SCREEN 100.
ENDIF.
*&---------------------------------------------------------------------*
*& Module PBO OUTPUT
*&---------------------------------------------------------------------*
* process before output
*----------------------------------------------------------------------*
MODULE pbo OUTPUT.
SET PF-STATUS 'MAIN100'.
SET TITLEBAR 'MAINTITLE'.
IF g_alv_tree IS INITIAL.
PERFORM init_tree.
CALL METHOD cl_gui_cfw=>flush
EXCEPTIONS
cntl_system_error = 1
cntl_error = 2.
IF sy-subrc NE 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = 'Automation Queue failure'(801)
txt1 = 'Internal error:'(802)
txt2 = 'A method in the automation queue'(803)
txt3 = 'caused a failure.'(804).
ENDIF.
ENDIF.
ENDMODULE. " PBO OUTPUT
*&---------------------------------------------------------------------*
*& Module PAI INPUT
*&---------------------------------------------------------------------*
* process after input
*----------------------------------------------------------------------*
MODULE pai INPUT.
save_ok = ok_code.
CLEAR ok_code.
CASE save_ok.
WHEN 'BACK'.
PERFORM exit_program USING 'X'.
WHEN 'EXIT' OR 'CANC'.
PERFORM exit_program USING ''.
WHEN OTHERS.
* §5. Call dispatch to process toolbar functions
* Toolbar events are registered in constructur method of
* CL_ALV_TREE_BASE as application events. So the dispatch call
* is a must if you want to use the standard toolbar.
CALL METHOD cl_gui_cfw=>dispatch.
ENDCASE.
CALL METHOD cl_gui_cfw=>flush.
ENDMODULE. " PAI INPUT
*&---------------------------------------------------------------------*
*& Form init_tree
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM init_tree.
* create container for alv-tree
DATA: l_tree_container_name(30) TYPE c.
l_tree_container_name = 'CCONTAINER1'.
CREATE OBJECT g_custom_container
EXPORTING
container_name = l_tree_container_name
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
lifetime_dynpro_dynpro_link = 5.
IF sy-subrc <> 0.
MESSAGE x208(00) WITH 'ERROR'(100).
ENDIF.
* create tree control
CREATE OBJECT g_alv_tree
EXPORTING
parent = g_custom_container
node_selection_mode = cl_gui_column_tree=>node_sel_mode_single
item_selection = 'X'
no_html_header = 'X'
no_toolbar = ''
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
illegal_node_selection_mode = 5
failed = 6
illegal_column_name = 7.
IF sy-subrc <> 0.
MESSAGE x208(00) WITH 'ERROR'. "#EC NOTEXT
ENDIF.
DATA l_hierarchy_header TYPE treev_hhdr.
PERFORM build_hierarchy_header CHANGING l_hierarchy_header.
* Hide columns and sum up values initially using the fieldcatalog
PERFORM build_fieldcatalog.
* IMPORTANT: Table 'gt_outtab' must be empty. Do not change this table
* (even after this method call). You can change data of your table
* by calling methods of CL_GUI_ALV_TREE.
* Furthermore, the output table 'gt_outtab' must be global and can
* only be used for one ALV Tree Control.
CALL METHOD g_alv_tree->set_table_for_first_display
EXPORTING
is_hierarchy_header = l_hierarchy_header
CHANGING
it_fieldcatalog = gt_fieldcatalog
it_outtab = gt_outtab. "table must be empty !
PERFORM create_hierarchy.
PERFORM register_events.
CALL METHOD g_alv_tree->column_optimize
EXPORTING
* i_start_column =
* i_end_column =
i_include_heading = 'X'
EXCEPTIONS
start_column_not_found = 1
end_column_not_found = 2
OTHERS = 3.
* Send data to frontend.
CALL METHOD g_alv_tree->frontend_update.
ENDFORM. " init_tree
*&---------------------------------------------------------------------*
*& Form build_hierarchy_header
*&---------------------------------------------------------------------*
* build hierarchy-header-information
*----------------------------------------------------------------------*
* -->P_L_HIERARCHY_HEADER strucxture for hierarchy-header
*----------------------------------------------------------------------*
FORM build_hierarchy_header CHANGING
p_hierarchy_header TYPE treev_hhdr.
p_hierarchy_header-heading = 'Stücklistenauflösung'(300).
p_hierarchy_header-width = 35.
p_hierarchy_header-width_pix = ''.
ENDFORM. " build_hierarchy_header
*&---------------------------------------------------------------------*
*& Form exit_program
*&---------------------------------------------------------------------*
* free object and leave program
*----------------------------------------------------------------------*
FORM exit_program USING toselscr TYPE c.
IF toselscr = 'X'.
LEAVE TO SCREEN 0.
ELSE.
LEAVE PROGRAM.
ENDIF.
ENDFORM. "exit_program
*--------------------------------------------------------------------
FORM build_fieldcatalog.
DATA: ls_fieldcatalog TYPE lvc_s_fcat.
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'ZBOMEXPLODE'
CHANGING
ct_fieldcat = gt_fieldcatalog.
LOOP AT gt_fieldcatalog INTO ls_fieldcatalog.
CASE ls_fieldcatalog-fieldname.
WHEN 'MEINS'.
ls_fieldcatalog-outputlen = 10.
WHEN 'DUMPS'.
ls_fieldcatalog-outputlen = 10.
WHEN 'DATUV'.
ls_fieldcatalog-outputlen = 10.
WHEN 'DATUB'.
ls_fieldcatalog-outputlen = 10.
WHEN 'STLNR'.
ls_fieldcatalog-outputlen = 15.
WHEN 'WERKS'.
ls_fieldcatalog-outputlen = 10.
WHEN 'STLAN'.
ls_fieldcatalog-outputlen = 5.
WHEN 'STLAL'.
ls_fieldcatalog-outputlen = 5.
ENDCASE.
MODIFY gt_fieldcatalog FROM ls_fieldcatalog.
ENDLOOP.
ENDFORM. " build_fieldcatalog
*-----------------------------------------------------------------------
FORM register_events.
*§4. Event registration: tell ALV Tree which events shall be passed
* from frontend to backend.
DATA: lt_events TYPE cntl_simple_events,
l_event TYPE cntl_simple_event,
l_event_receiver TYPE REF TO lcl_tree_event_receiver.
*§4a. Frontend registration(i): get already registered tree events.
*................................................................
* The following four tree events registers ALV Tree in the constructor
* method itself.
* - cl_gui_column_tree=>eventid_expand_no_children
* (needed to load data to frontend when a user expands a node)
* - cl_gui_column_tree=>eventid_header_context_men_req
* (needed for header context menu)
* - cl_gui_column_tree=>eventid_header_click
* (allows selection of columns (only when item selection activated))
* - cl_gui_column_tree=>eventid_item_keypress
* (needed for F1-Help (only when item selection activated))
*
* Nevertheless you have to provide their IDs again if you register
* additional events with SET_REGISTERED_EVENTS (see below).
* To do so, call first method GET_REGISTERED_EVENTS (this way,
* all already registered events remain registered, even your own):
CALL METHOD g_alv_tree->get_registered_events
IMPORTING
events = lt_events.
* (If you do not these events will be deregistered!!!).
* You do not have to register events of the toolbar again.
*§4b. Frontend registration(ii): add additional event ids
l_event-eventid = cl_gui_column_tree=>eventid_node_double_click.
APPEND l_event TO lt_events.
l_event-eventid = cl_gui_column_tree=>eventid_item_double_click.
APPEND l_event TO lt_events.
*§4c. Frontend registration(iii):provide new event table to alv tree
CALL METHOD g_alv_tree->set_registered_events
EXPORTING
events = lt_events
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
illegal_event_combination = 3.
IF sy-subrc <> 0.
MESSAGE x208(00) WITH 'ERROR'. "#EC NOTEXT
ENDIF.
*--------------------
*§4d. Register events on backend (ABAP Objects event handling)
CREATE OBJECT l_event_receiver.
SET HANDLER l_event_receiver->handle_node_double_click FOR g_alv_tree.
SET HANDLER l_event_receiver->handle_item_double_click FOR g_alv_tree.
ENDFORM. " register_events
*&---------------------------------------------------------------------*
*& Form create_hierarchy
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM create_hierarchy.
DATA: ls_stb LIKE LINE OF gt_stb,
ls_line TYPE zbomexplode,
lv_txt TYPE lvc_value,
lv_key TYPE lvc_nkey.
* WEGXX = Node Number
* TTIDX = Index in Table (gt_matcat-index <--> gt_stb-ttidx)
* VWEGX = Parent Node Number (regarding to stufe)
"Add Root-Node
MOVE-CORRESPONDING gs_topmat TO ls_line.
ls_line-ojtxp = gs_topmat-maktx.
ls_line-idnrk = gs_topmat-matnr.
lv_txt = gs_topmat-matnr.
SHIFT lv_txt LEFT DELETING LEADING '0'.
CALL METHOD g_alv_tree->add_node
EXPORTING
i_relat_node_key = ''
i_relationship = cl_gui_column_tree=>relat_last_child
is_outtab_line = ls_line
i_node_text = lv_txt
IMPORTING
e_new_node_key = lv_key.
"Create Hierarchy Recursive - Add Child Nodes
CLEAR ls_stb.
ls_stb-stufe = 0. "Parent
ls_stb-wegxx = 0. "Parent
PERFORM add_line USING ls_stb lv_key.
ENDFORM. " create_hierarchy
*&---------------------------------------------------------------------*
*& Form add_line
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IS_STB text
* -->IV_KEY text
*----------------------------------------------------------------------*
FORM add_line USING is_stb TYPE stpox iv_key TYPE lvc_nkey.
DATA: ls_line TYPE stpox,
lv_next TYPE histu,
lv_key TYPE lvc_nkey,
lv_txt TYPE lvc_value,
ls_lin TYPE zbomexplode,
ls_matcat1 LIKE LINE OF gt_matcat,
ls_stb1 TYPE stpox.
lv_next = is_stb-stufe + 1.
LOOP AT gt_stb INTO ls_line WHERE stufe = lv_next
AND vwegx = is_stb-wegxx. "Parent
MOVE-CORRESPONDING ls_line TO ls_lin.
lv_txt = ls_line-idnrk.
"We want to display the BOM-Number (STLNR) of each Material (if it is itself also a BOM)
"Actually gt_stb STLNR shows the BOM of the parent of which the component is part of
READ TABLE gt_matcat INTO ls_matcat1 WITH KEY matnr = ls_line-idnrk.
IF sy-subrc = 0. "Material is also a BOM
READ TABLE gt_stb INTO ls_stb1 WITH KEY ttidx = ls_matcat1-index.
ls_lin-stlan = ls_stb1-stlan.
ls_lin-stlal = ls_stb1-stlal.
ls_lin-stlnr = ls_stb1-stlnr.
ELSE. "Material is no BOM - its the last level
CLEAR: ls_lin-stlan, ls_lin-stlal, ls_lin-stlnr.
ENDIF.
CALL METHOD g_alv_tree->add_node
EXPORTING
i_relat_node_key = iv_key
i_relationship = cl_gui_column_tree=>relat_last_child
is_outtab_line = ls_lin
i_node_text = lv_txt
IMPORTING
e_new_node_key = lv_key.
PERFORM add_line USING ls_line lv_key.
ENDLOOP.
ENDFORM. "add_line
*&---------------------------------------------------------------------*
*& Form get_bom_data
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IV_RET text
*----------------------------------------------------------------------*
FORM get_bom_data CHANGING iv_ret.
DATA: lv_mktls TYPE c VALUE 'X'.
CALL FUNCTION 'CS_BOM_EXPL_MAT_V2'
EXPORTING
capid = 'PP01' "App ID
datuv = pa_datum
mktls = 'X' "Materialkurztext
mehrs = 'X' "Multi-level
mtnrv = pa_matnr
stlal = pa_stlal
stlan = pa_stlan
werks = pa_werks
IMPORTING
topmat = gs_topmat
TABLES
stb = gt_stb
matcat = gt_matcat
EXCEPTIONS
alt_not_found = 1
call_invalid = 2
material_not_found = 3
missing_authorization = 4
no_bom_found = 5
no_plant_data = 6
no_suitable_bom_found = 7
OTHERS = 8.
iv_ret = sy-subrc.
IF sy-subrc <> 0.
MESSAGE 'Stückliste konnte nicht gelesen werden!'(805) TYPE 'I' DISPLAY LIKE 'E'.
ELSE.
FIELD-SYMBOLS: <stb> TYPE stpox,
<mat> TYPE cscmat.
LOOP AT gt_stb ASSIGNING <stb>.
SHIFT <stb>-idnrk LEFT DELETING LEADING '0'.
ENDLOOP.
LOOP AT gt_matcat ASSIGNING <mat>.
SHIFT <mat>-matnr LEFT DELETING LEADING '0'.
ENDLOOP.
ENDIF.
ENDFORM. "get_bom_data
Structure zbomexplode