记录自定义维护视图的修改日志

上次在《创建自定义表的日志》里聊了如何记录日志,今天聊聊自定义维护视图如何记录修改日志。

一、首先为表创建一个SCDO对象ZSD001
在这里插入图片描述
二、然后在SE11创建完维护视图,并为其创建视图的维护程序
在这里插入图片描述
之后为视图创建事件
在这里插入图片描述
在这里插入图片描述
创建如下两个事件
在这里插入图片描述
01事件是在保存前记录日志,02事件更新数据库

通用示例代码如下,直接copy了放进去即可,但是我调试的时候总是有问题,逻辑是动态取视图中的表所对应的SCDO对象,通过执行动态程序来更新数据。有兴趣的同学可以调试下

*&----------------------------------------------------------------*
*&      Form  F_BEFORE_SAVE
*&----------------------------------------------------------------*
FORM f_before_save ##CALLED.
  TYPES: BEGIN OF ty_tcdrp,
           object     TYPE cdobjectcl,
           reportname TYPE cdreport,
         END OF   ty_tcdrp,
         BEGIN OF ty_view_tab,
           object  TYPE cdobjectcl,
           tabname TYPE cdtabname,
         END OF   ty_view_tab.
  DATA: lt_ptab      TYPE STANDARD TABLE OF string,
        lv_prog      TYPE string,
        lv_mess      TYPE string,
        lv_sid       TYPE string,
        lt_obj       TYPE STANDARD TABLE OF ty_view_tab,
        lt_tcdrp     TYPE STANDARD TABLE OF ty_tcdrp,
        lv_fugn      TYPE funct_pool,
        lv_table     TYPE cdtabname,
        lv_namesfunc TYPE namespace,
        lv_funcgroup TYPE progname,
        lv_namesprog TYPE namespace,
        lv_program   TYPE progname,
        lrt_tabname  TYPE RANGE OF tabname,
        lt_dd26v     TYPE TABLE OF dd26v,
        lv_object    TYPE cdobjectcl.
  " Get tabnames
  " DD: Interface for reading a view from the ABAP/4 Dictionary
  CALL FUNCTION 'DDIF_VIEW_GET'
    EXPORTING
      name          = vim_view_name
    TABLES
      dd26v_tab     = lt_dd26v
    EXCEPTIONS
      illegal_input = 1
      OTHERS        = 2.
  IF sy-subrc IS NOT INITIAL.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
            WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
  IF lt_dd26v IS INITIAL.
    APPEND INITIAL LINE TO lrt_tabname ASSIGNING FIELD-SYMBOL(<lrs_tabname>).
    <lrs_tabname>-sign   = 'I'.
    <lrs_tabname>-option = 'EQ'.
    <lrs_tabname>-low    = vim_view_name.
  ELSE.
    SORT lt_dd26v BY tabname.
    DELETE ADJACENT DUPLICATES FROM lt_dd26v COMPARING tabname.
    "*-
    LOOP AT lt_dd26v INTO DATA(ls_dd26v).
      APPEND INITIAL LINE TO lrt_tabname ASSIGNING <lrs_tabname>.
      <lrs_tabname>-sign   = 'I'.
      <lrs_tabname>-option = 'EQ'.
      <lrs_tabname>-low    = ls_dd26v-tabname.
    ENDLOOP.
  ENDIF.
  " Objects for change document creation
  SELECT object tabname
    FROM tcdob
    INTO TABLE lt_obj
    WHERE tabname IN lrt_tabname
    ##WARN_OK.
  IF sy-subrc IS NOT INITIAL.
    " No change document objects found
    MESSAGE i899(cd).
    RETURN.
  ENDIF.
  " Information on Include Reports Generated by RSSCD000
  SELECT object reportname
    FROM tcdrp
    INTO TABLE lt_tcdrp
    FOR ALL ENTRIES IN lt_obj
    WHERE object EQ lt_obj-object
    ##WARN_OK.
  IF sy-subrc IS NOT INITIAL.
    " Update program does not yet exist
    MESSAGE i446(m2).
    RETURN.
  ENDIF.
  " View Directory
  SELECT SINGLE area
    FROM tvdir
    INTO lv_fugn
    WHERE tabname EQ vim_view_name.
  "*-
  LOOP AT lt_obj ASSIGNING FIELD-SYMBOL(<ls_obj>).
    READ TABLE lt_tcdrp ASSIGNING FIELD-SYMBOL(<ls_tcdrp>)
                        WITH KEY object = <ls_obj>-object.
    IF sy-subrc IS NOT INITIAL.
      CONTINUE.
    ENDIF.
    " Split namespace
    CLEAR: lv_namesprog, lv_program.
    lv_program = <ls_tcdrp>-reportname.
    CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE'
      EXPORTING
        name_with_namespace    = lv_program
      IMPORTING
        namespace              = lv_namesprog
        name_without_namespace = lv_program
      EXCEPTIONS
        delimiter_error        = 1
        OTHERS                 = 2.
    IF sy-subrc <> 0.
      lv_program = <ls_tcdrp>-reportname.
    ENDIF.
    CLEAR: lv_namesfunc, lv_funcgroup.
    lv_funcgroup = lv_fugn.
    CALL FUNCTION 'RS_NAME_SPLIT_NAMESPACE'
      EXPORTING
        name_with_namespace    = lv_funcgroup
      IMPORTING
        namespace              = lv_namesfunc
        name_without_namespace = lv_funcgroup
      EXCEPTIONS
        delimiter_error        = 1
        OTHERS                 = 2.
    IF sy-subrc <> 0.
      lv_funcgroup = lv_fugn.
    ENDIF.
    " Namespace conversion
    lv_object = <ls_obj>-object.
    IF lv_object(1) = '/'.
      SHIFT lv_object LEFT DELETING LEADING '/'.
      REPLACE FIRST OCCURRENCE OF '/' IN lv_object WITH '_'.
    ENDIF.
    lv_table = <ls_obj>-tabname.
    IF lv_table(1) = '/'.
      SHIFT lv_table LEFT DELETING LEADING '/'.
      REPLACE FIRST OCCURRENCE OF '/' IN lv_table WITH '_'.
    ENDIF.
    " Subroutine pool
    APPEND ##NO_TEXT:
           `PROGRAM SUBPOOL.` TO lt_ptab,
           `  INCLUDE ` && lv_namesprog  && `F` && lv_program && `CDT.` TO lt_ptab,
           `  INCLUDE ` && lv_namesprog  && `F` && lv_program && `CDC.` TO lt_ptab,
           `  FORM f_process.` TO lt_ptab,
           `    TYPES:  BEGIN OF total.` TO lt_ptab,
           `            INCLUDE STRUCTURE ` && vim_view_name && `.` TO lt_ptab,
           `            INCLUDE STRUCTURE vimflagtab.` TO lt_ptab,
           `    TYPES:  END OF total.` TO lt_ptab,
           `    FIELD-SYMBOLS: <fs_total>       TYPE ANY TABLE,` TO lt_ptab,
           `                   <fs_total_wa>    TYPE total,` TO lt_ptab,
           `                   <fs_x_namtab>    TYPE ANY TABLE,` TO lt_ptab,
           `                   <fs_x_namtab_wa> TYPE vimnamtab,` TO lt_ptab,
           `                   <fs_field>       TYPE any.` TO lt_ptab,
           `    DATA: lv_tabname(40) TYPE c VALUE '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)TOTAL[]',` TO lt_ptab,
           `          lv_cond_line  TYPE string,` TO lt_ptab,
           `          lv_cond_line2 TYPE string.` TO lt_ptab,
           `    ASSIGN (lv_tabname) TO <fs_total>.` TO lt_ptab,
           `    LOOP AT <fs_total> ASSIGNING <fs_total_wa> CASTING.` TO lt_ptab,
           `      CASE <fs_total_wa>-action.` TO lt_ptab,
           `        WHEN 'U'. " Update` TO lt_ptab,
           `          lv_tabname = '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)X_NAMTAB[]'.` TO lt_ptab,
           `          ASSIGN (lv_tabname) TO <fs_x_namtab>.` TO lt_ptab,
           `          lv_cond_line2 = |keyflag EQ 'X' AND viewfield NE 'MANDT'|.` TO lt_ptab,
           `          LOOP AT <fs_x_namtab> ASSIGNING <fs_x_namtab_wa> WHERE (lv_cond_line2).` TO lt_ptab,
           `            ASSIGN COMPONENT <fs_x_namtab_wa>-viewfield OF STRUCTURE <fs_total_wa> TO <fs_field>.` TO lt_ptab,
           `            IF sy-subrc IS INITIAL.` TO lt_ptab,
           `              lv_cond_line = lv_cond_line && |AND | && ` TO lt_ptab,
           `                             <fs_x_namtab_wa>-viewfield && | EQ '| && <fs_field> && |' |.` TO lt_ptab,
           `              objectid = objectid && <fs_field>.` TO lt_ptab,
           `              UNASSIGN <fs_field>.` TO lt_ptab,
           `            ENDIF.` TO lt_ptab,
           `          ENDLOOP.` TO lt_ptab,
           `          IF sy-subrc IS INITIAL.` TO lt_ptab,
           `            SHIFT lv_cond_line LEFT BY 3 PLACES.` TO lt_ptab,
           `            SELECT SINGLE *` TO lt_ptab,
           `              FROM ` && <ls_obj>-tabname TO lt_ptab,
           `              INTO *` && <ls_obj>-tabname TO lt_ptab,
           `              WHERE (lv_cond_line).` TO lt_ptab,
           `            MOVE-CORRESPONDING <fs_total_wa> TO ` && <ls_obj>-tabname && `.` TO lt_ptab,
           `            objectid        = objectid.` TO lt_ptab,
           `            tcode           = sy-tcode.` TO lt_ptab,
           `            udate           = sy-datum.` TO lt_ptab,
           `            utime           = sy-uzeit.` TO lt_ptab,
           `            username        = sy-uname.` TO lt_ptab,
           `            cdoc_upd_object = 'U'.` TO lt_ptab,
           `            upd_` && lv_table && ` = 'U'.` TO lt_ptab,
           `            PERFORM cd_call_` && lv_object && `.` TO lt_ptab,
           `          ENDIF.` TO lt_ptab,
           `        WHEN 'N'. " New` TO lt_ptab,
           `          lv_tabname = '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)X_NAMTAB[]'.` TO lt_ptab,
           `          ASSIGN (lv_tabname) TO <fs_x_namtab>.` TO lt_ptab,
           `          lv_cond_line2 = |keyflag EQ 'X' AND viewfield NE 'MANDT'|.` TO lt_ptab,
           `          LOOP AT <fs_x_namtab> ASSIGNING <fs_x_namtab_wa> WHERE (lv_cond_line2).` TO lt_ptab,
           `            ASSIGN COMPONENT <fs_x_namtab_wa>-viewfield OF STRUCTURE <fs_total_wa> TO <fs_field>.` TO lt_ptab,
           `            IF sy-subrc IS INITIAL.` TO lt_ptab,
           `              objectid = objectid && <fs_field>.` TO lt_ptab,
           `              UNASSIGN <fs_field>.` TO lt_ptab,
           `            ENDIF.` TO lt_ptab,
           `          ENDLOOP.` TO lt_ptab,
           `          IF sy-subrc IS INITIAL.` TO lt_ptab,
           `            MOVE-CORRESPONDING <fs_total_wa> TO ` && <ls_obj>-tabname && `.` TO lt_ptab,
           `            objectid        = objectid.` TO lt_ptab,
           `            tcode           = sy-tcode.` TO lt_ptab,
           `            udate           = sy-datum.` TO lt_ptab,
           `            utime           = sy-uzeit.` TO lt_ptab,
           `            username        = sy-uname.` TO lt_ptab,
           `            cdoc_upd_object = 'I'.` TO lt_ptab,
           `            upd_` && lv_table && ` = 'I'.` TO lt_ptab,
           `            PERFORM cd_call_` && lv_object && `.` TO lt_ptab,
           `          ENDIF.` TO lt_ptab,
           `        WHEN 'D'. " Delete` TO lt_ptab,
           `          lv_tabname = '(` && lv_namesfunc && `SAPL` && lv_funcgroup && `)X_NAMTAB[]'.` TO lt_ptab,
           `          ASSIGN (lv_tabname) TO <fs_x_namtab>.` TO lt_ptab,
           `          lv_cond_line2 = |keyflag EQ 'X' AND viewfield NE 'MANDT'|.` TO lt_ptab,
           `          LOOP AT <fs_x_namtab> ASSIGNING <fs_x_namtab_wa> WHERE (lv_cond_line2).` TO lt_ptab,
           `            ASSIGN COMPONENT <fs_x_namtab_wa>-viewfield OF STRUCTURE <fs_total_wa> TO <fs_field>.` TO lt_ptab,
           `            IF sy-subrc IS INITIAL.` TO lt_ptab,
           `              objectid = objectid && <fs_field>.` TO lt_ptab,
           `              UNASSIGN <fs_field>.` TO lt_ptab,
           `            ENDIF.` TO lt_ptab,
           `          ENDLOOP.` TO lt_ptab,
           `          IF sy-subrc IS INITIAL.` TO lt_ptab,
           `            MOVE-CORRESPONDING <fs_total_wa> TO *` && <ls_obj>-tabname && `.` TO lt_ptab,
           `            objectid        = objectid.` TO lt_ptab,
           `            tcode           = sy-tcode.` TO lt_ptab,
           `            udate           = sy-datum.` TO lt_ptab,
           `            utime           = sy-uzeit.` TO lt_ptab,
           `            username        = sy-uname.` TO lt_ptab,
           `            cdoc_upd_object = 'D'.` TO lt_ptab,
           `            upd_` && lv_table && ` = 'D'.` TO lt_ptab,
           `            PERFORM cd_call_` && lv_object && `.` TO lt_ptab,
           `          ENDIF.` TO lt_ptab,
           `      ENDCASE.` TO lt_ptab,
           `      CLEAR: lv_cond_line, lv_cond_line2, objectid, ` && <ls_obj>-tabname && `, *` && <ls_obj>-tabname && `.` TO lt_ptab,
           `    ENDLOOP.` TO lt_ptab,
           `  ENDFORM.` TO lt_ptab.
    "*-
    GENERATE SUBROUTINE POOL lt_ptab NAME lv_prog
             MESSAGE lv_mess
             SHORTDUMP-ID lv_sid.
    IF sy-subrc = 0.
      PERFORM ('F_PROCESS') IN PROGRAM (lv_prog) IF FOUND.
    ELSEIF sy-subrc = 4.
      MESSAGE lv_mess TYPE 'I'.
    ELSEIF sy-subrc = 8.
      MESSAGE lv_sid TYPE 'I'.
    ENDIF.
    CLEAR: lt_ptab.
  ENDLOOP.
