SAP之FPM卷六:FPM开发实例-完成主页面功能(2)

本文档系列深入讲解了SAP FPM开发中的关键环节,包括创建WDA应用、需求分析与优化、数据表结构、搜索页面代码、主页面功能实现(包括数据锁定、编辑权限控制)和单步审批流程。详细介绍了如何通过事件处理判断数据状态,确保数据安全和编辑权限的正确管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

SAP之FPM卷一:FPM是什么
SAP之FPM卷二:FPM开发实例-创建WDA应用
SAP之FPM卷三:FPM开发实例-设想需求与优化
SAP之FPM卷四:FPM开发实例- 创建程序所需表,结构并完成搜索页面主要代码
SAP之FPM卷五:FPM开发实例-完成主页面功能(1)
SAP之FPM卷七:FPM开发实例-完成主页面功能(通过EXCEL上载数据)



前言

接上篇实现具体设计
创建:从底表直接带出抬头与明细数据,然后为当前数据加锁,直至退出或返回
调整:带出上一版数据,抬头数据版本加一,且设置新GUID,然后对上一版数据加锁,对新生成的这一版数据也加锁,直至退出或返回
展示:直接带出对应数据,不加任何锁
编辑:首先判断数据状态,是否为保存状态,如果是,则可以编辑,然后放开明细中字段可编辑,按钮保存与取消编辑可用,返回按钮一直可用,编辑与单步审批不可用,并对当前版本数据加锁
保存:通过保存前校验可保存数据进底表,并设置保存、取消编辑按钮不可用,编辑、单步审批可用,解锁当前数据
取消编辑:退出编辑状态,解锁当前数据,设置保存、取消编辑不可用,编辑、单步审批可用
单步审批:通过校验后更改数据状态为有效
返回:跳转到搜索页面


一、跳转到主页面后

首先,为主数据创建一个锁对象,在主页面中会频繁用到。
名称如图,属性为写入锁

在这里插入图片描述
在主页面(明细页面)的类ZCL_TEST_DEMO_MAIN_LIST的属性中添加以下属性,以作备用
在这里插入图片描述
在类接口中添加一个接口IF_FPM_GUIBB_FORM_EXT,之后会用到
在这里插入图片描述

上一篇所有按钮都已经加好,现在完成各功能对应代码就可以,我直接把所有代码都放进来并作一定说明

初始化程序
IF_FPM_GUIBB~INITIALIZE:

METHOD if_fpm_guibb~initialize.

  DATA:lt_app_key  TYPE TABLE OF string,
       lv_app_key  TYPE          string,
       lv_appvalue TYPE          string,
       lv_guid     TYPE          guid,
       ls_header   TYPE          ztest_demo_sch.

  mo_fpm ?= cl_fpm=>get_instance( ).

  CLEAR:ms_header,mv_adjut_guid,mv_save_ok,mv_edit_ok.

  IF mo_fpm IS NOT INITIAL.
  
*     获取应用传递的参数
    TRY.
        lt_app_key = mo_fpm->mo_app_parameter->get_keys( ).
        LOOP AT lt_app_key INTO lv_app_key.
          CALL METHOD mo_fpm->mo_app_parameter->get_value
            EXPORTING
              iv_key   = lv_app_key
            IMPORTING
              ev_value = lv_appvalue.
          CASE lv_app_key.
            WHEN 'ZSYBM'.
              ms_header-zsybm = lv_appvalue.
            WHEN 'PSPID'.
              ms_header-pspid = lv_appvalue.
            WHEN 'POST1'.
              ms_header-post1 = lv_appvalue.
            WHEN 'ACTION'.
              mv_curr_action = lv_appvalue.
            WHEN 'GUID'.
              lv_guid = lv_appvalue.
*            WHEN 'SAP-WD-CONFIGID'.
*              mv_app_name = lv_appvalue.

          ENDCASE.
        ENDLOOP.

*          创建
        IF mv_curr_action EQ gc_event_create.

          TRY.

              ms_header-guid = cl_system_uuid=>create_uuid_x16_static( ).

            CATCH cx_uuid_error .
          ENDTRY.

*          加锁
          CALL FUNCTION 'ENQUEUE_EZDEMOL'
            EXPORTING
              mode_ztest_demo_sch = 'E'
              mandt               = sy-mandt
              guid                = ms_header-guid
              x_guid              = ' '
              _scope              = '2'
              _wait               = ' '
              _collect            = ' '
            EXCEPTIONS
              foreign_lock        = 1
              system_failure      = 2
              OTHERS              = 3.
          IF sy-subrc <> 0.
* Implement suitable error handling here
          ENDIF.


          ms_header-version = 1.
          ms_header-status = '4'.
          ms_header-zcre_user = sy-uname.
          ms_header-zcre_date = sy-datum.

        ENDIF.

*          调整
        IF mv_curr_action EQ gc_event_adjust.

          mv_adjut_guid = lv_guid.

          SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_header
            FROM ztest_demo_sch
            WHERE guid = lv_guid.
          IF sy-subrc EQ 0.

            TRY.

                ms_header-guid = cl_system_uuid=>create_uuid_x16_static( ).

              CATCH cx_uuid_error .
            ENDTRY.

            ms_header-zsybm = ls_header-zsybm.
            ms_header-pspid = ls_header-pspid.
            ms_header-post1 = ls_header-post1.
            ms_header-status = '4'.
            ms_header-version = ls_header-version + 1.
            ms_header-zcre_user = sy-uname.
            ms_header-zcre_date = sy-datum.

            CLEAR:ms_header-zlch_user,ms_header-zlch_date.

          ENDIF.
          
*            查看
        ELSEIF mv_curr_action EQ 'DISPLAY'.

          CLEAR:ms_header.
          SELECT SINGLE * INTO CORRESPONDING FIELDS OF ms_header
            FROM ztest_demo_sch
            WHERE guid = lv_guid.

        ENDIF.

    ENDTRY.

  ENDIF.

ENDMETHOD.

IF_FPM_GUIBB_FORM~GET_DEFINITION:

  METHOD if_fpm_guibb_form~get_definition.

    DATA:
      ls_action_def  TYPE         fpmgb_s_actiondef,
      ls_fixed_value TYPE         wdr_context_attr_value,
      ls_field_descr LIKE LINE OF et_field_description,
      lt_component   TYPE         abap_component_tab,
      ls_value       TYPE         wdr_context_attr_value,
      lt_value       TYPE         wdr_context_attr_value_list.

    FIELD-SYMBOLS:
      <ls_component>  LIKE LINE OF lt_component,
      <fs_field_desc> TYPE         fpmgb_s_formfield_descr.

    eo_field_catalog ?= cl_abap_structdescr=>describe_by_data( ms_header ).
    lt_component = eo_field_catalog->get_components( ).

*    为字段设置属性
    LOOP AT lt_component ASSIGNING <ls_component>.
      CLEAR ls_field_descr.

      ls_field_descr-name = <ls_component>-name.

      "设置必输
      IF <ls_component>-name = 'ZSYBM'.

*        事业部设置成下拉框 所以必须要有fixed_value
        ls_value-value = '01'.
        ls_value-text = '北京事业部'.
        APPEND ls_value TO lt_value.
        ls_value-value = '02'.
        ls_value-text = '上海事业部'.
        APPEND ls_value TO lt_value.

        ls_field_descr-fixed_values = lt_value.
        CLEAR:lt_value.

        ls_field_descr-mandatory = 'X'.
        APPEND ls_field_descr TO et_field_description.
      ELSE.
        APPEND ls_field_descr TO et_field_description.
      ENDIF.

    ENDLOOP.

*   添加EVENT(按钮)
*   保存
    CLEAR: ls_action_def-extended.
    ls_action_def-id = 'FPM_SAVE'.
    ls_action_def-imagesrc = '~Icon/Save'.
    ls_action_def-text = '保存'.
    ls_action_def-enabled = abap_true.
    APPEND ls_action_def TO et_action_definition.

*   取消编辑
    CLEAR: ls_action_def-extended.
    ls_action_def-id = 'FPM_CANCEL'.
    ls_action_def-imagesrc = '~Icon/Cancel'.
    ls_action_def-text = '取消编辑'.
    ls_action_def-enabled = abap_true.
    APPEND ls_action_def TO et_action_definition.

*   取消编辑
    CLEAR: ls_action_def-extended.
    ls_action_def-id = 'FPM_EDIT'.
    ls_action_def-imagesrc = '~Icon/Edit'.
    ls_action_def-text = '编辑'.
    ls_action_def-enabled = abap_true.
    APPEND ls_action_def TO et_action_definition.

*   单步审批
    CLEAR: ls_action_def-extended.
    ls_action_def-id = 'FPM_DBSP'.
    ls_action_def-imagesrc = '~Icon/Complete'.
    ls_action_def-text = '单步审批'.
    ls_action_def-enabled = abap_true.
    APPEND ls_action_def TO et_action_definition.

*   返回
    CLEAR: ls_action_def-extended.
    ls_action_def-id = 'FPM_BACK'.
    ls_action_def-imagesrc = '~Icon/Cancelled'.
    ls_action_def-text = '返回'.
    ls_action_def-enabled = abap_true.
    APPEND ls_action_def TO et_action_definition.

  ENDMETHOD.

IF_FPM_GUIBB_FORM~FLUSH:

  METHOD if_fpm_guibb_form~flush.

    FIELD-SYMBOLS: <fs> TYPE any.

    IF it_change_log IS NOT INITIAL.
      ASSIGN is_data->* TO <fs>.
      ms_header = <fs>.
    ENDIF.

  ENDMETHOD.

