系列文章目录
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下载模板无需代码,但是需要其他处理
-
按照如图创建一个EXCEL,对EXCEL全选然后设置单元格式,选择文本,确定
-
SE80 进入资源库,如图路径,右键导入excel
-
为模板设置一个名字
-
选择包,测试程序,我放在本地
-
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.
除了有代码的方法,其他方法直接进入激活可以
完成所有代码后整体激活
二、效果图展示: