2022.05.14 【ABAP随笔】-SAP后台server读取Excel方案的想法
读取Excel方案的研究
我之前在文章(Excel批量导入)中提到过使用CL_XLSX_DOCUMENT来处理excel,此时EXCEL文件被当作多个xml文件来出了,速度和效率上有了很大的提升。 但是需要使用cl_ehfnd_xlsx这个类来得到EXCEL的单元格的值,发现很多客户还在使用ERP ECC6.0 ON HANA 的架构,所以系统里面没有这个类。 我们可以看到这个类是属于该S4的组件
最近得到一个需求就是从SAP服务器上获取某路径的EXCEL文件,需要读取其中的数据进行逻辑处理,处理的方式大多数为后台自动处理处理,因为sap服务器一般是不能够使用MS软件来处理EXCEL文件的,所以我想到了把cl_ehfnd_xlsx其中的逻辑搬运到ECC 6.0系统的想法. 我在查找资料的时候发现网上有以下资料进行借鉴:
XLSX Upload – a unified approach
但是它有个问题就是每次都需要重新写STRANS程序,然后co_sheet_xml=2 和 co_shared_str_xml = 3 固定,我debug下来发现存放内容xml不一定是在2和3的位置,所有有的excel直接退出
我在想能不能搞个通用的class来处理这个后台sever上读取excel数据的问题:
参考S_OOXML_XLSX类我们能够得出答案
废话不多说,下面开始讲解哈 我把读取excel需要用到的类全部从CL_EHFND_XLSX中拆解处理,包括了以下这几个类
同时还包括了3个STRANS:
- ehfnd_exp_xlsx_get_sheet_names
- ehfnd_exp_xlsx_get_strings
- ehfnd_exp_xlsx_read_sheet
我们先来了解下,从MS2007开始,微软采用了支持open xml的格式来管理excelJerry大神的文章也有提到,所以我们将excel扩展名从xlsx改为zip,然后打开
我们可以看出来XLSX文件时多个xml文件组成的,这样我们自然就从处理excel变成了处理XML。其中
- ehfnd_exp_xlsx_get_sheet_names 解析workbook.xml,来获取sheet的name,id,rID
- ehfnd_exp_xlsx_get_strings 解析sharedStrings.xml
- ehfnd_exp_xlsx_read_sheet 解析sheet.xml
调用程序demo
我们可以从前台和后台或许excel文件来进行处理
调用ZCL_TAB_EXCEL类来处理excel,避免了OLE去打开MS应用,速度是非常快的
测试下从前后端读取EXCEL到显示的时间分别为:0.22秒和0.004秒,这是相当快的了
而且读取3条数据是0.226秒,而我把数据扩展到500多条时,花费的时间也就是0.258秒
1 *前后台处理excel call demo.abap 2 *&---------------------------------------------------------------------* 3 *& Report ZTAB_ZHU_XLSX_02 4 *&---------------------------------------------------------------------* 5 *&=====================================================================* 6 *& create date: 20220514 7 *& created by: tab-zhu (微信公众号:tab_jxzhu) 8 *&---------------------------------------------------------------------* 9 REPORT ztab_zhu_xlsx_02. 10 11 *Constants 12 DATA:BEGIN OF ls_data, 13 a TYPE string, 14 b TYPE string, 15 c TYPE string, 16 END OF ls_data. 17 DATA lt_data LIKE STANDARD TABLE OF ls_data. 18 19 *Global data 20 DATA : l_len TYPE sy-tabix. 21 DATA : l_filename TYPE authb-filename. 22 DATA l_subrc TYPE sy-subrc. 23 DATA: l_lines TYPE i. 24 DATA: l_xstring TYPE xstring. 25 DATA: li_e_rcgrepfile_tab TYPE cpt_x255, 26 li_xtab TYPE cpt_x255. 27 DATA lst_rcgrepfile TYPE cps_x255. 28 DATA: l_file_content TYPE xstring. 29 30 DATA:BEGIN OF gt_tab OCCURS 0, 31 a1 TYPE string, 32 a2 TYPE string, 33 a3 TYPE string, 34 END OF gt_tab. 35 DATA e_file_size TYPE drao-orln. 36 DATA e_lines TYPE i. 37 38 SELECTION-SCREEN BEGIN OF BLOCK blk WITH FRAME TITLE TEXT-s01. 39 PARAMETERS:rb_01 RADIOBUTTON GROUP gp1, 40 rb_02 RADIOBUTTON GROUP gp1. 41 42 PARAMETERS:i_file TYPE rlgrap-filename DEFAULT '/usr/sap/S4H/SYS/src/test.xlsx'. 43 SELECTION-SCREEN END OF BLOCK blk. 44 45 AT SELECTION-SCREEN ON VALUE-REQUEST FOR i_file. 46 i_file = cl_openxml_helper=>browse_local_file_open( 47 iv_title = 'Select XLSX File' 48 iv_filename = '' 49 iv_extpattern = 'Excel(*.xlsx)|*.xlsx|All files(*.*)|*.*' ). 50 51 START-OF-SELECTION. 52 53 CASE abap_on. 54 WHEN rb_02. 55 * assign value 56 l_filename = i_file. 57 * check the authority for file 58 CALL FUNCTION 'AUTHORITY_CHECK_DATASET' 59 EXPORTING 60 * PROGRAM = 61 activity = sabc_act_read 62 * Authority Check allows right now only 60 Character 63 filename = l_filename(60) 64 EXCEPTIONS 65 no_authority = 1 66 activity_unknown = 2 67 OTHERS = 3. 68 IF sy-subrc <> 0. 69 RAISE no_permission. 70 ENDIF. 71 72 * read the raw-file from the appl.server 73 CLEAR l_subrc. 74 OPEN DATASET i_file FOR INPUT IN BINARY MODE. 75 l_subrc = sy-subrc. 76 IF sy-subrc <> 0 OR 77 l_subrc <> 0. 78 RAISE open_failed. 79 ENDIF. 80 DO. 81 CLEAR l_len. 82 CLEAR lst_rcgrepfile. 83 READ DATASET i_file INTO lst_rcgrepfile LENGTH l_len. 84 IF sy-subrc <> 0. 85 IF l_len > 0. 86 e_file_size = e_file_size + l_len. 87 APPEND lst_rcgrepfile TO li_e_rcgrepfile_tab. 88 ENDIF. 89 EXIT. 90 ENDIF. 91 CONCATENATE l_file_content lst_rcgrepfile 92 INTO l_file_content IN BYTE MODE. 93 e_file_size = e_file_size + l_len. 94 APPEND lst_rcgrepfile TO li_e_rcgrepfile_tab. 95 ENDDO. 96 IF sy-subrc > 10. 97 RAISE read_error. 98 ENDIF. 99 DESCRIBE TABLE li_e_rcgrepfile_tab LINES e_lines. 100 CLOSE DATASET i_file. 101 IF li_e_rcgrepfile_tab[] IS NOT INITIAL. 102 li_xtab[] = li_e_rcgrepfile_tab[]. 103 ENDIF. 104 *Convert data to xstring 105 cl_scp_change_db=>xtab_to_xstr( EXPORTING im_xtab = li_xtab 106 im_size = l_lines 107 IMPORTING ex_xstring = l_xstring ). 108 109 WHEN rb_01. 110 DATA lv_filename TYPE string. 111 lv_filename = i_file. 112 TRY. 113 l_xstring = cl_openxml_helper=>load_local_file( lv_filename ). "获取excel路径 为 xstring格式 114 CATCH cx_openxml_not_found INTO DATA(openxml_not_found). 115 RETURN. 116 ENDTRY. 117 ENDCASE. 118 119 DATA lo_tab_excel TYPE REF TO zcl_tab_excel. 120 CREATE OBJECT lo_tab_excel. 121 "mo_xlsx_document 122 CALL METHOD lo_tab_excel->load_doc( iv_file_data = l_xstring ). 123 lo_tab_excel->initialize( ). 124 DATA(lo_sheet) = lo_tab_excel->get_sheet_by_name( 'Sheet1' ). 125 DATA(ls_sheet_data) = lo_tab_excel->get_sheet_data( lo_sheet ). 126 "获取第1行列数 (一共几列) 127 DATA(ls_last_columns) = lo_tab_excel->get_last_column_number_in_row( 1 ). 128 "获取行数 129 DATA(ls_last_rows) = lo_tab_excel->get_last_row_number( ). 130 DATA(startrow) = 1. 131 WHILE startrow <= ls_last_rows. 132 CLEAR ls_data. 133 DO ls_last_columns TIMES. 134 DATA(currentcolumn) = sy-index. 135 DATA(lv_content) = lo_tab_excel->get_cell_content( 136 iv_row = startrow 137 iv_column = currentcolumn 138 ). 139 ASSIGN COMPONENT currentcolumn OF STRUCTURE ls_data TO FIELD-SYMBOL(<fs_any>). 140 IF sy-subrc EQ 0. 141 <fs_any> = lv_content. 142 ENDIF. 143 ENDDO. 144 APPEND ls_data TO lt_data. 145 startrow = startrow + 1. 146 ENDWHILE. 147 148 cl_demo_output=>display( lt_data ).