ENDFORM.
*&----------------------------------------------------------------*
*&      Form  F_AFTER_SAVE
*&----------------------------------------------------------------*
FORM f_after_save ##CALLED.
  COMMIT WORK AND WAIT.
ENDFORM.

我没有调通上面的代码,于是重新复写了FRM_BEFORE_SAVE

FORM frm_before_save.
  TYPES:  BEGIN OF total.
          INCLUDE STRUCTURE zsdv004.
          INCLUDE STRUCTURE vimflagtab.
  TYPES:  END OF total.

  FIELD-SYMBOLS: <fs_total>    TYPE ANY TABLE,
                 <fs_total_wa> TYPE total.
  DATA: lv_tabname(40) TYPE c VALUE '(SAPLZSDV004)TOTAL[]'.
  DATA: lv_uuid        LIKE sysuuid-x,
        ls_zsd001      LIKE cdtxt,
        lt_zsd001      LIKE TABLE OF ls_zsd001,
        ls_zsdt004     TYPE zsdt004,
        ls_yzsdt004    TYPE yzsdt004,
        lt_zsdt004     TYPE TABLE OF YZSDT004,
        lt_zsdt004_old TYPE TABLE OF YZSDT004.

  ASSIGN (lv_tabname) TO <fs_total>.
  LOOP AT <fs_total> ASSIGNING <fs_total_wa> CASTING.
    CLEAR: lt_zsdt004,lt_zsdt004_old,lt_zsd001.

    CASE <fs_total_wa>-action.
      WHEN 'U'. " Update