从搜索页面到主页面后,需要判断是什么操作,然后设置按钮属性,如果是调整,那么给选中的那条调整数据加锁
如果是保存或取消编辑操作,保存操作需要判断是否保存成功,否则不允许修改字段或按钮状态
返回搜索页面则先解锁,然后跳转到当前程序
如果是编辑操作,需要判断当前数据能否编辑,如果是有效数据就不允许编辑,保存和编辑的判断都是在PROCESS_EVENT中,因为操作在PROCESS_EVENT中先于GET_DATA
IF_FPM_GUIBB_FORM~GET_DATA:

METHOD if_fpm_guibb_form~get_data.

    DATA:
      lv_field      TYPE         string,
      lv_index1     TYPE         i,
      lv_edit_mode  TYPE         fpm_edit_mode,

      lt_app_params TYPE         apb_lpd_t_params,
      ls_app_param  LIKE LINE OF lt_app_params,
      ls_add_para   TYPE         apb_lpd_s_add_wd_parameters.

    FIELD-SYMBOLS:<fs_field_usage>  TYPE fpmgb_s_fieldusage,
                  <fs_action_usage> TYPE fpmgb_s_actionusage.

    CASE io_event->mv_event_id.

*      跳转到主页面的标准event
      WHEN cl_fpm_event=>gc_event_leave_initial_screen." 'FPM_LEAVE_INITIAL_SCREEN'.

        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.

          IF mv_curr_action EQ gc_event_display.

            IF <fs_action_usage>-id EQ gc_event_save OR <fs_action_usage>-id EQ gc_event_cancel.
              <fs_action_usage>-enabled = abap_false.
            ELSE.
              <fs_action_usage>-enabled = abap_true.
            ENDIF.

          ELSEIF mv_curr_action EQ gc_event_adjust OR mv_curr_action EQ gc_event_create.

            IF <fs_action_usage>-id EQ gc_event_save OR <fs_action_usage>-id EQ gc_event_cancel
              OR <fs_action_usage>-id EQ gc_event_back.
              <fs_action_usage>-enabled = abap_true.
            ELSE.
              <fs_action_usage>-enabled = abap_false.
            ENDIF.

          ENDIF.

        ENDLOOP.

        IF mv_curr_action EQ gc_event_adjust.

          CALL FUNCTION 'ENQUEUE_EZDEMOL'
            EXPORTING
              mode_ztest_demo_sch = 'E'
              mandt               = sy-mandt
              guid                = ms_header-guid
              x_guid              = ' '
              _scope              = '2'
              _wait               = ' '
              _collect            = ' '
            EXCEPTIONS
              foreign_lock        = 1
              system_failure      = 2
              OTHERS              = 3.
          IF sy-subrc <> 0.
* Implement suitable error handling here
          ENDIF.

        ENDIF.

        CALL METHOD me->get_exist_data( ).

      WHEN gc_event_cancel OR gc_event_save.

        IF io_event->mv_event_id EQ gc_event_save AND mv_save_ok NE abap_true.
          EXIT.
        ENDIF.

        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.
          IF <fs_action_usage>-id EQ gc_event_save OR <fs_action_usage>-id EQ gc_event_cancel.
            <fs_action_usage>-enabled = abap_false.
          ELSE.
            <fs_action_usage>-enabled = abap_true.
          ENDIF.
        ENDLOOP.

      WHEN gc_event_back.

*        解锁
        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.
          IF <fs_action_usage>-id EQ gc_event_save.
            IF <fs_action_usage>-enabled = abap_true.

              IF mv_adjut_guid IS NOT INITIAL.
                CALL FUNCTION 'DEQUEUE_EZDEMOL'
                  EXPORTING
                    mode_ztest_demo_sch = 'E'
                    mandt               = sy-mandt
                    guid                = mv_adjut_guid
                    x_guid              = ' '
                    _scope              = '3'
                    _synchron           = ' '
                    _collect            = ' '.
              ENDIF.

              CALL FUNCTION 'DEQUEUE_EZDEMOL'
                EXPORTING
                  mode_ztest_demo_sch = 'E'
                  mandt               = sy-mandt
                  guid                = ms_header-guid
                  x_guid              = ' '
                  _scope              = '3'
                  _synchron           = ' '
                  _collect            = ' '.

            ENDIF.
          ENDIF.

        ENDLOOP.

        CLEAR:lt_app_params,ls_add_para.
*        ls_app_param-key = 'SKIP_INITIAL_SCREEN'.
*        ls_app_param-value = abap_false.
*        APPEND ls_app_param TO lt_app_params.

        ls_add_para-navigation_mode = 'INPLACE'.   "替换当前页面

*        跳转到搜索页面
        zgld_cl_fpm_navigation=>launch_webdynpro_abap(
          iv_wda  = 'ZTEST_WDA_APPLICATION'
          iv_wdac = 'ZTEST_WDA_APPLICATION'
          it_parameter = lt_app_params
          is_additional_parameters = ls_add_para ).

      WHEN gc_event_edit.

        IF io_event->mv_event_id EQ gc_event_edit AND mv_edit_ok NE abap_true.
          EXIT.
        ENDIF.

        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.
          IF <fs_action_usage>-id EQ gc_event_save OR <fs_action_usage>-id EQ gc_event_cancel
          OR <fs_action_usage>-id EQ gc_event_back.
            <fs_action_usage>-enabled = abap_true.
          ELSE.
            <fs_action_usage>-enabled = abap_false.
          ENDIF.
        ENDLOOP.

      WHEN OTHERS.
    ENDCASE.

