笔者在网上搜了很多文章,发现批量做这个修改的都是用的BDC录屏,虽然录屏很简单,但是既然要作为教程写在这里,我想还是BAPI或者RFC好一点,这部,刚好让笔者找到了.
具体功能:
上传一个excel文档,文档里是要创建或者修改的数据,点击执行则执行完毕了
上传的格式如下
也可以写成在选择屏幕上给个按钮,下载模板的形式,这里只为了演示,所以不做(甚至连ALV输出都没写)。
程序提供了正式运行和测试运行两种方式,在代码里用一个标识 ZMARK 来判断.
具体代码如下,仅供参考:
*&---------------------------------------------------------------------*
*& Report ZCYCLE11
*&---------------------------------------------------------------------*
*& 测试 ME_INFORECORD_MAINTAIN
*1.因为函数ME_INFORECORD_MAINTAIN不允许同时有净价和条件,所以需要分两次调用来实现创建/修改;
*2.因为函数ME_INFORECORD_MAINTAIN报错不明显,返回的报错信息仅当参考,因为需要自己debug去看具体的报错原因,
* 比如:如果单位错了,函数会报一个不相干的错误;
*3.用RFC ZALSM_EXCEL_TO_INTERNAL_TABLE 来获取上传的excel文件
*&---------------------------------------------------------------------*
REPORT zcycle11.
DATA : BEGIN OF it_tab OCCURS 0,
zkey2 TYPE n, "行项目号
zmark TYPE c, "是否测试标志 , X 标识测试
matnr LIKE eina-matnr, "物料编码
werks LIKE eine-werks, "工厂
lifnr LIKE eina-lifnr, "供应商
ekorg LIKE eine-ekorg, "采购组织
esokz LIKE eine-esokz, "采购信息记录分类
ekgrp LIKE eine-ekgrp, "采购组
waers LIKE eine-waers, "货币码
mwskz LIKE eine-mwskz, "税码
aplfz LIKE eine-aplfz, "计划交货时间(天)
netpr LIKE eine-netpr, "净价
bprme LIKE eine-bprme, "采购单位
peinh LIKE eine-peinh, "价格单位
datab LIKE konh-datab, "有效期起始日
datbi LIKE konh-datbi, "有效期截至日
umrez LIKE eina-umrez, "单位转换分子
umren LIKE eina-umren, "单位转换分母
END OF it_tab.
DATA : BEGIN OF et_tab OCCURS 0, "结果记录表
zresult TYPE c,
message TYPE char100,
zkey TYPE n,
infnr LIKE eine-infnr, "采购信息记录号
END OF et_tab.
DATA : st_tab LIKE TABLE OF et_tab.
DATA:lv_mode TYPE c. " I 为新增 , M 为修改
DATA:ls_eina TYPE eina,
ls_eine TYPE eine.
DATA:ls_mara TYPE mara.
*-----------BAPI数据定义--------------------------
DATA:i_eina TYPE mewieina,
i_einax TYPE mewieinax,
i_eine TYPE mewieine,
i_einex TYPE mewieinex.
DATA:lv_test TYPE bapiflag-bapiflag.
DATA:lt_return2 TYPE mewi_t_return,
ls_return2 LIKE LINE OF lt_return2.
DATA:lt_con_vali TYPE TABLE OF mewivalidity,
ls_con_vali TYPE mewivalidity.
DATA:lt_condition TYPE TABLE OF mewicondition,
ls_condition TYPE mewicondition.
DATA:e_eina TYPE mewieina,
e_eine TYPE mewieine.
"SALV 输出定义
DATA: i_table TYPE REF TO cl_salv_table.
DATA: lr_columns TYPE REF TO cl_salv_columns_table.
DATA: lr_functions TYPE REF TO cl_salv_functions.
"定义上载的EXCEL表
DATA:gs_upload TYPE alsmex_tabline,
gt_upload TYPE TABLE OF alsmex_tabline.
SELECTION-SCREEN : BEGIN OF BLOCK b WITH FRAME TITLE TEXT-001.
PARAMETERS : p1 TYPE string.
SELECTION-SCREEN : END OF BLOCK b.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p1.
PERFORM frm_fn."路径搜索帮助打开
START-OF-SELECTION.
PERFORM upload_data. "上传数据
PERFORM process_data. "处理上传的数据
PERFORM deal_data. "BAPI生成info record
PERFORM salv_show. "SALV输出
FORM deal_data.
LOOP AT it_tab.
CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
EXPORTING
input = it_tab-matnr
IMPORTING
output = it_tab-matnr
EXCEPTIONS
length_error = 1
OTHERS = 2.
"补齐供应商的前导零
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = it_tab-lifnr
IMPORTING
output = it_tab-lifnr.
SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_eina
FROM eina
WHERE matnr = it_tab-matnr
AND lifnr = it_tab-lifnr.
IF sy-subrc <> 0.
lv_mode = 'I'."新增
ELSE.
SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_eine
FROM eine
WHERE infnr = ls_eina-infnr
AND ekorg = it_tab-ekorg "采购组织
AND esokz = it_tab-esokz "采购信息记录分类
AND werks = it_tab-werks."工厂
IF sy-subrc = 0.
lv_mode = 'M'."修改
i_eina-info_rec = ls_eina-infnr."采购信息记录号
i_eine-info_rec = ls_eina-infnr."
i_einex-info_rec = 'X'.
* i_einax-vendor = 'X'.
* i_einax-material = 'X'.
ELSE.
lv_mode = 'I'."新增
ENDIF.
ENDIF.
i_eina-vendor = it_tab-lifnr."供应商
i_eina-material = it_tab-matnr."物料编码
i_einax-vendor = 'X'.
i_einax-material = 'X'.
"
i_eine-purch_org = it_tab-ekorg."采购组织
IF i_eine-purch_org IS NOT INITIAL.
i_einex-purch_org = 'X'.
ENDIF.
i_eine-info_type = it_tab-esokz."信息类别
IF i_eine-info_type IS NOT INITIAL.
i_einex-info_type = 'X'.
ENDIF.
i_eine-plant = it_tab-werks."工厂
IF i_eine-plant IS NOT INITIAL.
i_einex-plant = 'X'.
ENDIF.
i_eine-pur_group = it_tab-ekgrp."采购组
IF i_eine-pur_group IS NOT INITIAL.
i_einex-pur_group = 'X'.
ENDIF.
i_eine-currency = it_tab-waers."货币码
IF i_eine-currency IS NOT INITIAL.
i_einex-currency = 'X'.
ENDIF.
i_eine-tax_code = it_tab-mwskz."税码
IF i_eine-tax_code IS NOT INITIAL.
i_einex-tax_code = 'X'.
ENDIF.
i_eine-plnd_delry = it_tab-aplfz."计划交货时间(天)
IF i_eine-plnd_delry IS NOT INITIAL.
i_einex-plnd_delry = 'X'.
ENDIF.
i_eine-net_price = it_tab-netpr."净价
IF i_eine-net_price IS NOT INITIAL.
i_einex-net_price = 'X'.
ENDIF.
"对采购单位进行一次转换
CALL FUNCTION 'CONVERSION_EXIT_CUNIT_INPUT'
EXPORTING
input = it_tab-bprme
* LANGUAGE = SY-LANGU
IMPORTING
output = it_tab-bprme
EXCEPTIONS
unit_not_found = 1
OTHERS = 2.
"对单位进行校验
SELECT SINGLE * INTO ls_mara
FROM mara
WHERE matnr = it_tab-matnr.
IF sy-subrc = 0.
IF ls_mara-bstme IS NOT INITIAL.
IF ls_mara-bstme <> it_tab-bprme.
et_tab-zresult = 'E'.
et_tab-message = '采购单位与采购订单计量单位不一致'.
APPEND et_tab.
CLEAR et_tab.
CONTINUE.
ENDIF.
ELSE.
IF ls_mara-meins <> it_tab-bprme.
et_tab-zresult = 'E'.
et_tab-message = '采购单位与基本单位不一致'.
APPEND et_tab.
CLEAR et_tab.
CONTINUE.
ENDIF.
ENDIF.
ENDIF.
*** 因为上面已经要求单位要一致,所以这里分子分母要为空,如果没有要求单位一致,那么就一定要输出单位转换的分子分母
i_eine-conv_num1 = it_tab-umrez. "单位转换分子
IF i_eine-conv_num1 IS NOT INITIAL.
i_einex-conv_num1 = 'X'.
ENDIF.
i_eine-conv_den1 = it_tab-umren. "单位转换分母
IF i_eine-conv_den1 IS NOT INITIAL.
i_einex-conv_den1 = 'X'.
ENDIF.
i_eine-orderpr_un = it_tab-bprme."采购单位
IF i_eine-orderpr_un IS NOT INITIAL.
i_einex-orderpr_un = 'X'.
ENDIF.
i_eine-price_unit = it_tab-peinh."价格单位
IF i_eine-price_unit IS NOT INITIAL.
i_einex-price_unit = 'X'.
ENDIF.
"i_eine-nrm_po_qty = '1'."标准采购订单数量
"i_einex-nrm_po_qty = 'X'.
ls_con_vali-plant = it_tab-werks."工厂
ls_con_vali-valid_from = it_tab-datab."有效起始日
ls_con_vali-valid_to = it_tab-datbi."有效截止日
APPEND ls_con_vali TO lt_con_vali.
ls_condition-cond_type = 'PB00'."固定值
ls_condition-currency = it_tab-waers."货币码
ls_condition-cond_value = it_tab-netpr."净价
ls_condition-cond_p_unt = it_tab-peinh."条件定价单位
ls_condition-cond_unit = it_tab-bprme."条件单位
APPEND ls_condition TO lt_condition.
lv_test = it_tab-zmark."是否测试,如果为'X',则为测试
CLEAR:lt_return2.
IF lv_mode = 'I'. "新建
CALL FUNCTION 'ME_INFORECORD_MAINTAIN'
EXPORTING
i_eina = i_eina
* I_EINAX =
i_eine = i_eine
i_einex = i_einex
testrun = lv_test
IMPORTING
e_eina = e_eina
e_eine = e_eine
TABLES
* TXT_LINES =
* cond_validity = lt_con_vali
* condition = lt_condition
* COND_SCALE_VALUE =
* COND_SCALE_QUAN =
return = lt_return2.
READ TABLE lt_return2 INTO ls_return2 WITH KEY type = 'E'.
IF sy-subrc <> 0 AND lv_test = ''.
"创建时需要将数据写入到数据库里,不然报错
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'.
"因为净价和条件不能同时维护,所以分开维护
CLEAR:i_einex-net_price.
CLEAR:lt_return2.
i_eina-info_rec = e_eina-info_rec."采购信息记录号
i_eine-info_rec = e_eina-info_rec."采购信息记录号
i_einex-info_rec = 'X'.
CALL FUNCTION 'ME_INFORECORD_MAINTAIN'
EXPORTING
i_eina = i_eina
* I_EINAX =
i_eine = i_eine
i_einex = i_einex
testrun = lv_test
IMPORTING
e_eina = e_eina
e_eine = e_eine
TABLES
* TXT_LINES =
cond_validity = lt_con_vali "第二次运行增加有效期信息
condition = lt_condition "第二次运行增加条件信息
* COND_SCALE_VALUE =
* COND_SCALE_QUAN =
return = lt_return2.
ENDIF.
ELSE. "修改
"对数据进行修改
CALL FUNCTION 'ME_INFORECORD_MAINTAIN'
EXPORTING
i_eina = i_eina
i_einax = i_einax
i_eine = i_eine
i_einex = i_einex
testrun = lv_test
IMPORTING
e_eina = e_eina
e_eine = e_eine
TABLES
* TXT_LINES =
* cond_validity = lt_con_vali
* condition = lt_condition
* COND_SCALE_VALUE =
* COND_SCALE_QUAN =
return = lt_return2.
"理论上这里可以不用commit就能更改条件
CLEAR:i_einex-net_price."一定要清空这个变量,不然程序会报错
CALL FUNCTION 'ME_INFORECORD_MAINTAIN'
EXPORTING
i_eina = i_eina
* I_EINAX =
i_eine = i_eine
i_einex = i_einex
testrun = lv_test
IMPORTING
e_eina = e_eina
e_eine = e_eine
TABLES
* TXT_LINES =
cond_validity = lt_con_vali "第二次运行增加有效期信息
condition = lt_condition "第二次运行增加条件信息
* COND_SCALE_VALUE =
* COND_SCALE_QUAN =
return = lt_return2.
ENDIF.
IF lv_test IS INITIAL."正式运行
READ TABLE lt_return2 INTO ls_return2 WITH KEY type = 'E'.
IF sy-subrc = 0.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
et_tab-zresult = 'E'.
et_tab-message = '创建失败'.
APPEND et_tab.
CLEAR et_tab.
ELSE.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'.
et_tab-zkey = it_tab-zkey2."行项目号
et_tab-infnr = e_eina-info_rec."采购信息记录号
et_tab-zresult = 'S'.
et_tab-message = '创建成功'.
APPEND et_tab.
CLEAR et_tab.
ENDIF.
ELSE. "测试运行 lv_text = 'X'
READ TABLE lt_return2 INTO ls_return2 WITH KEY type = 'E'.
IF sy-subrc = 0.
LOOP AT lt_return2 INTO ls_return2.
IF sy-tabix = 1.
et_tab-message = ls_return2-message.
ELSE.
et_tab-message = et_tab-message && ';' && ls_return2-message.
ENDIF.
ENDLOOP.
et_tab-zresult = 'E'.
APPEND et_tab.
CLEAR et_tab.
ELSE.
et_tab-zresult = 'S'.
et_tab-message = '试运行成功'.
APPEND et_tab.
CLEAR:et_tab.
ENDIF.
ENDIF.
CLEAR:i_eina,i_einax,
i_eine,i_einex,
lt_con_vali,lt_condition,
ls_eina.
CLEAR:lt_return2.
ENDLOOP.
ENDFORM.
FORM salv_show.
st_tab[] = et_tab[].
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = i_table
CHANGING
t_table = st_tab ).
CATCH cx_salv_msg.
ENDTRY.
" 功能按钮
lr_functions = i_table->get_functions( ).
lr_functions->set_all( abap_true ).
" 列自适应
lr_columns = i_table->get_columns( ).
lr_columns->set_optimize( 'X').
"设置列名称
"lr_columns->get_column( 'CHRG2' )->set_long_text( '批次22' )."
" alv输出
i_table->display( ).
ENDFORM.
FORM frm_fn .
CALL FUNCTION 'WS_FILENAME_GET' "Get file name
EXPORTING
mask = ',*.* ,*.*.' "',*.xls,*.xlsx.'
mode = '0'
title = TEXT-h10
IMPORTING
filename = p1
EXCEPTIONS
inv_winsys = 1
no_batch = 2
selection_cancel = 3
selection_error = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE E016 WITH I_PATH.
ENDIF.
ENDFORM.
FORM upload_data.
DATA: lv_xls LIKE rlgrap-filename .
IF p1 IS INITIAL.
MESSAGE '导入文件地址不能为空!' TYPE 'E'.
STOP.
ENDIF.
CLEAR lv_xls.
lv_xls = p1.
"从第二行第一列开始读取
CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
EXPORTING
filename = lv_xls
i_begin_col = 1
i_begin_row = 2
i_end_col = 18 " 读取多少列
i_end_row = 9999 "读取多少行
TABLES
intern = gt_upload
EXCEPTIONS
inconsistent_parameters = 1
upload_ole = 2
OTHERS = 3.
IF sy-subrc NE 0 .
MESSAGE '从本地文件导入到SAP失败' TYPE 'E'.
ENDIF.
CLEAR gs_upload.
SORT gt_upload BY row col.
ENDFORM.
FORM process_data.
DATA : l_index TYPE i.
DATA : l_type TYPE c.
FIELD-SYMBOLS : <fs>.
LOOP AT gt_upload INTO gs_upload . "把上传的excel数据转换到内表 it_tab 中
MOVE gs_upload-col TO l_index.
ASSIGN COMPONENT l_index OF STRUCTURE it_tab TO <fs>.
DESCRIBE FIELD <fs> TYPE l_type. "获取cell里的数据类型
IF l_type = 'C'. "如果这个cell里的数据是 C 类型,则condense以下
<fs> = gs_upload-value.
CONDENSE <fs>.
ELSE.
<fs> = gs_upload-value.
ENDIF.
AT END OF row.
APPEND it_tab.
CLEAR it_tab.
ENDAT.
ENDLOOP.
ENDFORM.