*        CALL FUNCTION 'SYSTEM_UUID_CREATE'
*          IMPORTING
*            uuid = lv_uuid.
        CONCATENATE SY-MANDT <fs_total_wa>-kunnr INTO ls_zsd001-teilobjid.
*        ls_zsd001-teilobjid = lv_uuid.
        ls_zsd001-textart = 'MODF'.
        ls_zsd001-textspr = '1'.
        ls_zsd001-updkz = 'U'.
        APPEND ls_zsd001 TO lt_zsd001.
        CLEAR ls_zsd001.

        "旧值
        SELECT SINGLE *
          FROM zsdt004
          INTO ls_zsdt004
         WHERE kunnr = <fs_total_wa>-kunnr.
        IF sy-subrc = 0.
          MOVE-CORRESPONDING ls_zsdt004 to ls_yzsdt004.
          APPEND ls_yzsdt004 TO lt_zsdt004_old.
          CLEAR: ls_zsdt004,ls_yzsdt004.
        ENDIF.

        "新值
        MOVE-CORRESPONDING <fs_total_wa> TO ls_yzsdt004.
        APPEND ls_yzsdt004 TO lt_zsdt004.
        CLEAR ls_yzsdt004.

        CALL FUNCTION 'ZSD001_WRITE_DOCUMENT'
          EXPORTING
            objectid          = 'ZSD001'
            tcode             = sy-tcode
            utime             = sy-uzeit
            udate             = sy-datum
            username          = sy-uname
            upd_icdtxt_zsd001 = 'U'
            upd_zsdt004       = 'U'
          TABLES
            icdtxt_zsd001     = lt_zsd001
            xzsdt004          = lt_zsdt004
            yzsdt004          = lt_zsdt004_old.

      WHEN 'D'. " Delete