*    设置事业部与状态字段只读
    LOOP AT ct_field_usage ASSIGNING <fs_field_usage>.

      IF <fs_field_usage>-name EQ 'ZSYBM' OR <fs_field_usage>-name EQ 'STATUS'.
        <fs_field_usage>-read_only = abap_true.
      ENDIF.

    ENDLOOP.

    ev_action_usage_changed = abap_true.
    ev_field_usage_changed = abap_true.

    cs_data = ms_header.
    ev_data_changed = abap_true.
    
  ENDMETHOD.

IF_FPM_GUIBB_FORM~PROCESS_EVENT:

  METHOD if_fpm_guibb_form~process_event.

    DATA:ls_message TYPE fpmgb_s_t100_message.

    CASE io_event->mv_event_id.
      WHEN gc_event_edit.

*        编辑前检查
        CALL METHOD me->check_before_edit(
          CHANGING
            cv_result   = ev_result
            ct_messages = et_messages
                          ).

        IF ev_result NE 'FAILED'.
          mv_edit_ok = abap_true.
        ELSE.
          CLEAR:mv_edit_ok.
        ENDIF.

        CHECK ev_result NE 'FAILED'.

*    加锁
        CALL FUNCTION 'ENQUEUE_EZDEMOL'
          EXPORTING
            mode_ztest_demo_sch = 'E'
            mandt               = sy-mandt
            guid                = ms_header-guid
            x_guid              = ' '
            _scope              = '2'
            _wait               = ' '
            _collect            = ' '
          EXCEPTIONS
            foreign_lock        = 1
            system_failure      = 2
            OTHERS              = 3.
        IF sy-subrc <> 0.
* Implement suitable error handling here
        ENDIF.

      WHEN gc_event_cancel OR gc_event_save.    "取消编辑 保存

*    解锁
        IF io_event->mv_event_id EQ gc_event_save.

          CALL METHOD me->check_before_save(
            CHANGING
              cv_result   = ev_result
              ct_messages = et_messages
                            ).

          IF ev_result NE 'FAILED'.
            mv_save_ok = abap_true.
          ELSE.
            CLEAR:mv_save_ok.
          ENDIF.
          CHECK ev_result NE 'FAILED'.

          CALL METHOD me->save_data( ).

          mv_save_ok = abap_true.

        ENDIF.

        IF mv_adjut_guid IS NOT INITIAL.
          CALL FUNCTION 'DEQUEUE_EZDEMOL'
            EXPORTING
              mode_ztest_demo_sch = 'E'
              mandt               = sy-mandt
              guid                = mv_adjut_guid
              x_guid              = ' '
              _scope              = '3'
              _synchron           = ' '
              _collect            = ' '.
        ENDIF.

        CALL FUNCTION 'DEQUEUE_EZDEMOL'
          EXPORTING
            mode_ztest_demo_sch = 'E'
            mandt               = sy-mandt
            guid                = ms_header-guid
            x_guid              = ' '
            _scope              = '3'
            _synchron           = ' '
            _collect            = ' '.

      WHEN gc_event_dbsp.

*        单步审批前检查
        CALL METHOD me->check_before_dbsp(
          CHANGING
            cv_result   = ev_result
            ct_messages = et_messages
                          ).
        CHECK ev_result NE 'FAILED'.

*        设置状态为生效
        UPDATE ztest_demo_sch SET status = '7' WHERE guid EQ ms_header-guid.

        ms_header-status = '7'.

        CLEAR:ls_message.
        ev_result = 'OK'.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'S'.
        ls_message-parameter_1 = '单步审批成功!'.
        APPEND ls_message TO et_messages.

      WHEN OTHERS.
    ENDCASE.


  ENDMETHOD.

然后是LIST
IF_FPM_GUIBB_LIST~GET_DEFINITION:

METHOD if_fpm_guibb_list~get_definition.

  DATA:ls_action_def    TYPE        fpmgb_s_actiondef,
       lt_component     TYPE        abap_component_tab,
       ls_field_descr   TYPE        fpmgb_s_listfield_descr,
       lo_field_catalog	TYPE REF TO cl_abap_structdescr.

  FIELD-SYMBOLS:
    <ls_component> LIKE LINE OF lt_component.

  eo_field_catalog ?= cl_abap_structdescr=>describe_by_data( mt_ldmx ).
  lo_field_catalog ?= eo_field_catalog->get_table_line_type( ).
  lt_component = lo_field_catalog->get_components( ).

