BOM示例:
BOM层级 | ||||
---|---|---|---|---|
1 | A | |||
2 | 1 | 2 | 3 | |
3 | Q | W | ||
4 | R | T | ||
5 | Q |
BOM层级 | ||||
---|---|---|---|---|
1 | B | |||
2 | 4 | 5 | 6 | |
3 | U | Y | ||
4 | Q |
效果展示:
物料 | 上层组件1 | 上层组件2 | 上层组件3 | 上层组件4 |
---|---|---|---|---|
Q | 1 | A | ||
Q | R | W | 1 | A |
Q | U | 6 | B |
代码执行:
*&---------------------------------------------------------------------*
*& Report
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Responsibility
*&---------------------------------------------------------------------*
* Program Name: ZPPR003
* T-Code: ZPPR003
* Date written: 2023/11/15
* Author's name: Tony Tian
* Last update: 2023/11/15
* Program title: BOM物料反查报表
* Project Name:
* Version: v1.0
*&---------------------------------------------------------------------*
* Description: BOM物料反查报表
*&---------------------------------------------------------------------*
*
*&---------------------------------------------------------------------*
* Change History
*&---------------------------------------------------------------------*
* Date | Programmer | Corr. # | Description
* | | |
* | | |
*&---------------------------------------------------------------------*
REPORT zppr003.
TYPE-POOLS: slis.
TABLES:
mast,
stko.
*&---------------------------------------------------------------------*
* TYPES
*&---------------------------------------------------------------------*
TYPES:
BEGIN OF ty_list,
matnr TYPE matnr,
matnr1 TYPE matnr,
matnr2 TYPE matnr,
matnr3 TYPE matnr,
matnr4 TYPE matnr,
matnr5 TYPE matnr,
matnr6 TYPE matnr,
matnr7 TYPE matnr,
matnr8 TYPE matnr,
matnr9 TYPE matnr,
matnr10 TYPE matnr,
matnr11 TYPE matnr,
matnr12 TYPE matnr,
matnr13 TYPE matnr,
matnr14 TYPE matnr,
matnr15 TYPE matnr,
maktx TYPE maktx,
maktx1 TYPE maktx,
maktx2 TYPE maktx,
maktx3 TYPE maktx,
maktx4 TYPE maktx,
maktx5 TYPE maktx,
maktx6 TYPE maktx,
maktx7 TYPE maktx,
maktx8 TYPE maktx,
maktx9 TYPE maktx,
maktx10 TYPE maktx,
maktx11 TYPE maktx,
maktx12 TYPE maktx,
maktx13 TYPE maktx,
maktx14 TYPE maktx,
maktx15 TYPE maktx,
END OF ty_list.
*&---------------------------------------------------------------------*
* GLOBAL DATA
*&---------------------------------------------------------------------*
DATA: lv_fieldname TYPE char30,
lv_matnr TYPE matnr,
lv_count TYPE i,
lv_count2 TYPE i,
lv_null TYPE i,
lv_stop.
DATA:t1 TYPE timestampl, "开始时时戳
t2 TYPE timestampl, "结束时间戳
tc1 TYPE c LENGTH 22, "开始时间戳文本
tc2 TYPE c LENGTH 22, "结束时间戳文本
td1 TYPE d, "开始时间:日期
td2 TYPE d, "结束时间:日期
th1 TYPE i, "开始时间:时
th2 TYPE i, "结束时间:时
tm1 TYPE i, "开始时间:分
tm2 TYPE i, "结束时间:分
ts1 TYPE p DECIMALS 7, "开始时间:秒(含小数部分)
ts2 TYPE p DECIMALS 7, "结束时间:秒(含小数部分)
tmd TYPE p DECIMALS 4. "时间差异,取6位小数
*&---------------------------------------------------------------------*
* GLOBAL INTERNAL TABLES
*&---------------------------------------------------------------------*
DATA: gt_list1 TYPE TABLE OF ty_list,
gt_list2 TYPE TABLE OF ty_list,
equicat TYPE TABLE OF cscequi,
kndcat TYPE TABLE OF cscknd,
matcat TYPE TABLE OF cscmat,
stdcat TYPE TABLE OF cscstd,
tplcat TYPE TABLE OF csctpl,
wultb TYPE TABLE OF stpov.
DATA: dy_table TYPE REF TO data,
gs_line TYPE REF TO data.
FIELD-SYMBOLS: <dyn_alv> TYPE STANDARD TABLE,
<dyn_wa>,
<dyn_field>.
DATA: gt_fieldcat TYPE lvc_t_fcat,
gs_fieldcat TYPE lvc_s_fcat.
DATA: gs_layout TYPE lvc_s_layo.
*&---------------------------------------------------------------------*
* SELECTION-SCREEN
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK bk1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_werks TYPE mast-werks OBLIGATORY DEFAULT '2011'.
SELECT-OPTIONS: s_matnr FOR mast-matnr OBLIGATORY.
PARAMETERS: p_datuv TYPE stko-datuv DEFAULT sy-datum OBLIGATORY.
PARAMETERS:r_sig TYPE char01 RADIOBUTTON GROUP g1,
r_mut TYPE char01 RADIOBUTTON GROUP g1 DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK bk1.
*&---------------------------------------------------------------------*
*
* MAIN PROGRAM
*
*----------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM time_calculate USING 'INIT'.
PERFORM get_data.
PERFORM set_fieldcat.
PERFORM set_layout.
PERFORM create_table.
PERFORM display_alv.
*&---------------------------------------------------------------------*
*& Form GET_DATA
*&---------------------------------------------------------------------*
FORM get_data .
SELECT matnr INTO TABLE gt_list1 FROM mara WHERE matnr IN s_matnr.
SORT gt_list1 BY matnr.
DELETE ADJACENT DUPLICATES FROM gt_list1 COMPARING matnr.
WHILE lv_stop = abap_false.
PERFORM time_calculate USING 'CACL'.
lv_count = lv_count + 1. "用来动态填充 MATNR(1~15)
IF r_sig = abap_true AND lv_count = 2.
EXIT.
ENDIF.
PERFORM single_layer_up_search.
CLEAR gt_list1.
MOVE-CORRESPONDING gt_list2 TO gt_list1.
CLEAR gt_list2.
ENDWHILE.
PERFORM get_other_data.
ENDFORM. " GET_DATA
*&---------------------------------------------------------------------*
*& Form single_layer_up_search
*&---------------------------------------------------------------------*
FORM single_layer_up_search .
LOOP AT gt_list1 ASSIGNING FIELD-SYMBOL(<lfs>).
CLEAR: lv_matnr,lv_count2,lv_fieldname,matcat.
*--> 获取上一个 MATNR
IF lv_count = 1.
lv_matnr = <lfs>-matnr.
ELSE.
lv_count2 = lv_count - 1.
lv_fieldname = 'MATNR' && lv_count2.
CONDENSE lv_fieldname NO-GAPS.
ASSIGN COMPONENT lv_fieldname OF STRUCTURE <lfs> TO <dyn_field>.
IF sy-subrc EQ 0.
lv_matnr = <dyn_field>.
ENDIF.
ENDIF.
*--> 根据上一个 MATNR,进行向上展BOM
CALL FUNCTION 'CS_WHERE_USED_MAT'
EXPORTING
datub = p_datuv
datuv = p_datuv
matnr = lv_matnr
werks = p_werks
TABLES
wultb = wultb
equicat = equicat
kndcat = kndcat
matcat = matcat
stdcat = stdcat
tplcat = tplcat
EXCEPTIONS
call_invalid = 1
material_not_found = 2
no_where_used_rec_found = 3
no_where_used_rec_selected = 4
no_where_used_rec_valid = 5
OTHERS = 6.
*--> 如果向上展BOM失败,即停止循环
IF matcat IS INITIAL.
APPEND <lfs> TO gt_list2.
lv_null = lv_null + 1.
CONTINUE.
ENDIF.
*--> 如果向上展BOM成功,将结果填入下一个 MATNR
LOOP AT matcat ASSIGNING FIELD-SYMBOL(<matcat>).
CLEAR:lv_fieldname.
lv_fieldname = 'MATNR' && lv_count.
CONDENSE lv_fieldname NO-GAPS.
ASSIGN COMPONENT lv_fieldname OF STRUCTURE <lfs> TO <dyn_field>.
IF sy-subrc EQ 0.
<dyn_field> = <matcat>-matnr.
ENDIF.
APPEND <lfs> TO gt_list2.
ENDLOOP.
ENDLOOP.
*--> 判断所有行是否向上展失败,失败停止全局循环,成功继续下一个循环
DATA(lv_line) = lines( gt_list2 ).
IF lv_line = lv_null.
lv_stop = abap_true.
EXIT.
ENDIF.
CLEAR: gt_list1,lv_null.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form get_other_data
*&---------------------------------------------------------------------*
FORM get_other_data .
DATA: lv_value(20),
lv_filed1(70),
lv_filed2(70),
lv_where(100),
lv_count TYPE i.
DEFINE %%select_maktx.
SELECT SINGLE maktx INTO (&1) FROM makt WHERE (&2).
END-OF-DEFINITION.
LOOP AT gt_list1 ASSIGNING FIELD-SYMBOL(<lfs>).
CLEAR lv_count.
DO 16 TIMES.
IF sy-index = '1'.
lv_value = '<lfs>-maktx'.
lv_filed2 = 'maktx'.
lv_where = 'matnr = <lfs>-matnr AND spras = ''1'''.
ELSE.
lv_count = lv_count + 1.
lv_value = '<lfs>-maktx' && lv_count.
lv_filed1 = '<lfs>-matnr' && lv_count.
lv_filed2 = 'maktx' && lv_count.
CONCATENATE 'matnr' '=' lv_filed1 'AND' 'spras' '=' '1' INTO lv_where SEPARATED BY ' '.
ENDIF.
%%select_maktx: lv_value lv_where.
ASSIGN COMPONENT lv_filed2 OF STRUCTURE <lfs> TO <dyn_field>.
IF sy-subrc EQ 0.
<dyn_field> = lv_value.
ENDIF.
CLEAR: lv_value,lv_where,lv_filed1,lv_filed2.
ENDDO.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form set_fieldcat
*&---------------------------------------------------------------------*
FORM set_fieldcat .
DATA: lv_index TYPE i.
PERFORM get_max_column CHANGING lv_index.
REFRESH gt_fieldcat.
DEFINE init_fill_fcat.
CLEAR gs_fieldcat.
gs_fieldcat-fieldname = &1.
gs_fieldcat-coltext = &2.
gs_fieldcat-scrtext_l = &2.
gs_fieldcat-scrtext_m = &2.
gs_fieldcat-scrtext_s = &2.
gs_fieldcat-reptext = &2.
gs_fieldcat-ref_table = &3.
gs_fieldcat-ref_field = &4.
gs_fieldcat-f4availabl = &5.
gs_fieldcat-icon = &6.
gs_fieldcat-edit = &7.
gs_fieldcat-no_zero = &8.
gs_fieldcat-inttype = &9.
APPEND gs_fieldcat TO gt_fieldcat.
END-OF-DEFINITION.
DATA:lv_fieldname1 TYPE char30.
DATA:lv_fieldname2 TYPE char30.
init_fill_fcat 'MATNR' '物料' 'MARA' 'MATNR' '' '' '' 'X' ''.
init_fill_fcat 'MAKTX' '物料描述' 'MAKT' 'MAKTX' '' '' '' 'X' ''.
"循环最多行项目的行数
DO lv_index TIMES.
CLEAR:lv_fieldname.
lv_fieldname1 = 'MATNR' && sy-index.
lv_fieldname2 = '上层组件' && sy-index.
init_fill_fcat lv_fieldname1 lv_fieldname2 'MARA' 'MATNR' '' '' '' 'X' ''.
CLEAR:lv_fieldname.
lv_fieldname1 = 'MAKTX' && sy-index.
lv_fieldname2 = '上层组件' && sy-index && '描述'.
init_fill_fcat lv_fieldname1 lv_fieldname2 'MAKT' 'MAKTX' '' '' '' 'X' ''.
ENDDO.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form set_layout
*&---------------------------------------------------------------------*
FORM set_layout .
CLEAR gs_layout.
gs_layout-sel_mode = 'A'. "选择行模式
gs_layout-cwidth_opt = 'A'. "优化列宽设置
gs_layout-zebra = 'X'. "设置斑马线
ENDFORM.
*&---------------------------------------------------------------------*
*& Form create_table
*&---------------------------------------------------------------------*
FORM create_table .
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = gt_fieldcat
IMPORTING
ep_table = dy_table.
ASSIGN dy_table->* TO <dyn_alv>. " 用表类型指针 <dyn_table> 指向 数据对象的内容.
CREATE DATA gs_line LIKE LINE OF <dyn_alv>. " 建立一个与动态内表结构相同的数据对象,且数据对象为是一个结构
ASSIGN gs_line->* TO <dyn_wa>. " 用<dyn_wa>指针指向该结构
MOVE-CORRESPONDING gt_list1 TO <dyn_alv>.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form display_alv
*&---------------------------------------------------------------------*
FORM display_alv .
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = sy-repid
is_layout_lvc = gs_layout
* i_callback_pf_status_set = 'FRM_SET_STATUS'
* i_callback_user_command = 'FRM_USER_COMMAND'
it_fieldcat_lvc = gt_fieldcat
i_save = 'A'
TABLES
t_outtab = <dyn_alv>
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form get_max_column
*&---------------------------------------------------------------------*
FORM get_max_column CHANGING lv_index TYPE i.
DATA: lv_filed(7),
lv_filed_count TYPE i,
lv_where(250).
DATA: lt_list TYPE TABLE OF ty_list.
DEFINE %%select_max.
SELECT (&1) FROM @gt_list1 AS t WHERE (&2) INTO TABLE @lt_list.
END-OF-DEFINITION.
WHILE lt_list IS INITIAL.
lv_filed_count = lv_filed_count + 1.
lv_filed = 'MATNR' && lv_filed_count.
CONDENSE lv_filed.
CONCATENATE lv_filed 'IS' 'NOT' 'INITIAL' INTO lv_where SEPARATED BY ' '.
%%select_max: lv_filed lv_where.
IF lt_list IS INITIAL.
EXIT.
ENDIF.
lv_index = lv_index + 1.
CLEAR lt_list.
ENDWHILE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form time_calculate
*&---------------------------------------------------------------------*
FORM time_calculate USING p_value.
CASE p_value.
WHEN 'INIT'.
GET TIME STAMP FIELD t1.
tc1 = t1.
td1 = tc1+0(8).
th1 = tc1+8(2).
tm1 = tc1+10(2).
ts1 = tc1+12(10).
WHEN 'CACL'.
GET TIME STAMP FIELD t2.
tc2 = t2.
td2 = tc2+0(8).
th2 = tc2+8(2).
tm2 = tc2+10(2).
ts2 = tc2+12(10).
tmd = ( td2 - td1 ) * 24 * 3600 + ( th2 - th1 ) * 3600 + ( tm2 - tm1 ) * 60 + ( ts2 - ts1 ).
IF tmd > '1800'.
MESSAGE '报表运行时间超过30分钟,程序自动停止!请减少料号输入量!' TYPE 'E'.
ENDIF.
ENDCASE.
ENDFORM.