*        CALL FUNCTION 'SYSTEM_UUID_CREATE'
*          IMPORTING
*            uuid = lv_uuid.

*        ls_zsd001-teilobjid = lv_uuid.
        CONCATENATE SY-MANDT <fs_total_wa>-kunnr INTO ls_zsd001-teilobjid.
        ls_zsd001-textart = 'DELE'.
        ls_zsd001-textspr = '1'.
        ls_zsd001-updkz = 'D'.
        APPEND ls_zsd001 TO lt_zsd001.
        CLEAR ls_zsd001.

        "旧值
        SELECT SINGLE *
          FROM zsdt004
          INTO ls_zsdt004
         WHERE kunnr = <fs_total_wa>-kunnr.
        IF sy-subrc = 0.
          MOVE-CORRESPONDING ls_zsdt004 to ls_yzsdt004.
          APPEND ls_yzsdt004 TO lt_zsdt004_old.
          CLEAR: ls_zsdt004,ls_yzsdt004.
        ENDIF.

        "新值
        MOVE-CORRESPONDING <fs_total_wa> TO ls_yzsdt004.
        APPEND ls_yzsdt004 TO lt_zsdt004.
        CLEAR ls_yzsdt004.

        CALL FUNCTION 'ZSD001_WRITE_DOCUMENT'
          EXPORTING
            objectid          = 'ZSD001'
            tcode             = sy-tcode
            utime             = sy-uzeit
            udate             = sy-datum
            username          = sy-uname
            upd_icdtxt_zsd001 = 'U'
            upd_zsdt004       = 'U'
          TABLES
            icdtxt_zsd001     = lt_zsd001
            xzsdt004          = lt_zsdt004
            yzsdt004          = lt_zsdt004_old.
    ENDCASE.
  ENDLOOP.

ENDFORM.

三、创建报表程序,调用rsscd100显示更改日志

REPORT zsdr054.

DATA: gt_cdred_str        TYPE cdred_str_tab.

*----------------------------------------------------------------------
* screen
*----------------------------------------------------------------------
SELECTION-SCREEN BEGIN OF BLOCK bk1 WITH FRAME TITLE text-001.
PARAMETERS: aenderer TYPE cdhdr-username,
            datum    TYPE cdhdr-udate,
            zeit     TYPE cdhdr-utime,
            dat_bis  TYPE cdhdr-udate DEFAULT sy-datum,
            zeit_bis TYPE cdhdr-utime DEFAULT '235959'.
SELECTION-SCREEN END OF BLOCK bk1.

*----------------------------------------------------------------------
* START-OF-SELECTION
*----------------------------------------------------------------------
START-OF-SELECTION.
* 调用程序显示数据
  PERFORM frm_data_display.

*&---------------------------------------------------------------------*
*&      Form  FRM_DATA_DISPLAY
*&---------------------------------------------------------------------*
*       调用程序显示数据
*----------------------------------------------------------------------*
FORM frm_data_display .
  SUBMIT rsscd100 WITH objekt = 'ZSD001'
                  WITH aenderer = aenderer
                  WITH datum = datum
                  WITH zeit = zeit
                  WITH dat_bis = dat_bis
                  WITH zeit_bis = zeit_bis AND RETURN.
ENDFORM.                    " FRM_DATA_DISPLAY

执行程序,查看运行效果:
在这里插入图片描述
在这里插入图片描述
PS:喜欢的同学可以关注微信公众号
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值