*    为字段设置属性 手填字段设置为READONLY字段控制  当READONLY = X为只读  空为可编辑
  LOOP AT lt_component ASSIGNING <ls_component>.
    CLEAR ls_field_descr.

    ls_field_descr-name = <ls_component>-name.
    IF ls_field_descr-name EQ 'ZZJZMJ' OR ls_field_descr-name EQ 'ZWCMJ'
      OR ls_field_descr-name EQ 'ZYJWC' OR ls_field_descr-name EQ 'ZSJWC'
      OR ls_field_descr-name EQ 'ZREASON'.

      ls_field_descr-read_only_ref = 'READONLY'.

    ENDIF.

    APPEND ls_field_descr TO et_field_description.

  ENDLOOP.


*   添加EVENT(按钮)
*   上传数据
  CLEAR: ls_action_def-extended.
  ls_action_def-id = 'UPLOAD_DATA'.
  ls_action_def-imagesrc = '~Icon/Upload'.
  ls_action_def-text = '上载数据'.
  ls_action_def-enabled = abap_true.
  APPEND ls_action_def TO et_action_definition.

*   下载模板
  CLEAR: ls_action_def-extended.
  ls_action_def-id = 'DOWNLOAD_TEMP'.
  ls_action_def-imagesrc = '~Icon/Download'.
  ls_action_def-text = '下载模板'.
  ls_action_def-enabled = abap_true.
  APPEND ls_action_def TO et_action_definition.

ENDMETHOD.

IF_FPM_GUIBB_LIST~GET_DATA:

  METHOD if_fpm_guibb_list~get_data.

    FIELD-SYMBOLS:
      <fs_action_usage> TYPE fpmgb_s_actionusage,
      <fs_field_usage>  TYPE fpmgb_s_fieldusage,
      <fs_ldmx>         TYPE ts_ldmx.

    CASE iv_eventid->mv_event_id.

*      跳转到主页面的标准event
      WHEN cl_fpm_event=>gc_event_leave_initial_screen. " 'FPM_LEAVE_INITIAL_SCREEN'.
*        获取数据   设置按钮属性

        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.
          IF <fs_action_usage>-id EQ gc_upload_data.

            IF mv_curr_action EQ gc_event_display.
              <fs_action_usage>-enabled = abap_false.
            ELSE.
              <fs_action_usage>-enabled = abap_true.
            ENDIF.

          ENDIF.
        ENDLOOP.

        LOOP AT mt_ldmx ASSIGNING <fs_ldmx>.

          IF mv_curr_action EQ gc_event_display.
            <fs_ldmx>-readonly = abap_true.
          ELSE.
            <fs_ldmx>-readonly = abap_false.
          ENDIF.

        ENDLOOP.

      WHEN gc_event_cancel OR gc_event_save.

        IF iv_eventid->mv_event_id EQ gc_event_save AND mv_save_ok NE abap_true.
          EXIT.
        ENDIF.

        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.
          IF <fs_action_usage>-id EQ gc_upload_data.
            <fs_action_usage>-enabled = abap_false.
          ENDIF.
        ENDLOOP.

        LOOP AT mt_ldmx ASSIGNING <fs_ldmx>.

          <fs_ldmx>-readonly = abap_true.

        ENDLOOP.

      WHEN gc_event_edit.

        IF iv_eventid->mv_event_id EQ gc_event_edit AND mv_edit_ok NE abap_true.
          EXIT.
        ENDIF.

        LOOP AT ct_action_usage ASSIGNING <fs_action_usage>.
          IF <fs_action_usage>-id EQ gc_upload_data.
            <fs_action_usage>-enabled = abap_true.
          ENDIF.
        ENDLOOP.

        LOOP AT mt_ldmx ASSIGNING <fs_ldmx>.

          <fs_ldmx>-readonly = abap_false.

        ENDLOOP.

      WHEN OTHERS.
    ENDCASE.

    ct_data = mt_ldmx.
    ev_data_changed = abap_true.
    ev_action_usage_changed = abap_true.
    ev_field_usage_changed = abap_true.

  ENDMETHOD.

IF_FPM_GUIBB_LIST~FLUSH:

METHOD if_fpm_guibb_list~flush.

  FIELD-SYMBOLS: <ft> TYPE INDEX TABLE.

  IF it_change_log IS NOT INITIAL.
    ASSIGN it_data->* TO <ft>.
    mt_ldmx = <ft>.
  ENDIF.

ENDMETHOD.

这里为上载数据保留了一个口子,下一章再写怎么实现通过EXCEL上载数据
IF_FPM_GUIBB_LIST~PROCESS_EVENT:

METHOD if_fpm_guibb_list~process_event.

  CASE io_event->mv_event_id.

*    WHEN gc_upload_data.   "上载数据
 
    WHEN gc_download_temp.   "下载模板

      CALL METHOD me->download_template( ).

    WHEN OTHERS.
  ENDCASE.

ENDMETHOD.

