SAP ABAP使用SHDB(BDC程序)批量处理数据(从负九九九开始教你ABAP批导程序)

一、业务场景:批量修改工作中心能力(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里上传的文件功能。点击就可以下载一个新的导入模板,不必担心模板丢失啦!
在这里插入图片描述
选择文件后,点击执行。提示修改成功:
在这里插入图片描述
以上。
不妥之处欢迎留言指正。手动笑脸
欢迎关注公众号,每日更新:
在这里插入图片描述

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI云书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值