前言
用戶需要批量地使用 CK91N 創建 備選採購,然後通過 CK94 來設定混合比率,因此需要開發一個 批導模板。但是在網絡上查找相關的BAPI均未果,BDC的録屏也有些問題,問題無法解決,苦惱數日,今日完成,特來記録一下。
表 CKMLMV001 存儲 CK91N 中的記録
表 CKMLMV003 存儲 CK94 中的記録
方案說明
1、通過BDC録屏的方式來執行 CK91N 部分
2、關於 CK94 部分,録屏時要輸入 ① 處的三個字段,選中 ② 這一列,或者點擊 ③ 處,通過 ④ 來篩選出唯一一條待修改的數據(因為可能有會有很多條數據,而對於不同的用戶,其前臺顯示的行數可能不同,因此通過 ‘評估類型’來將需要更改的行定位到第一行),如果BDC可以實現 選中-篩選,那BDC無疑是比較容易的解決方案,但實際情況很不幸,無論是 ② 還是 ③,都無法選中。
因此選擇使用BAPI的方式來完成 CK94,但是在實際操作中,BAPI 只能處理修改(CKMLMV003 已經存在 該物料的數據時),爾不能處理 CKMLMV003 還沒有存入數據的情況。
我的解決方案是,先使用BDC輸入第一行的數據,保存。然後使用BAPI來更改。
代碼
CK91N 的BDC録屏
DATA: lv_msg TYPE string.
DATA: lv_succ TYPE string VALUE '备选采购执行成功'.
DATA: ls_01 TYPE ckmlmv001.
UNASSIGN <fs_data>.
LOOP AT gt_data ASSIGNING <fs_data> WHERE icon = icon_led_green AND msg IS INITIAL AND zbox = 'X'.
CLEAR:gt_bdcdata.
IF <fs_data>-ck91n_flag = 'X'.
<fs_data>-icon = icon_led_green.
<fs_data>-msg = '数据已执行过备选采购'.
CONTINUE.
ENDIF.
SELECT SINGLE *
INTO @DATA(l_matnr_n)
FROM ckmlmv001
WHERE matnr = @<fs_data>-matnr
AND werks = @<fs_data>-werks.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-BWTAR'.
PERFORM bdc_field USING 'BDC_OKCODE' '/00'.
PERFORM bdc_field USING 'CKMLMV_SURF-MATNR' <fs_data>-matnr.
PERFORM bdc_field USING 'CKMLMV_SURF-WERKS' <fs_data>-werks.
PERFORM bdc_field USING 'CKMLMV_SURF-BWTAR' <fs_data>-bwtar.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-MATNR'.
PERFORM bdc_field USING 'BDC_OKCODE' '/00'.
PERFORM bdc_field USING 'CKMLMV_SURF-MATNR' <fs_data>-matnr.
PERFORM bdc_field USING 'CKMLMV_SURF-WERKS' <fs_data>-werks.
PERFORM bdc_field USING 'CKMLMV_SURF-BWTAR' <fs_data>-bwtar.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-MATNR'.
PERFORM bdc_field USING 'BDC_OKCODE' '/00'.
PERFORM bdc_field USING 'CKMLMV_SURF-MATNR' <fs_data>-matnr.
PERFORM bdc_field USING 'CKMLMV_SURF-WERKS' <fs_data>-werks.
PERFORM bdc_field USING 'CKMLMV_SURF-BWTAR' <fs_data>-bwtar.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-MATNR'.
PERFORM bdc_field USING 'BDC_OKCODE' '=CREATE'.
PERFORM bdc_field USING 'CKMLMV_SURF-MATNR' <fs_data>-matnr.
PERFORM bdc_field USING 'CKMLMV_SURF-WERKS' <fs_data>-werks.
PERFORM bdc_field USING 'CKMLMV_SURF-BWTAR' <fs_data>-bwtar.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_OKCODE' '=BTYP'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMVTOOL_540-BTYP'.
PERFORM bdc_field USING 'CKMLMVTOOL_540-BTYP' <fs_data>-btyp.
IF l_matnr_n IS INITIAL.
PERFORM bdc_dynpro USING 'SAPLSPO5' '0110'.
PERFORM bdc_field USING 'BDC_OKCODE' '=OK'.
PERFORM bdc_field USING 'BDC_CURSOR' 'SPOPLI-SELFLAG(02)'.
ENDIF.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_OKCODE' '=ENTZ'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMVTOOL_540-VERID_ND'.
PERFORM bdc_field USING 'CKMLMVTOOL_540-VERID_ND' <fs_data>-verid_nd.
PERFORM bdc_field USING 'CKMLMVTOOL_540-LOSGR_PC' <fs_data>-losgr_pc.
"新加
* PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
* PERFORM bdc_field USING 'BDC_OKCODE' '=ENTE'.
* PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMVTOOL_540-VERID_ND'.
IF l_matnr_n IS NOT INITIAL.
PERFORM bdc_dynpro USING 'SAPLSPO1' '0100'.
PERFORM bdc_field USING 'BDC_OKCODE' '=YES'.
ENDIF.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-MATNR'.
PERFORM bdc_field USING 'BDC_OKCODE' '=SAVE'.
PERFORM bdc_field USING 'CKMLMV_SURF-MATNR' <fs_data>-matnr.
PERFORM bdc_field USING 'CKMLMV_SURF-WERKS' <fs_data>-werks.
PERFORM bdc_field USING 'CKMLMV_SURF-BWTAR' <fs_data>-bwtar.
PERFORM bdc_field USING 'CKMLMVTOOL_530-LOSGR_PC' <fs_data>-losgr_pc.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-MATNR'.
PERFORM bdc_field USING 'BDC_OKCODE' '=SAVE'.
PERFORM bdc_field USING 'CKMLMV_SURF-MATNR' <fs_data>-matnr.
PERFORM bdc_field USING 'CKMLMV_SURF-WERKS' <fs_data>-werks.
PERFORM bdc_field USING 'CKMLMV_SURF-BWTAR' <fs_data>-bwtar.
PERFORM bdc_field USING 'CKMLMVTOOL_530-LOSGR_PC' <fs_data>-losgr_pc.
IF l_matnr_n IS NOT INITIAL.
PERFORM bdc_dynpro USING 'SAPLSPO1' '0100'.
PERFORM bdc_field USING 'BDC_OKCODE' '=YES'.
ENDIF.
PERFORM bdc_dynpro USING 'SAPLCKMLMVSURF' '0100'.
PERFORM bdc_field USING 'BDC_OKCODE' '/EBACK'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKMLMV_SURF-MATNR'.
CLEAR: gt_msgtab.
CALL TRANSACTION 'CK91N' USING gt_bdcdata
MODE p_mode
MESSAGES INTO gt_msgtab
UPDATE 'S'.
CLEAR: ls_01.
SELECT SINGLE *
FROM ckmlmv001
INTO ls_01
WHERE matnr = <fs_data>-matnr
AND werks = <fs_data>-werks
AND bwtar = <fs_data>-bwtar.
IF sy-subrc = 0.
<fs_data>-msg = lv_succ.
<fs_data>-ck91n_flag = 'X'.
ELSE.
<fs_data>-msg = '备选采购执行失败:' && <fs_data>-msg.
<fs_data>-msg = shift_right( val = <fs_data>-msg sub = ':').
<fs_data>-icon = icon_led_red.
ENDIF.
ENDLOOP.
CK94
CASE r_ucomm.
WHEN 'CK94'.
"說明,gt_data 的結構為 matnr 、werks 、bwtar,同一批執行的數據 是相同的matnr和相同的werks,bwtar(评估类型) 來區分不同的數據
LOOP AT gt_data ASSIGNING <fs_data> WHERE icon = icon_led_green AND zbox = 'X'.
AT NEW werks.
"執行 BDC 只為將數據保存值表 CKMLMV003 中
SELECT SINGLE * FROM ckmlmv003 INTO @DATA(ls_ckml03) WHERE matnr = @<fs_data>-matnr AND werks = @<fs_data>-werks.
IF sy-subrc <> 0.
READ TABLE gt_head INTO gs_head WITH KEY matnr = <fs_data>-matnr werks = <fs_data>-werks BINARY SEARCH.
IF sy-subrc = 0 AND ls_ckml03 IS INITIAL.
PERFORM frm_bdc_ck94 USING gs_head. "先通過BDC在CK94中保存數據
ENDIF.
ENDIF.
ENDAT.
IF <fs_data>-ck91n_flag = ''.
<fs_data>-msg = '备选采购未执行,请先执行该步骤'.
<fs_data>-icon = icon_led_red.
CONTINUE.
ENDIF.
APPEND <fs_data> TO gt_item.
AT END OF werks.
PERFORM frm_bapi_ck94 USING <fs_data>.
CLEAR: gt_item.
ENDAT.
ENDLOOP.
ENDCASE.
####### CK94 的 BDC
FORM frm_bdc_ck94 USING ps_data TYPE ty_data.
CLEAR: gt_bdcdata.
"CK94 初始屏幕
PERFORM bdc_dynpro USING 'SAPLCKBASCR1' '0200'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKI94A-MATNR'.
PERFORM bdc_field USING 'BDC_OKCODE' '=ENTR'.
PERFORM bdc_field USING 'CKI94A-MATNR' ps_data-matnr .
PERFORM bdc_field USING 'CKI94A-WERKS' ps_data-werks .
PERFORM bdc_field USING 'CKI94A-MGTYP' 'Z9000' .
"第一次进入时,有弹框
PERFORM bdc_dynpro USING 'SAPLSPO2' '0300'.
PERFORM bdc_field USING 'BDC_OKCODE' '=OPT1'.
"输入相关数据
PERFORM bdc_dynpro USING 'SAPLCKBASCR1' '0202'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKI94B-MISCH_VERH(01)'.
PERFORM bdc_field USING 'BDC_OKCODE' '=ENTR'.
PERFORM bdc_field USING 'CKI94B-ALDAT_PC(01)' ps_data-aldat_pc."成本核算数量结构日期
PERFORM bdc_field USING 'CKI94B-MIXCOST_PC(01)' ps_data-mixcost_pc."是否混合相关比率
PERFORM bdc_field USING 'CKI94B-MISCH_VERH(01)' ps_data-misch_verh. "混合比例
"保存
PERFORM bdc_dynpro USING 'SAPLCKBASCR1' '0202'.
PERFORM bdc_field USING 'BDC_CURSOR' 'CKI94B-MISCH_VERH(01)'.
PERFORM bdc_field USING 'BDC_OKCODE' '=STOR'.
CLEAR: gt_msgtab.
CALL TRANSACTION 'CK94' USING gt_bdcdata
MODE p_mode
MESSAGES INTO gt_msgtab
UPDATE 'S'.
ENDFORM.
####### CK94 的 BAPI
FORM frm_bapi_ck94 USING ps_data TYPE ty_data. .
DATA: ls_03 TYPE ckmlmv003.
"CK94 相關結構及變量
TYPES:
* Tabelle für Materialbewertunsgarten mit Mischungsverhältnisse
BEGIN OF ckmv1_mat_cratio_str,
kalnr_mb LIKE ckmlmv001-kalnr, "Material (MBEW-Ebene)
kalnr_mk LIKE ckmlmv001-kalnr, "Material (BwKreis-Ebene)
bwkey LIKE ckmlmv001-bwkey, "BewertKreis(Kalnr_Mb)
matnr LIKE ckmlmv001-matnr, "Material(Kalnr_Mb)
bwtar LIKE ckmlmv001-bwtar, "Bewqertungsart(Kalnr_Mb)
misch_verh LIKE ckmlmv003-misch_verh, "Mischungsverhältnis
END OF ckmv1_mat_cratio_str,
BEGIN OF ckmv1_alt_cratio_str,
kalnr_pr LIKE ckmlmv001-kalnr, "Prozeß
kalnr_ba LIKE ckmlmv001-kalnr, "Alternative
kalnr_mb LIKE ckmlmv001-kalnr, "Material (MBEW-Ebene)
werks LIKE ckmlmv001-werks, "Werk (Alternative)
bwkey LIKE ckmlmv001-bwkey, "BewertKreis(Kalnr_Mb)
matnr LIKE ckmlmv001-matnr, "Material(Kalnr_Mb)
bwtar LIKE ckmlmv001-bwtar, "Bewqertungsart(Kalnr_Mb)
btyp LIKE ckmlmv001-btyp, "Beschaffungstyp
misch_verh LIKE ckmlmv003-misch_verh, "Mischungsverh
* Zusatzdaten für die Mischkalkulation
mixcost_pc TYPE ck_mixcost. "Kz:Relevant f.Mischkal
INCLUDE TYPE ckmv1_mix001_data. "Aus Stammsatz
INCLUDE TYPE ckmv1_mix003_data. "Aus Mischverhältnis
TYPES:
* Namen/Bezeichnungen der Beschaffungsalternative
name TYPE ckmv1_ename, "Editierter Name (Altern)
balt_name_str TYPE ckmv1_name_str, "Merkmale (Alternative)
END OF ckmv1_alt_cratio_str.
DATA:li_mmratio_tbl TYPE STANDARD TABLE OF ckmv1_mat_cratio_str,
li_amratio_tbl TYPE STANDARD TABLE OF ckmv1_alt_cratio_str,
ls_amratio TYPE ckmv1_alt_cratio_str,
ls_cki94c TYPE cki94c,
ls_cki94a TYPE cki94a.
DATA: e_percent TYPE ckmlmv003-misch_verh,
rc LIKE sy-subrc,
i_percent TYPE ckmlmv003-misch_verh.
CLEAR: ls_cki94a.
ls_cki94a-matnr = ps_data-matnr.
ls_cki94a-werks = ps_data-werks.
ls_cki94a-mgtyp = 'Z9000'. "数量结构类型
CALL FUNCTION 'CKBA_MIXRATIO_PREPARE_VALUES'
IMPORTING
e_cki94c = ls_cki94c
e_mmratio_tbl = li_mmratio_tbl
e_amratio_tbl = li_amratio_tbl
CHANGING
c_cki94a = ls_cki94a.
READ TABLE li_amratio_tbl INTO ls_amratio INDEX 1.
IF sy-subrc EQ 0.
CALL FUNCTION 'CKBA_MIXRATIO_CHECK'
EXPORTING
i_percent_check = space
i_mixratio = li_amratio_tbl[]
IMPORTING
e_returncode = rc
e_percent = e_percent.
IF rc EQ 0.
LOOP AT li_amratio_tbl ASSIGNING FIELD-SYMBOL(<fs_amratio>).
READ TABLE gt_item INTO gs_item WITH KEY bwtar = <fs_amratio>-bwtar .
IF sy-subrc = 0.
<fs_amratio>-aldat_pc = gs_item-aldat_pc. "数量结构日期
<fs_amratio>-mixcost_pc = gs_item-mixcost_pc. "是否混合相关比率
<fs_amratio>-misch_verh = gs_item-misch_verh. "混合比率
ENDIF.
ENDLOOP.
CALL FUNCTION 'CKML_MGV_CROSS_RATIO_UPDATE'
EXPORTING
iv_mgtyp = ls_cki94a-mgtyp
iv_gjahr = '0000'
iv_perio = '000'
it_alt_cratio = li_amratio_tbl[].
ENDIF.
ENDIF.
*2.Update Mixing ratio
*for updatign mixing ratio, we can use the below function module.
DATA: lw_bdatj TYPE cki94a-bdatj, "Posting date YYYY
lw_mgtyp TYPE cki94a-mgtyp VALUE 'Z9000', "Quantity Structure Type
lt_mixratio TYPE ckmv1_alt_cratio_tbl.
CONSTANTS: c_per_000 TYPE ckmlmv003-perio VALUE '000'. ":Period 000
MOVE-CORRESPONDING li_amratio_tbl TO lt_mixratio.
* Update Mix Ratio
CALL FUNCTION 'MIXRATIO_MAINTAIN'
EXPORTING
i_mgtyp = lw_mgtyp
i_fyear = lw_bdatj
i_perio = c_per_000
i_mixratio_procalt = lt_mixratio[]
EXCEPTIONS
mixratio_already_exist = 1
db_error = 2
mgtyp_error = 3
no_mixratio = 4
percent_error = 5
OTHERS = 6.
IF sy-subrc EQ 0.
COMMIT WORK.
ENDIF.
LOOP AT gt_item INTO gs_item ."LOOP gt_item 是因為 gt_item 存儲的是同物料號下能執行的被選中的數據
CLEAR: ls_03.
READ TABLE gt_data ASSIGNING <fs_data1> WITH KEY matnr = gs_item-matnr werks = gs_item-werks bwtar = gs_item-bwtar.
IF sy-subrc = 0.
SELECT SINGLE * FROM ckmlmv003 INTO ls_03
WHERE matnr = <fs_data1>-matnr
AND werks = <fs_data1>-werks
AND aldat_pc = <fs_data1>-aldat_pc
AND misch_verh = <fs_data1>-misch_verh
.
ENDIF.
IF ls_03 IS NOT INITIAL.
<fs_data1>-msg = <fs_data1>-msg && ';估算比率执行成功'.
<fs_data1>-icon = icon_led_green.
ELSE.
<fs_data1>-msg = <fs_data1>-msg && ';估算比率执行失败'.
<fs_data1>-icon = icon_led_red.
ENDIF.
<fs_data1>-msg = shift_left( val = <fs_data1>-msg sub = ';').
ENDLOOP.
ENDFORM.
注意
使用 BDC 録屏時,輸入的數值型的字段要轉換為 Char 型,否則會有警告:長度不一致,致使BDC 被迫結束
TYPES: BEGIN OF ty_data,
matnr TYPE ckmlmv001-matnr , " 物料
werks TYPE ckmlmv001-werks , " 工厂
bwtar TYPE ckmlmv001-bwtar , " 评估类型
btyp TYPE ckmlmv001-btyp , " 处理类型
verid_nd TYPE ckmlmv001-verid_nd , " 生产版本
losgr_pc(17) TYPE c , " 成本核算批量
aldat_pc(8) TYPE c , " 数量结构日期
mixcost_pc TYPE c , " 是否混合相关比率
misch_verh(17) TYPE c , " 混合比率
"以上Excel模板字段
icon(4) TYPE c,
zbox,
msg(100) TYPE c,
ck91n_flag,
END OF ty_data.