类中添加以下方法:
在这里插入图片描述
CHECK_BEFORE_SAVE参数:
在这里插入图片描述
代码:

  METHOD check_before_save.

    DATA:ls_sch     TYPE          ztest_demo_sch,
         lt_sch     TYPE TABLE OF ztest_demo_sch,
         ls_message TYPE          fpmgb_s_t100_message,
         ls_ldmx    TYPE          ztest_demo_mx.

    SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_sch
      FROM ztest_demo_sch
      WHERE pspid EQ ms_header-pspid
      AND version EQ ms_header-version
      AND status NE '6'.

    IF sy-subrc EQ 0.
      READ TABLE lt_sch WITH KEY guid = ms_header-guid TRANSPORTING NO FIELDS.
      IF sy-subrc NE 0.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '已存在相同版本数据,请检查'.
        APPEND ls_message TO ct_messages.

      ELSE.

        cv_result = 'OK'.

      ENDIF.
    ENDIF.

    LOOP AT mt_ldmx INTO ls_ldmx WHERE zzjzmj IS NOT INITIAL.

      IF ls_ldmx-zwcmj GT ls_ldmx-zzjzmj.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '实际完成面积不能大于总建筑面积!'.
        APPEND ls_message TO ct_messages.
        EXIT.

      ENDIF.

      IF ls_ldmx-zwcmj EQ ls_ldmx-zzjzmj AND ls_ldmx-zsjwc IS INITIAL.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '完成所有面积实际完成日期必填!'.
        APPEND ls_message TO ct_messages.
        EXIT.

      ENDIF.

      IF ls_ldmx-zwcmj LT ls_ldmx-zzjzmj AND ls_ldmx-zyjwc IS INITIAL.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '如存在未完成面积,计划完成日期必填!'.
        APPEND ls_message TO ct_messages.
        EXIT.

      ENDIF.

      IF ls_ldmx-zsjwc GT sy-datum.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '实际完成日期不能大于今天!'.
        APPEND ls_message TO ct_messages.
        EXIT.

      ENDIF.

      IF ls_ldmx-zsjwc GT ls_ldmx-zyjwc AND ls_ldmx-zreason IS INITIAL.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '延期完成必须说明延期原因!'.
        APPEND ls_message TO ct_messages.
        EXIT.

      ENDIF.

    ENDLOOP.

  ENDMETHOD.

CHECK_BEFORE_EDIT参数:
在这里插入图片描述
代码:

  METHOD check_before_edit.

    DATA:ls_sch     TYPE ztest_demo_sch,
         ls_message TYPE fpmgb_s_t100_message.

    SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_sch
      FROM ztest_demo_sch
      WHERE guid EQ ms_header-guid.
    IF sy-subrc EQ 0.

      IF ls_sch-status NE '4'.

        cv_result = 'FAILED'.
        CLEAR:ls_message.
        ls_message-msgid = 'ZTEST'.
        ls_message-msgno = '004'.
        ls_message-severity = 'E'.
        ls_message-parameter_1 = '该数据状态不能修改'.
        APPEND ls_message TO ct_messages.

      ELSE.

        cv_result = 'OK'.

      ENDIF.

    ENDIF.

  ENDMETHOD.

SAVE_DATA无需参数
代码:

  METHOD save_data.

    FIELD-SYMBOLS:<fs_ldmx> TYPE ztest_demo_mx.

    ms_header-zlch_date = sy-datum.
    ms_header-zlch_user = sy-uname.

    MODIFY ztest_demo_sch FROM ms_header.

*    总建筑面积为0  清空维护数据
    LOOP AT mt_ldmx ASSIGNING <fs_ldmx>.
      IF <fs_ldmx>-zzjzmj IS INITIAL.
        CLEAR:<fs_ldmx>-zreason,<fs_ldmx>-zyjwc,<fs_ldmx>-zsjwc,<fs_ldmx>-zwcmj.
      ENDIF.
      CLEAR:<fs_ldmx>-readonly.
    ENDLOOP.

    MODIFY ztest_demo_mx FROM TABLE mt_ldmx.

  ENDMETHOD.

GET_EXIST_DATA无需参数
对于不同情况:创建,调整,查看 带出数据的代码均有不同
代码:

  METHOD get_exist_data.

    DATA:ls_proj   TYPE          proj,
         lt_prps   TYPE TABLE OF prps,
         ls_prps   TYPE          prps,
         ls_header TYPE          ztest_demo_sch,
         lt_ldmx   TYPE TABLE OF ztest_demo_mx,
         ls_ldmx   TYPE          ztest_demo_mx,
         lt_prhi   TYPE TABLE OF prhi,
         ls_prhi   TYPE          prhi,
         ls_prhi_t TYPE          prhi,
         lv_pspid  TYPE          ps_pspid,
         lv_posnr  TYPE          ps_posnr,
         lv_pspnr  TYPE          ps_psphi.

    FIELD-SYMBOLS:
      <fs_ldmx> TYPE ztest_demo_mx.

*    展示数据
    IF mv_curr_action EQ gc_event_display.

      SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_header
        FROM ztest_demo_sch
        WHERE guid EQ ms_header-guid.
      IF sy-subrc EQ 0.
        MOVE-CORRESPONDING ls_header TO ms_header.
      ENDIF.

      SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_ldmx
        FROM ztest_demo_mx
        WHERE guid_header EQ ms_header-guid.
      IF sy-subrc EQ 0.

        CLEAR mt_ldmx.
        MOVE-CORRESPONDING lt_ldmx TO mt_ldmx.

      ENDIF.

