一、业务场景:批量修改工作中心能力(TCode:CR02)页签内的工厂日历,开始时间,休息时间等。由于涉及到PPDS的资源表更新问题,所以没有使用bapi,函数去进行更新,本次采用的是BDC的方式处理。
二、代码场景:优先使用函数CR_CAPACITY_UPDATE或者/ISDFPS/WCUPS_WC_CHANGE进行修改工作中心,但笔者发现有时会出现不能同时更新PPDS的资源表/SAPAPO/RES_HEAD的情况,所以使用BDC方式实现,并且顺便做一个比较方便的BDC程序,作为模板,以备后用和分享。
三、涉及TCode及实现的功能:
1.SHDB BDC程序生成
2.SMW0上传导入模板文件,很多ABAP开发者有个不好的习惯,做批导程序时,只提供一个导入模板,后续一旦文件遗失,那么用户很难再使用做好的批导程序,SMW0可以有效的解决问题。
3.CR02修改工作中心
4.ALV筛选屏幕添加按钮
四、实现过程:
1.SHDB录制BDC程序:进入TCode:SHDB,输入如下
正常填写要修改的数据,最后点保存,会跳转到如下界面。
这里只保留要批量修改的字段即可,确认字段后,点生成程序
下面这一部分是我们将要使用的BDC程序。这里的form:bdc_field和form:bdc_dynpro我们在程序里可以重新编写,更简单方便一点(这里只放个截图,改写的代码在后面)。
2.SMW0上传模板文件
包一般选Z开头的,点执行
点击新建,输入文件编号,描述,点选择模板文件,即可把文件模板上传到SAP中。这里要记录下对象名称ZPPDS009以便在程序中下载模板。
3.有了BDC的程序和模板文件以后,下面是程序代码:
*--------------------------------------------------------------------S↓*
"S4 LJ 数据定义 06.07.2021 13:16:33
TYPE-POOLS: truxs.
TABLES:sscrfields.
TYPES: BEGIN OF ty_datas,
werks(4) TYPE c, "工厂
arbpl(8) TYPE c, "工作中心
kalid(2) TYPE c, "工厂日历
begzt TYPE sy-uzeit, "开始时间
endzt TYPE sy-uzeit, "结束时间
pause TYPE sy-uzeit, "休息时间
END OF ty_datas.
DATA:BEGIN OF gt_ex_data OCCURS 0,
werks(4) TYPE c, "工厂
arbpl(8) TYPE c, "工作中心
kalid(2) TYPE c, "工厂日历
begzt(10) TYPE c, "开始时间
endzt(10) TYPE c, "结束时间
pause(10) TYPE c, "休息时间
END OF gt_ex_data.
DATA: gt_data TYPE TABLE OF ty_datas WITH HEADER LINE,
wa_data TYPE ty_datas.
DATA: gv_repid TYPE sy-repid,
gv_tcode TYPE sy-tcode,
gv_user TYPE sy-uname.
DATA: gt_bdcdata TYPE TABLE OF bdcdata WITH HEADER LINE.
DATA: msg(200) TYPE c."消息输出
DATA: e_time TYPE kapbegzt."时间转换
*--------------------------------------------------------------------E↑*
*--------------------------------------------------------------------S↓*
"S4 LJ 选择屏幕 06.07.2021 10:10:55
PARAMETERS : p_file TYPE rlgrap-filename.
SELECTION-SCREEN: FUNCTION KEY 1, "按钮:下载模板
FUNCTION KEY 2.
INITIALIZATION.
sscrfields-functxt_01 = '@49@ 下载模板'.
*sscrfields-functxt_02 = '@54@ 备用按钮'.
AT SELECTION-SCREEN.
CASE sscrfields-ucomm. "响应下载按钮命令
WHEN'FC01'.
PERFORM frm_downlaod_temp USING 'ZPPDS009'.
*WHEN 'FC02'.
ENDCASE.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
PERFORM frm_get_filename.
*--------------------------------------------------------------------E↑*
START-OF-SELECTION.
PERFORM frm_get_data.
PERFORM frm_check_data.
END-OF-SELECTION.
* " 调用BDC方法
PERFORM frm_exec_transaction.
**------------------------------------------FROM------------------------------------------**
* 获取导入文件路径
FORM frm_get_filename .
DATA: lv_rc TYPE i.
DATA: lt_file_table TYPE filetable.
CALL FUNCTION 'KD_GET_FILENAME_ON_F4'
CHANGING
file_name = p_file
EXCEPTIONS
mask_too_long = 1
OTHERS = 2.
ENDFORM.
*获取excel数据
FORM frm_get_data .
DATA: lt_raw TYPE truxs_t_text_data.
CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP'
EXPORTING
i_line_header = 'X'
i_tab_raw_data = lt_raw
i_filename = p_file
TABLES
i_tab_converted_data = gt_ex_data
EXCEPTIONS
conversion_failed = 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:frm_check_data.
CLEAR:msg.
LOOP AT gt_ex_data.
* 所以字段必输
IF gt_ex_data-werks IS INITIAL OR gt_ex_data-arbpl IS INITIAL OR gt_ex_data-begzt IS INITIAL
OR gt_ex_data-endzt IS INITIAL OR gt_ex_data-kalid IS INITIAL OR gt_ex_data-pause IS INITIAL.
msg = '所有字段必输,请检查数据!'.
EXIT.
ENDIF.
gt_data-werks = gt_ex_data-werks.
SELECT SINGLE kapid,arbpl INTO @DATA(ds_kapid) FROM crhd WHERE arbpl = @gt_ex_data-arbpl.
IF sy-subrc NE 0.
msg = '工作中心' && gt_data-arbpl && '系统内不存在'.
EXIT.
ELSE.
gt_data-arbpl = ds_kapid-arbpl.
ENDIF.
SELECT SINGLE ident INTO @DATA(ds_ident) FROM tfacd WHERE ident = @gt_ex_data-kalid.
IF sy-subrc NE 0.
msg = '工作中心:' && gt_ex_data-arbpl && '的' && '工厂日历' && gt_data-kalid && '系统内不存在'.
EXIT.
ELSE.
gt_data-kalid = ds_ident.
ENDIF.
CALL FUNCTION 'CONVERT_TIME_INPUT'
EXPORTING
input = gt_ex_data-begzt
IMPORTING
output = gt_data-begzt
EXCEPTIONS
plausibility_check_failed = 1
wrong_format_in_input = 2
OTHERS = 3.
IF sy-subrc <> 0.
msg = '工作中心:' && gt_ex_data-arbpl && '的' && '开始时间' && gt_ex_data-begzt && '数据不合法'.
EXIT.
ENDIF.
CALL FUNCTION 'CONVERT_TIME_INPUT'
EXPORTING
input = gt_ex_data-endzt
IMPORTING
output = gt_data-endzt
EXCEPTIONS
plausibility_check_failed = 1
wrong_format_in_input = 2
OTHERS = 3.
IF sy-subrc <> 0.
msg = '工作中心:' && gt_ex_data-arbpl && '的' && '结束时间' && gt_ex_data-endzt && '数据不合法'.
EXIT.
ENDIF.
CALL FUNCTION 'CONVERT_TIME_INPUT'
EXPORTING
input = gt_ex_data-pause
IMPORTING
output = gt_data-pause
EXCEPTIONS
plausibility_check_failed = 1
wrong_format_in_input = 2
OTHERS = 3.
IF sy-subrc <> 0.
msg = '工作中心:' && gt_ex_data-arbpl && '的' && '休息时间' && gt_ex_data-pause && '数据不合法'.
EXIT.
ENDIF.
APPEND gt_data.
CLEAR:gt_data.
ENDLOOP.
IF msg IS NOT INITIAL.
MESSAGE msg TYPE 'E'.
ENDIF.
ENDFORM.
*事务shdb录制的程序
FORM frm_convert_data USING p_wa_data TYPE ty_datas.
* BDC_SUBSCR的项没有意义,可不填
CLEAR: gt_bdcdata,gt_bdcdata[].
PERFORM frm_screen_line USING 'SAPLCRA0' '0100'.
PERFORM frm_field_line USING 'BDC_CURSOR' 'RC68A-WERKS'.
PERFORM frm_field_line USING 'BDC_OKCODE' '=KAUE'.
PERFORM frm_field_line USING 'RC68A-WERKS' p_wa_data-werks.
PERFORM frm_field_line USING 'RC68A-ARBPL' p_wa_data-arbpl.
PERFORM frm_screen_line USING 'SAPLCRA0' '4000'.
PERFORM frm_field_line USING 'BDC_OKCODE' '=KAKO'.
PERFORM frm_field_line USING 'BDC_CURSOR' 'P3006-FORK1(01)'.
PERFORM frm_screen_line USING 'SAPLCRK0' '0101'.
PERFORM frm_field_line USING 'BDC_OKCODE' '=UPD'.
PERFORM frm_field_line USING 'BDC_CURSOR' 'RC68K-PAUSE'.
PERFORM frm_field_line USING 'RC68K-BEGZT' p_wa_data-begzt.
PERFORM frm_field_line USING 'RC68K-ENDZT' p_wa_data-endzt.
PERFORM frm_field_line USING 'RC68K-PAUSE' p_wa_data-pause.
PERFORM frm_field_line USING 'KAKO-KALID' p_wa_data-kalid.
ENDFORM.
*重新编写的BDC程序:BDC的屏幕号放入gt_bdcdata
FORM frm_screen_line USING VALUE(p_value1)
VALUE(p_value2).
CLEAR: gt_bdcdata.
gt_bdcdata-program = p_value1.
gt_bdcdata-dynpro = p_value2.
gt_bdcdata-dynbegin = 'X'.
APPEND gt_bdcdata.
ENDFORM.
*重新编写的BDC程序:BDC的数据行放入gt_bdcdata
FORM frm_field_line USING VALUE(p_value11)
VALUE(p_value12).
CLEAR: gt_bdcdata.
gt_bdcdata-fnam = p_value11.
gt_bdcdata-fval = p_value12.
APPEND gt_bdcdata.
ENDFORM.
* 用BDC循环处理导入数据
FORM frm_exec_transaction.
DATA: lt_message TYPE TABLE OF bdcmsgcoll WITH HEADER LINE.
DATA: lv_message TYPE string.
LOOP AT gt_data.
* 填写BDC数据
PERFORM frm_convert_data USING gt_data.
* 执行BDC
CALL TRANSACTION 'CR02' USING gt_bdcdata[]
MESSAGES INTO lt_message "返回消息
UPDATE 'S' "更新模式:S 同步 A 异步
MODE 'E'. "显示模式:A 前台 N 后台 E 仅显示错误
IF sy-subrc = 0.
WRITE:/ '工作中心:',gt_data-arbpl,'修改成功'.
ELSE.
LOOP AT lt_message WHERE msgtyp = 'E'.
WRITE:/ '工作中心:',gt_data-arbpl,'修改失败'.
CALL FUNCTION 'MESSAGE_TEXT_BUILD'
EXPORTING
msgid = lt_message-msgid
msgnr = lt_message-msgnr
msgv1 = lt_message-msgv1
msgv2 = lt_message-msgv2
msgv3 = lt_message-msgv3
msgv4 = lt_message-msgv4
IMPORTING
message_text_output = lv_message.
* 简单输出返回的消息
WRITE:/ lv_message.
ENDLOOP.
ENDIF.
ENDLOOP.
ENDFORM.
* 从SMW0下载模板,此form可以做成类,可以很方便的在其他批导程序中使用
FORM frm_downlaod_temp USING p_name TYPE wwwdata-objid.
DATA: lv_fielname TYPE string,
lv_path TYPE string,
lv_fullpath TYPE string,
lv_dest TYPE rlgrap-filename.
DATA: lv_objid TYPE wwwdata-objid.
DATA: lo_objdata TYPE wwwdatatab.
DATA: lv_rc TYPE sy-subrc.
DATA: lo_excel TYPE ole2_object,
lo_workbook TYPE ole2_object,
lo_worksheet TYPE ole2_object,
lo_columns TYPE ole2_object.
DATA:iv_window_title TYPE string,
iv_filename TYPE string,
iv_fiel_filter TYPE string,
iv_isopen TYPE boolean."布尔变量(X = 真,- = 假,空格 = 未知
IF p_name IS INITIAL.
RETURN.
ENDIF.
CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
window_title = iv_window_title
default_extension = 'XLS'
default_file_name = iv_filename
file_filter = iv_fiel_filter
CHANGING
filename = lv_fielname
path = lv_path
fullpath = lv_fullpath
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
invalid_default_file_name = 4
OTHERS = 5.
IF sy-subrc <> 0.
RETURN.
ENDIF.
lv_dest = lv_fullpath.
SELECT SINGLE relid objid FROM wwwdata INTO CORRESPONDING FIELDS OF lo_objdata
WHERE srtf2 = 0 AND relid = 'MI' AND objid = p_name.
****检查表wwwdata中是否存在模板文件
IF sy-subrc NE 0 OR lo_objdata-objid EQ space.
MESSAGE '此模板文件不存在' TYPE 'S' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
CLEAR lv_rc.
CALL FUNCTION 'DOWNLOAD_WEB_OBJECT'
EXPORTING
key = lo_objdata
destination = lv_dest
IMPORTING
rc = lv_rc.
IF lv_rc NE 0.
MESSAGE '模板文件下载失败' TYPE 'S' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
IF iv_isopen IS INITIAL.
RETURN.
ENDIF.
ENDFORM.
最后当然是成品展示啦!
ALV筛选界面新加的按钮:下载模板,就是我们在程序中添加的下载在SMW0里上传的文件功能。点击就可以下载一个新的导入模板,不必担心模板丢失啦!
选择文件后,点击执行。提示修改成功:
以上。
不妥之处欢迎留言指正。手动笑脸
欢迎关注公众号,每日更新: