系列文章目录
SAP之FPM卷一:FPM是什么
SAP之FPM卷二:FPM开发实例-创建WDA应用
SAP之FPM卷三:FPM开发实例-设想需求与优化
SAP之FPM卷四:FPM开发实例- 创建程序所需表,结构并完成搜索页面主要代码
SAP之FPM卷五:FPM开发实例-完成主页面功能(1)
SAP之FPM卷六:FPM开发实例-完成主页面功能(2)
前言
本篇实现通过EXCEL上载数据的功能
一、创建所需结构
均为预定义类型
保存激活
二、实现类
新创建一个类(CLASS)ZCL_TEST_DEMO_UPLOAD,引入两个接口
IF_FPM_GUIBB
IF_FPM_GUIBB_FORM
添加两个属性,MS_DATA为刚创建的结构
IF_FPM_GUIBB~INITIALIZE代码:
METHOD if_fpm_guibb~initialize.
CHECK io_app_parameter IS BOUND.
io_app_parameter->get_value(
EXPORTING
iv_key = 'STUC_NAME'
IMPORTING
ev_value = mv_stuc_name
).
ENDMETHOD.
IF_FPM_GUIBB_FORM~GET_DEFINITION代码:
METHOD if_fpm_guibb_form~get_definition.
DATA:
ls_field_description TYPE fpmgb_s_formfield_descr.
eo_field_catalog ?= cl_abap_structdescr=>describe_by_name( 'ZTEST_S_DEMO_UPSEL' ).
ls_field_description-name = 'DATA'.
ls_field_description-file_name_ref = 'FILENAME'.
ls_field_description-mime_type_ref = 'MIMETYPE'.
APPEND ls_field_description TO et_field_description.
CLEAR ls_field_description.
ls_field_description-name = 'FILENAME'.
ls_field_description-technical_field = abap_true.
APPEND ls_field_description TO et_field_description.
CLEAR ls_field_description.
ls_field_description-name = 'MIMETYPE'.
ls_field_description-technical_field = abap_true.
APPEND ls_field_description TO et_field_description.
CLEAR ls_field_description.
ENDMETHOD.
IF_FPM_GUIBB_FORM~PROCESS_EVENT代码:
METHOD if_fpm_guibb_form~process_event.
DATA:
lt_value_list TYPE wdr_context_attr_value_list,
ls_value TYPE wdr_context_attr_value,
lo_event TYPE REF TO cl_fpm_event,
lo_fpm TYPE REF TO if_fpm,
lv_line TYPE i,
lv_con TYPE i,
lv_con_t TYPE i,
lv_action(10),
lo_excel_core TYPE REF TO cx_fdt_excel_core,
lo_excel TYPE REF TO cl_fdt_xl_spreadsheet,
lt_worksheets TYPE STANDARD TABLE OF string,
lv_ws_name TYPE string,
lo_data TYPE REF TO data,
lv_xstring TYPE xstring,
lv_str TYPE string,
lv_subrc TYPE sy-subrc,
ls_upload TYPE REF TO data,
lt_upload TYPE REF TO data,
lt_temp_data TYPE REF TO data.
DATA:
ls_component TYPE abap_compdescr,
lo_structdescr TYPE REF TO cl_abap_structdescr.
FIELD-SYMBOLS:
<ft_table> TYPE ANY TABLE,
<ft_upload> TYPE ANY TABLE,
<fs_upload> TYPE any,
<fs_data> TYPE ztest_s_demo_upsel,
<fs_struc> TYPE any,
<fs_temp> TYPE any,
<fs_value> TYPE any.
DATA:lv_any TYPE n.
CASE io_event->mv_event_id.
WHEN cl_fpm_event=>gc_event_close_dialog_box.
CALL METHOD io_event->mo_event_data->get_value
EXPORTING
iv_key = 'DIALOG_BUTTON_ACTION'
IMPORTING
ev_value = lv_action.
CHECK lv_action = 'OK'.
ASSIGN ms_data TO <fs_data>.
CHECK <fs_data> IS ASSIGNED.
lv_xstring = <fs_data>-data.
TRY.
CREATE OBJECT lo_excel
EXPORTING
document_name = <fs_data>-filename
xdocument = lv_xstring.
CATCH cx_fdt_excel_core INTO lo_excel_core.
RETURN.
ENDTRY.
CHECK lo_excel IS BOUND.
CALL METHOD lo_excel->if_fdt_doc_spreadsheet~get_worksheet_names
IMPORTING
worksheet_names = lt_worksheets.
CHECK lt_worksheets IS NOT INITIAL.
TRY .
READ TABLE lt_worksheets INDEX 1 INTO lv_ws_name.
lo_data = lo_excel->if_fdt_doc_spreadsheet~get_itab_from_worksheet(
lv_ws_name ).
CHECK lo_data IS BOUND .
ASSIGN lo_data->* TO <ft_table>.
CHECK <ft_table> IS ASSIGNED.
lo_structdescr ?= cl_abap_structdescr=>describe_by_name( mv_stuc_name ).
DESCRIBE TABLE lo_structdescr->components LINES lv_line.
* 减去未在excel中出现字段的次数
IF mv_stuc_name EQ 'ZTEST_DEMO_MX'.
lv_line = lv_line - 5.
ENDIF.
CREATE DATA lt_upload TYPE TABLE OF (mv_stuc_name).
ASSIGN lt_upload->* TO <ft_upload>.
LOOP AT <ft_table> ASSIGNING <fs_struc>.
CHECK <fs_struc> IS ASSIGNED.
IF sy-tabix < 2. "过滤抬头
CONTINUE.
ENDIF.
CREATE DATA ls_upload TYPE (mv_stuc_name).
ASSIGN ls_upload->* TO <fs_upload>.
DO lv_line TIMES.
lv_con = lv_con + 1.
ASSIGN COMPONENT lv_con OF STRUCTURE <fs_struc> TO <fs_temp>.
* 由于底表与excel中结构不一致需要调整一致
* 也可以新创建结构与excel 中保持一致 这里就不需要调整lv_con
IF mv_stuc_name EQ 'ZTEST_DEMO_MX'.
lv_con_t = lv_con + 3.
ELSE.
lv_con_t = lv_con.
ENDIF.
READ TABLE lo_structdescr->components INTO ls_component INDEX lv_con_t.
IF sy-subrc = 0.
ASSIGN COMPONENT ls_component-name OF STRUCTURE <fs_upload> TO <fs_value>.
IF <fs_temp> IS ASSIGNED.
IF mv_stuc_name EQ 'ZTEST_DEMO_MX'.
CASE ls_component-name . "对于特定字段,单独处理
WHEN 'MANDT'.
WHEN 'GUID'.
WHEN 'GUID_HEADER'.
WHEN 'POSID_F'.
WHEN 'POST1_F'.
WHEN 'POSID_L'.
WHEN 'POST1_L'.
WHEN 'AREA_UNT'.
WHEN 'READONLY'.
WHEN OTHERS.
* <fs_value> = <fs_temp>.
lv_str = <fs_temp>.
lv_subrc = 0.
* 去除特殊字符
DO 10 TIMES.
REPLACE '-' INTO lv_str WITH ``.
SEARCH lv_str FOR '-'.
IF sy-subrc <> 0.
EXIT.
ENDIF.
ENDDO.
DO 10 TIMES.
REPLACE '/' INTO lv_str WITH ``.
SEARCH lv_str FOR '/'.
IF sy-subrc <> 0.
EXIT.
ENDIF.
ENDDO.
* DO 10 TIMES.
* REPLACE '.' INTO lv_str WITH ``.
* SEARCH lv_str FOR '.'.
* IF sy-subrc <> 0.
* EXIT.
* ENDIF.
* ENDDO.
<fs_value> = lv_str.
ENDCASE.
ENDIF.
ENDIF.
ENDIF.
ENDDO.
INSERT <fs_upload> INTO TABLE <ft_upload> .
CLEAR: ls_upload,lv_con,<fs_upload>.",lv_msgflag,lv_msginfo.
ENDLOOP.
CHECK lt_upload IS BOUND AND lt_worksheets IS NOT INITIAL.
CREATE OBJECT lo_event
EXPORTING
iv_event_id = 'GET_UPLOAD_DATA'.
lo_event->mo_event_data->set_value(
iv_key = 'UPLOAD_DATA'
ir_value = lt_upload ).
IF lo_fpm IS INITIAL.
lo_fpm ?= cl_fpm=>get_instance( ).
ENDIF.
lo_fpm->raise_event( io_event = lo_event ).
CATCH cx_sy_conversion_error.
ENDTRY.
ENDCASE.
ENDMETHOD.
IF_FPM_GUIBB_FORM~FLUSH代码:
METHOD if_fpm_guibb_form~flush.
FIELD-SYMBOLS: <fs_data> TYPE zteste_s_demo_upsel.
IF it_change_log IS NOT INITIAL.
ASSIGN is_data->* TO <fs_data>.
ms_data = <fs_data>.
ENDIF.
ENDMETHOD.
其他方法直接激活即可
三、创建组件:
- 在程序工作台新建对话框
2. 页面标识改名为UPLOAD_DATA,添加一个表单组件
3. 为组件取名ZTEST_WDCC_SCH_DEMO_UPLOAD,保存
4. 点扳手或配置UIBB
5. 新建,加描述,选择包,然后填入刚才创建的类
6. 添加元素DATA,设置显示类型为文件上载
7. 改名保存
- 在类ZCL_TEST_DEMO_MAIN_LIST~GET_DATA添加处理方法
IF_FPM_GUIBB_LIST~GET_DATA CASE新增获取上载数据代码:
WHEN gc_event_upload." 'GET_UPLOAD_DATA'.
CALL METHOD get_upload_data
EXPORTING
iv_event = iv_eventid
CHANGING
ct_messages = et_messages.
添加属性:
上载方法GET_UPLOAD_DATA参数:
IF_FPM_GUIBB_LIST~PROCESS_EVENT用以下代码替换激活:
METHOD if_fpm_guibb_list~process_event.
DATA:
ls_dialog_box_properties TYPE fpm_s_dialog_box_properties.
CASE io_event->mv_event_id.
* WHEN gc_event_edit. "编辑
WHEN gc_upload_data.
mo_fpm->mo_app_parameter->set_value(
iv_key = 'STUC_NAME'
iv_value = 'ZTEST_DEMO_MX'
).
ls_dialog_box_properties-width = '800'.
ls_dialog_box_properties-button_set = '3'.
CALL METHOD mo_fpm->open_dialog_box
EXPORTING
iv_dialog_box_id = 'UPLOAD_DATA'
is_dialog_box_properties = ls_dialog_box_properties
io_event_data = mo_fpm->mo_app_parameter.
WHEN gc_download_temp. "下载模板
CALL METHOD me->download_template( ).
WHEN OTHERS.
ENDCASE.
ENDMETHOD.
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.
GET_UPLOAD_DATA 方法代码:
METHOD get_upload_data.
DATA:
lv_tabix LIKE sy-tabix,
lr_upload TYPE REF TO data.
FIELD-SYMBOLS:
<fs_data_upload> TYPE any,
<fv_value> TYPE any,
<fs_ldmx> TYPE ztest_demo_mx,
<ft_data_upload> TYPE ANY TABLE.
CALL METHOD iv_event->mo_event_data->get_value
EXPORTING
iv_key = 'UPLOAD_DATA'
IMPORTING
er_value = lr_upload.
ASSIGN lr_upload->* TO <ft_data_upload>.
CHECK <ft_data_upload> IS ASSIGNED.
LOOP AT <ft_data_upload> ASSIGNING <fs_data_upload>.
lv_tabix = sy-tabix.
READ TABLE mt_ldmx ASSIGNING <fs_ldmx> INDEX lv_tabix.
IF sy-subrc EQ 0.
ASSIGN COMPONENT 'ZZJZMJ' OF STRUCTURE <fs_data_upload> TO <fv_value>.
IF sy-subrc EQ 0.
<fs_ldmx>-zzjzmj = <fv_value>.
ENDIF.
ASSIGN COMPONENT 'ZWCMJ' OF STRUCTURE <fs_data_upload> TO <fv_value>.
IF sy-subrc EQ 0.
<fs_ldmx>-zwcmj = <fv_value>.
ENDIF.
ASSIGN COMPONENT 'ZYJWC' OF STRUCTURE <fs_data_upload> TO <fv_value>.
IF sy-subrc EQ 0.
<fs_ldmx>-zyjwc = <fv_value>.
ENDIF.
ASSIGN COMPONENT 'ZSJWC' OF STRUCTURE <fs_data_upload> TO <fv_value>.
IF sy-subrc EQ 0.
<fs_ldmx>-zsjwc = <fv_value>.
ENDIF.
ASSIGN COMPONENT 'ZREASON' OF STRUCTURE <fs_data_upload> TO <fv_value>.
IF sy-subrc EQ 0.
<fs_ldmx>-zreason = <fv_value>.
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
四、效果展示
点击上载数据
选择文件(文件是通过下载模板按钮保存到本地的,一开始是空的,这里随便维护一些测试数据)
文件内内容
点击确定后:
现在的看到的效果已经很显著了
总结
纯FPM简单的开发例子已经实现,从卷三到这里都是有完整代码的,有问题也可以评论区讨论。
谢谢观看本系列文章,下一个系列是FBI( BOBF+FPM )