*    创建
    ELSEIF mv_curr_action EQ gc_event_create.

      SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_proj
        FROM proj
      WHERE pspid EQ ms_header-pspid.
      IF sy-subrc EQ 0.

        ms_header-post1 = ls_proj-post1.

      ENDIF.

      CALL FUNCTION 'CONVERSION_EXIT_ABPSN_OUTPUT'
        EXPORTING
          input  = ms_header-pspid
        IMPORTING
          output = lv_pspid.

      CALL FUNCTION 'CONVERSION_EXIT_KONPD_INPUT'
        EXPORTING
          input     = lv_pspid
        IMPORTING
          output    = lv_pspnr
*         PROJWA    =
        EXCEPTIONS
          not_found = 1
          OTHERS    = 2.
      IF sy-subrc <> 0.
* Implement suitable error handling here
      ENDIF.

      SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_prhi
        FROM prhi
        WHERE psphi EQ lv_pspnr.
      IF sy-subrc EQ 0.

        SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_prps
          FROM prps
          FOR ALL ENTRIES IN lt_prhi
          WHERE pspnr EQ lt_prhi-posnr
          AND stufe IN ( 2,3 ).
        IF sy-subrc EQ 0.
          SORT lt_prhi BY posnr ASCENDING.
          LOOP AT lt_prhi INTO ls_prhi WHERE up IS NOT INITIAL
            AND down IS NOT INITIAL.

            READ TABLE lt_prps INTO ls_prps WITH KEY pspnr = ls_prhi-posnr.
            IF sy-subrc EQ 0.

              CLEAR:ls_ldmx.
              ls_ldmx-posid_f = ls_prps-posid.
              ls_ldmx-post1_f = ls_prps-post1.
              LOOP AT lt_prhi INTO ls_prhi_t WHERE up EQ ls_prhi-posnr.

                READ TABLE lt_prps INTO ls_prps WITH KEY pspnr = ls_prhi_t-posnr.
                IF sy-subrc EQ 0.
                  ls_ldmx-posid_l = ls_prps-posid.
                  ls_ldmx-post1_l = ls_prps-post1.
                ENDIF.

                TRY.

                    ls_ldmx-guid = cl_system_uuid=>create_uuid_x16_static( ).

                  CATCH cx_uuid_error .
                ENDTRY.

                ls_ldmx-guid_header = ms_header-guid.
                APPEND ls_ldmx TO lt_ldmx.

              ENDLOOP.

            ENDIF.

          ENDLOOP.

        ENDIF.

      ENDIF.

      IF lt_ldmx IS NOT INITIAL.

        CLEAR:mt_ldmx.
        MOVE-CORRESPONDING lt_ldmx TO mt_ldmx.

      ENDIF.

*    调整数据直接带出上一版数据
    ELSEIF mv_curr_action EQ gc_event_adjust.

      SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_ldmx
        FROM ztest_demo_mx
        WHERE guid_header EQ mv_adjut_guid.
      IF sy-subrc EQ 0.
        LOOP AT lt_ldmx ASSIGNING <fs_ldmx>.

          TRY.

              <fs_ldmx>-guid = cl_system_uuid=>create_uuid_x16_static( ).

            CATCH cx_uuid_error .
          ENDTRY.
          <fs_ldmx>-guid_header = ms_header-guid.

        ENDLOOP.

        CLEAR:mt_ldmx.
        MOVE-CORRESPONDING lt_ldmx TO mt_ldmx.

      ENDIF.

    ENDIF.

  ENDMETHOD.

CHECK_BEFORE_DBSP参数:
在这里插入图片描述
代码:

  METHOD check_before_dbsp.

    DATA:ls_message TYPE fpmgb_s_t100_message.

    cv_result = 'OK'.

    IF ms_header-status NE '4'.

      cv_result = 'FAILED'.
      ls_message-msgid = 'ZTEST'.
      ls_message-msgno = '004'.
      ls_message-severity = 'E'.
      ls_message-parameter_1 = '当前状态不允许单步审批'.
      APPEND ls_message TO ct_messages.

    ENDIF.

  ENDMETHOD.

DOWNLOAD_TEMPLATE下载模板无需代码,但是需要其他处理

  1. 按照如图创建一个EXCEL,对EXCEL全选然后设置单元格式,选择文本,确定
    在这里插入图片描述

  2. SE80 进入资源库,如图路径,右键导入excel
    在这里插入图片描述在这里插入图片描述

  3. 为模板设置一个名字
    在这里插入图片描述

  4. 选择包,测试程序,我放在本地
    在这里插入图片描述

  5. DOWNLOAD_TEMPLATE下载模板方法的代码:

  METHOD download_template.

    DATA:lv_url          TYPE        string,
         lv_mime_file    TYPE        xstring,
         lv_filename     TYPE        string,
         lv_pspid        TYPE        ps_pspid,
         lv_line         TYPE        i,
         ls_ldmx         TYPE        ztest_demo_mx,

         lv_xdocument    TYPE        xstring,
         lo_excel_e      TYPE REF TO zcx_excel,
         lo_excel_reader TYPE REF TO zif_excel_reader,
         lo_excel_writer TYPE REF TO zif_excel_writer,
         lo_excel        TYPE REF TO zcl_excel,
         lo_worksheet    TYPE REF TO zcl_excel_worksheet.

*    EXCEL模板路径
    lv_url = 'SAP/PUBLIC/EXCEL TEMPLATE/ZTEST_DEMO_TEMP.xlsx'.

    cl_mime_repository_api=>get_api( )->get(
    EXPORTING        i_url     = lv_url
    IMPORTING        e_content = lv_mime_file
    EXCEPTIONS OTHERS = 8 ).

    IF sy-subrc <> 0.
      RETURN.
    ELSE.

      CREATE OBJECT lo_excel_reader TYPE zcl_excel_reader_2007.

      TRY.

          lv_line = 1.
          lo_excel = lo_excel_reader->load( i_excel2007 = lv_mime_file ).
          IF sy-subrc EQ 0.
            lo_worksheet = lo_excel->get_worksheet_by_name(
            EXPORTING
              ip_sheet_name = 'Sheet1' ).

            IF mt_ldmx IS NOT INITIAL.

*              循环把数据插入EXCEL
              LOOP AT mt_ldmx INTO ls_ldmx.

                lv_line = lv_line + 1.

*                分期转化为外码
                CALL FUNCTION 'CONVERSION_EXIT_ABPSN_OUTPUT'
                  EXPORTING
                    input  = ls_ldmx-posid_f
                  IMPORTING
                    output = lv_pspid.

                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'A' ip_value = lv_pspid ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'B' ip_value = ls_ldmx-post1_f ip_abap_type = cl_abap_typedescr=>typekind_string ).

*                楼栋转化为代码
                CALL FUNCTION 'CONVERSION_EXIT_ABPSN_OUTPUT'
                  EXPORTING
                    input  = ls_ldmx-posid_l
                  IMPORTING
                    output = lv_pspid.
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'C' ip_value = lv_pspid ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'D' ip_value = ls_ldmx-post1_l ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'E' ip_value = ls_ldmx-zzjzmj ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'F' ip_value = ls_ldmx-zwcmj ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'G' ip_value = ls_ldmx-zyjwc ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'H' ip_value = ls_ldmx-zsjwc ip_abap_type = cl_abap_typedescr=>typekind_string ).
                lo_worksheet->set_cell( ip_row = lv_line ip_column = 'I' ip_value = ls_ldmx-zreason ip_abap_type = cl_abap_typedescr=>typekind_string ).

              ENDLOOP.

            ENDIF.

          ENDIF.

*           导出文件
          CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007.
          lv_xdocument = lo_excel_writer->write_file( lo_excel ).

        CATCH zcx_excel INTO lo_excel_e.
      ENDTRY.

      CALL FUNCTION 'CONVERSION_EXIT_ABPSN_OUTPUT'
        EXPORTING
          input  = ms_header-pspid
        IMPORTING
          output = lv_pspid.

      IF lv_pspid IS NOT INITIAL.

        lv_filename = lv_pspid && 'DEMO明细导出.xlsx'.

      ENDIF.


      cl_wd_runtime_services=>attach_file_to_response(
      i_filename      = lv_filename                         "#EC NOTEXT
*      i_content       = lv_mime_file
      i_content       = lv_xdocument
      i_mime_type     = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      i_in_new_window = abap_false
      i_inplace       = abap_false
      ).
    ENDIF.

  ENDMETHOD.

IF_FPM_GUIBB_FORM_EXT~NEEDS_CONFIRMATION接口代码:

  METHOD if_fpm_guibb_form_ext~needs_confirmation.

    DATA  lo_confirm TYPE REF TO cl_fpm_confirmation_request.
    DATA  lt_confirmation_text TYPE string_table.
    DATA  lv_text TYPE string.

    IF io_event->mv_event_id = gc_event_dbsp.

      lv_text = '确认通过审批?'.
      APPEND lv_text TO  lt_confirmation_text.
      CREATE OBJECT lo_confirm
        EXPORTING
          it_confirmation_text = lt_confirmation_text.
      eo_confirmation_request = lo_confirm.

    ELSEIF io_event->mv_event_id = gc_event_back.

      lv_text = '确认返回搜索页面?'.
      APPEND lv_text TO  lt_confirmation_text.
      CREATE OBJECT lo_confirm
        EXPORTING
          it_confirmation_text = lt_confirmation_text.
      eo_confirmation_request = lo_confirm.

    ENDIF.

  ENDMETHOD.

除了有代码的方法,其他方法直接进入激活可以
完成所有代码后整体激活

二、效果图展示:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


总结

根据实际需求完善逻辑,下一章实现上载数据
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ggreekn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值