本程序实现了将一个内表表(任何格式的固定内表或动态内表)下载到本地Excel文件(xlsx格式)和将一个基于任何透明表格式的Excel解析到动态内表中的两个功能
REPORT ZUPLOAD. TABLES:dd02l. TABLES sscrfields. DATA g_functxt TYPE smp_dyntxt. DATA: ct_excel_tab TYPE z_tt_ex_tabline. DATA:g_iserror. SELECTION-SCREEN BEGIN OF BLOCK 02 WITH FRAME TITLE text-001 . *以下定义数据导入时的条件 PARAMETERS:p_table TYPE tabname16 OBLIGATORY, p_file LIKE rlgrap-filename. "上载文件 SELECTION-SCREEN END OF BLOCK 02. SELECTION-SCREEN BEGIN OF BLOCK blk4 WITH FRAME TITLE text-002. SELECTION-SCREEN COMMENT 1(79) text-003. SELECTION-SCREEN SKIP. SELECTION-SCREEN COMMENT 1(79) text-004 . SELECTION-SCREEN SKIP. SELECTION-SCREEN COMMENT 1(79) text-005 . SELECTION-SCREEN SKIP. SELECTION-SCREEN COMMENT 1(79) text-006 . SELECTION-SCREEN SKIP. SELECTION-SCREEN COMMENT 1(79) text-007 . SELECTION-SCREEN SKIP. SELECTION-SCREEN COMMENT 1(79) text-008 . SELECTION-SCREEN END OF BLOCK blk4. SELECTION-SCREEN: FUNCTION KEY 1. INITIALIZATION. "定义模板下载按钮 g_functxt-icon_id = icon_xls. g_functxt-quickinfo = '下载模板'. g_functxt-icon_text = '下载特定表模板'. sscrfields-functxt_01 = g_functxt. ***定义地址栏** AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file. PERFORM frm_filename. "定义上载文件F4 AT SELECTION-SCREEN . CASE sscrfields-ucomm. WHEN 'FC01'. PERFORM frm_down_template. ENDCASE. START-OF-SELECTION. PERFORM frm_check. PERFORM frm_upload_data. PERFORM frm_update_table. *&---------------------------------------------------------------------* *& Form FRM_CHECK *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM frm_check . IF p_file IS INITIAL. MESSAGE '请选择一个Excel文件' TYPE 'S' DISPLAY LIKE 'E'. STOP. ENDIF. SELECT SINGLE * FROM dd02l WHERE tabname = p_table. IF sy-subrc NE 0. MESSAGE '表名无效' TYPE 'S' DISPLAY LIKE 'E'. STOP. ENDIF. ENDFORM. " FRM_CHECK *&---------------------------------------------------------------------* *& Form FRM_UPLOAD_DATA *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM frm_upload_data . DATA: lv_len_fname TYPE i , lv_comp_field TYPE char05 , lv_localfile TYPE localfile , lv_cur_row TYPE numc4 . DATA:ls_stru TYPE REF TO cl_abap_structdescr, ls_comp TYPE abap_componentdescr, lt_comp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_comp_tmp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_components_incl TYPE abap_component_tab, l_field_nums TYPE i. ls_stru ?= cl_abap_typedescr=>describe_by_name( p_table ). lt_comp = ls_stru->get_components( ). LOOP AT lt_comp INTO ls_comp . IF ls_comp-as_include EQ abap_true. ls_stru ?= ls_comp-type. lt_components_incl = ls_stru->get_components( ). APPEND LINES OF lt_components_incl TO lt_comp_tmp. ELSE. APPEND ls_comp TO lt_comp_tmp. ENDIF. ENDLOOP. lt_comp = lt_comp_tmp. l_field_nums = lines( lt_comp ). "Check if the file that will be uploaded is an excel file. IF p_file IS NOT INITIAL. lv_localfile = p_file. CALL FUNCTION 'Z_EXCEL_TO_INT_TABLE' EXPORTING filename = lv_localfile i_begin_col = 1 i_begin_row = 2 i_end_col = l_field_nums i_end_row = 100000 TABLES intern = ct_excel_tab EXCEPTIONS inconsistent_parameters = 1 upload_ole = 2 OTHERS = 3. IF sy-subrc <> 0. MESSAGE '读取文件内容失败' TYPE 'S' DISPLAY LIKE 'E'. STOP. ENDIF. ENDIF. IF ct_excel_tab IS INITIAL. MESSAGE '文件内容为空,请检查' TYPE 'S' DISPLAY LIKE 'E'. STOP. ENDIF. ENDFORM. " FRM_UPLOAD_DATA *&---------------------------------------------------------------------* *& Form FRM_UPDATE_TABLE *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* FORM frm_update_table. DATA:lv_cur_row TYPE numc4. FIELD-SYMBOLS: <fs_ex_tabline> TYPE z_s_ex_tabline. DATA : dy_table TYPE REF TO data, wa_line TYPE REF TO data, l_field_nums TYPE i. FIELD-SYMBOLS: <dyn_table> TYPE STANDARD TABLE, <dyn_wa> TYPE any, <field_value> TYPE any. DATA:ls_stru TYPE REF TO cl_abap_structdescr, ls_comp TYPE abap_componentdescr, lt_comp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_comp_tmp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_components_incl TYPE abap_component_tab. ls_stru ?= cl_abap_typedescr=>describe_by_name( p_table ). lt_comp = ls_stru->get_components( ). LOOP AT lt_comp INTO ls_comp . IF ls_comp-as_include EQ abap_true. ls_stru ?= ls_comp-type. lt_components_incl = ls_stru->get_components( ). APPEND LINES OF lt_components_incl TO lt_comp_tmp. ELSE. APPEND ls_comp TO lt_comp_tmp. ENDIF. ENDLOOP. lt_comp = lt_comp_tmp. l_field_nums = lines( lt_comp ). *根据表名创建动态内表,以便接收Excel数据 CREATE DATA dy_table TYPE TABLE OF (p_table). ASSIGN dy_table->* TO <dyn_table>. CREATE DATA wa_line LIKE LINE OF <dyn_table>. ASSIGN wa_line->* TO <dyn_wa>. lv_cur_row = 1. SORT ct_excel_tab BY row col. LOOP AT ct_excel_tab ASSIGNING <fs_ex_tabline>. ASSIGN COMPONENT <fs_ex_tabline>-col OF STRUCTURE <dyn_wa> TO <field_value>. IF sy-subrc EQ 0. <field_value> = <fs_ex_tabline>-value. ENDIF. * IF <fs_ex_tabline>-col = l_field_nums. * APPEND <dyn_wa> TO <dyn_table>. * CLEAR <dyn_wa>. * ENDIF. AT END OF ROW. APPEND <dyn_wa> TO <dyn_table>. CLEAR <dyn_wa>. ENDAT. ENDLOOP. MODIFY (p_table) FROM TABLE <dyn_table>. IF sy-subrc EQ 0. COMMIT WORK. MESSAGE '上载成功,请人工检查导入结果' TYPE 'S'. ELSE. ROLLBACK WORK. MESSAGE '上载失败,请联系管理员' TYPE 'S' DISPLAY LIKE 'E'. ENDIF. ENDFORM. "FRM_UPDATE_TABLE *&---------------------------------------------------------------------* *& Form FRM_FILENAME *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM frm_filename . CALL FUNCTION 'WS_FILENAME_GET' EXPORTING mask = ',Excel,*.XLSX;*.XLS.' IMPORTING filename = p_file EXCEPTIONS inv_winsys = 1 no_batch = 2 selection_cancel = 3 selection_error = 4 OTHERS = 5. IF sy-subrc <> 0. * IF sy-subrc <> 0 AND sy-subrc <> 3. * MESSAGE '选择文件出错' TYPE 'S' DISPLAY LIKE 'E'. * EXIT. MESSAGE '取消选择' TYPE 'S'."取消操作 ENDIF. ENDFORM. " FRM_FILENAME *&---------------------------------------------------------------------* *& Form FRM_DOWN_TEMPLATE *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * --> p1 text * <-- p2 text *----------------------------------------------------------------------* FORM frm_down_template . DATA:l_xstring TYPE xstring. DATA:ls_stru TYPE REF TO cl_abap_structdescr, ls_comp TYPE abap_componentdescr, lt_comp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_comp_tmp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_components_incl TYPE abap_component_tab, l_tabix TYPE sy-tabix. DATA : dy_table TYPE REF TO data. DATA:l_field_desc TYPE string, lt_ddic_info TYPE ddfields, l_dfies TYPE dfies, lo_elem_descr TYPE REF TO cl_abap_elemdescr. DATA:lt_column TYPE if_fdt_doc_spreadsheet=>t_column. DATA: ls_column TYPE LINE OF if_fdt_doc_spreadsheet=>t_column. FIELD-SYMBOLS:<l_column> TYPE LINE OF if_fdt_doc_spreadsheet=>t_column. IF p_table IS INITIAL. MESSAGE '请先输入表名' TYPE 'S' DISPLAY LIKE 'E'. EXIT. ENDIF. SELECT SINGLE * FROM dd02l WHERE tabname = p_table. IF sy-subrc NE 0. MESSAGE '表名无效' TYPE 'S' DISPLAY LIKE 'E'. EXIT. ENDIF. ls_stru ?= cl_abap_typedescr=>describe_by_name( p_table ). lt_comp = ls_stru->get_components( ). *组件可能含有include structure,需翻译到底层 LOOP AT lt_comp INTO ls_comp . IF ls_comp-as_include EQ abap_true. ls_stru ?= ls_comp-type. lt_components_incl = ls_stru->get_components( ). APPEND LINES OF lt_components_incl TO lt_comp_tmp. ELSE. APPEND ls_comp TO lt_comp_tmp. ENDIF. ENDLOOP. * PERFORM frm_get_components_recursive TABLES lt_comp. lt_comp = lt_comp_tmp. CREATE DATA dy_table TYPE TABLE OF (p_table). LOOP AT lt_comp INTO ls_comp. lo_elem_descr ?= ls_comp-type. lo_elem_descr->get_ddic_field( * EXPORTING * p_langu = SY-LANGU RECEIVING p_flddescr = l_dfies EXCEPTIONS not_found = 1 no_ddic_type = 2 OTHERS = 3 ). IF sy-subrc <> 0. * MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno * WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. APPEND INITIAL LINE TO lt_column ASSIGNING <l_column>. IF <l_column> IS ASSIGNED. MOVE: sy-tabix TO <l_column>-id, ls_comp-name TO <l_column>-name, l_dfies-fieldtext TO <l_column>-display_name, abap_true TO <l_column>-is_result, ls_comp-type TO <l_column>-type. ENDIF. ENDLOOP. cl_fdt_xl_spreadsheet=>if_fdt_doc_spreadsheet~create_document( EXPORTING itab = dy_table iv_call_type = 2 * is_dt_excel = abap_false columns = lt_column * IV_SHEET_NAME = 'TEST' RECEIVING xdocument = l_xstring ). PERFORM from_save_on_frontend USING l_xstring. ENDFORM. " FRM_DOWN_TEMPLATE *&---------------------------------------------------------------------* *& Form FROM_save_on_frontend *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_XSTRING text *----------------------------------------------------------------------* FORM from_save_on_frontend USING p_xstring TYPE xstring. DATA: lv_file_tab TYPE STANDARD TABLE OF solisti1, lw_file_tab TYPE solisti1, lv_bytecount TYPE i, l_string TYPE string, l_xstring TYPE xstring. DATA: l_fpath TYPE string. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = p_xstring IMPORTING output_length = lv_bytecount TABLES binary_tab = lv_file_tab. "Save the file PERFORM frm_get_temp_dir CHANGING l_fpath. IF l_fpath IS NOT INITIAL. cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount filename = l_fpath filetype = 'BIN' CHANGING data_tab = lv_file_tab ). IF sy-subrc NE 0. * r_subrc = sy-subrc. ENDIF. ELSE. * r_subrc = 2. ENDIF. ENDFORM. "FROM_save_on_frontend *&---------------------------------------------------------------------* *& Form FRM_get_temp_dir *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_PATH text *----------------------------------------------------------------------* FORM frm_get_temp_dir CHANGING p_path. DATA: l_wtitle TYPE string. DATA: l_name TYPE string. DATA: l_fpath TYPE string. DATA tempdir TYPE string . l_wtitle = '选择文件路径'. cl_gui_frontend_services=>file_save_dialog( EXPORTING window_title = l_wtitle default_extension = 'xlsx' file_filter = 'xlsx' CHANGING filename = l_name path = tempdir fullpath = l_fpath ). cl_gui_cfw=>flush( ). p_path = l_fpath. ENDFORM. "FRM_get_temp_dir *&---------------------------------------------------------------------* *& Form frm_get_components_recursive *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->IT_COMPONENTS text * -->ABAP_COMPONENTDESCR text *----------------------------------------------------------------------* FORM frm_get_components_recursive TABLES it_components TYPE STANDARD TABLE. DATA:ls_stru TYPE REF TO cl_abap_structdescr, ls_comp TYPE abap_componentdescr, lt_comp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_comp_tmp TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, lt_components_incl TYPE abap_component_tab. lt_comp = it_components. *组件可能含有include structure,需翻译到底层 LOOP AT lt_comp INTO ls_comp . IF ls_comp-as_include EQ abap_true. ls_stru ?= ls_comp-type. lt_components_incl = ls_stru->get_components( ). PERFORM frm_get_components_recursive TABLES lt_components_incl. APPEND LINES OF lt_components_incl TO lt_comp_tmp. ELSE. APPEND ls_comp TO lt_comp_tmp. ENDIF. ENDLOOP. it_components = lt_comp_tmp. ENDFORM. "frm_get_components_recursive
1 FUNCTION Z_EXCEL_TO_INT_TABLE. 2 *"---------------------------------------------------------------------- 3 *"*"局部接口: 4 *" IMPORTING 5 *" REFERENCE(FILENAME) TYPE RLGRAP-FILENAME 6 *" REFERENCE(I_BEGIN_COL) TYPE I 7 *" REFERENCE(I_BEGIN_ROW) TYPE I 8 *" REFERENCE(I_END_COL) TYPE I 9 *" REFERENCE(I_END_ROW) TYPE I 10 *" TABLES 11 *" INTERN TYPE Z_TT_EX_TABLINE 12 *" EXCEPTIONS 13 *" INCONSISTENT_PARAMETERS 14 *" UPLOAD_OLE 15 *"---------------------------------------------------------------------- 16 DATA: excel_tab TYPE ty_t_sender. 17 DATA: ld_separator TYPE c. 18 DATA: application TYPE ole2_object, 19 workbook TYPE ole2_object, 20 range TYPE ole2_object, 21 worksheet TYPE ole2_object. 22 DATA: h_cell TYPE ole2_object, 23 h_cell1 TYPE ole2_object. 24 DATA: 25 ld_rc TYPE i. 26 27 DEFINE m_message. 28 case sy-subrc. 29 when 0. 30 when 1. 31 message id sy-msgid type sy-msgty number sy-msgno 32 with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 33 when others. raise upload_ole. 34 endcase. 35 END-OF-DEFINITION. 36 37 * check parameters 38 IF i_begin_row > i_end_row. RAISE inconsistent_parameters. ENDIF. 39 IF i_begin_col > i_end_col. RAISE inconsistent_parameters. ENDIF. 40 41 * Get TAB-sign for separation of fields 42 CLASS cl_abap_char_utilities DEFINITION LOAD. 43 ld_separator = cl_abap_char_utilities=>horizontal_tab. 44 45 * open file in Excel 46 IF application-header = space OR application-handle = -1. 47 CREATE OBJECT application 'Excel.Application'. 48 m_message. 49 ENDIF. 50 CALL METHOD OF 51 application 52 'Workbooks' = workbook. 53 m_message. 54 CALL METHOD OF 55 workbook 56 'Open' 57 58 EXPORTING 59 #1 = filename. 60 m_message. 61 62 * set property of application 'Visible' = 1. 63 * m_message. 64 GET PROPERTY OF application 'ACTIVESHEET' = worksheet. 65 m_message. 66 67 * mark whole spread sheet 68 CALL METHOD OF 69 worksheet 70 'Cells' = h_cell 71 EXPORTING 72 #1 = i_begin_row 73 #2 = i_begin_col. 74 m_message. 75 CALL METHOD OF 76 worksheet 77 'Cells' = h_cell1 78 EXPORTING 79 #1 = i_end_row 80 #2 = i_end_col. 81 m_message. 82 83 CALL METHOD OF 84 worksheet 85 'RANGE' = range 86 EXPORTING 87 #1 = h_cell 88 #2 = h_cell1. 89 m_message. 90 CALL METHOD OF 91 range 92 'SELECT'. 93 m_message. 94 95 * copy marked area (whole spread sheet) into Clippboard 96 CALL METHOD OF 97 range 98 'COPY'. 99 m_message. 100 101 * read clipboard into ABAP 102 CALL METHOD cl_gui_frontend_services=>clipboard_import 103 IMPORTING 104 data = excel_tab 105 EXCEPTIONS 106 cntl_error = 1 107 * ERROR_NO_GUI = 2 108 * NOT_SUPPORTED_BY_GUI = 3 109 OTHERS = 4. 110 IF sy-subrc <> 0. 111 RAISE upload_ole. 112 ENDIF. 113 114 PERFORM separated_to_intern_convert TABLES excel_tab intern 115 USING ld_separator. 116 117 * clear clipboard 118 REFRESH excel_tab. 119 CALL METHOD cl_gui_frontend_services=>clipboard_export 120 IMPORTING 121 data = excel_tab 122 CHANGING 123 rc = ld_rc 124 EXCEPTIONS 125 cntl_error = 1 126 * ERROR_NO_GUI = 2 127 * NOT_SUPPORTED_BY_GUI = 3 128 OTHERS = 4. 129 130 * quit Excel and free ABAP Object - unfortunately, this does not kill 131 * the Excel process 132 CALL METHOD OF 133 application 134 'QUIT'. 135 m_message. 136 137 * >>>>> Begin of change note 575877 138 * to kill the Excel process it's necessary to free all used objects 139 FREE OBJECT h_cell. m_message. 140 FREE OBJECT h_cell1. m_message. 141 FREE OBJECT range. m_message. 142 FREE OBJECT worksheet. m_message. 143 FREE OBJECT workbook. m_message. 144 FREE OBJECT application. m_message. 145 * <<<<< End of change note 575877 146 147 ENDFUNCTION. 148 149 *&---------------------------------------------------------------------* 150 *& Form SEPARATED_TO_INTERN_CONVERT 151 *&---------------------------------------------------------------------* 152 FORM separated_to_intern_convert TABLES i_tab TYPE ty_t_sender 153 i_intern TYPE ty_t_itab 154 USING i_separator TYPE c. 155 DATA: l_sic_tabix LIKE sy-tabix, 156 l_sic_col TYPE kcd_ex_col. 157 DATA: l_fdpos LIKE sy-fdpos. 158 159 REFRESH i_intern. 160 161 LOOP AT i_tab. 162 l_sic_tabix = sy-tabix. 163 l_sic_col = 0. 164 WHILE i_tab CA i_separator. 165 l_fdpos = sy-fdpos. 166 l_sic_col = l_sic_col + 1. 167 PERFORM line_to_cell_separat TABLES i_intern 168 USING i_tab l_sic_tabix l_sic_col 169 i_separator l_fdpos. 170 ENDWHILE. 171 IF i_tab <> space. 172 CLEAR i_intern. 173 i_intern-row = l_sic_tabix. 174 i_intern-col = l_sic_col + 1. 175 i_intern-value = i_tab. 176 APPEND i_intern. 177 ENDIF. 178 ENDLOOP. 179 ENDFORM. " SEPARATED_TO_INTERN_CONVERT 180 181 *&---------------------------------------------------------------------* 182 *& Form line_to_cell_separat 183 *&---------------------------------------------------------------------* 184 FORM line_to_cell_separat TABLES i_intern TYPE ty_t_itab 185 USING i_line 186 i_row LIKE sy-tabix 187 ch_cell_col TYPE kcd_ex_col 188 i_separator TYPE c 189 i_fdpos LIKE sy-fdpos. 190 DATA: l_string TYPE ty_s_senderline. 191 DATA l_sic_int TYPE i. 192 193 CLEAR i_intern. 194 l_sic_int = i_fdpos. 195 i_intern-row = i_row. 196 l_string = i_line. 197 i_intern-col = ch_cell_col. 198 IF ( i_separator = ';' OR i_separator = ',' ) AND 199 l_string(1) = gc_esc. 200 PERFORM line_to_cell_esc_sep USING l_string 201 l_sic_int 202 i_separator 203 i_intern-value. 204 ELSE. 205 IF l_sic_int > 0. 206 i_intern-value = i_line(l_sic_int). 207 ENDIF. 208 ENDIF. 209 IF l_sic_int > 0. 210 APPEND i_intern. 211 ENDIF. 212 l_sic_int = l_sic_int + 1. 213 i_line = i_line+l_sic_int. 214 ENDFORM. "line_to_cell_separat 215 216 *---------------------------------------------------------------------* 217 FORM line_to_cell_esc_sep USING i_string 218 i_sic_int TYPE i 219 i_separator TYPE c 220 i_intern_value TYPE ty_d_itabvalue. 221 DATA: l_int TYPE i, 222 l_cell_end(2). 223 FIELD-SYMBOLS: <l_cell>. 224 l_cell_end = gc_esc. 225 l_cell_end+1 = i_separator . 226 227 IF i_string CS gc_esc. 228 i_string = i_string+1. 229 IF i_string CS l_cell_end. 230 l_int = sy-fdpos. 231 ASSIGN i_string(l_int) TO <l_cell>. 232 i_intern_value = <l_cell>. 233 l_int = l_int + 2. 234 i_sic_int = l_int. 235 i_string = i_string+l_int. 236 ELSEIF i_string CS gc_esc. 237 l_int = sy-fdpos. 238 ASSIGN i_string(l_int) TO <l_cell>. 239 i_intern_value = <l_cell>. 240 l_int = l_int + 1. 241 i_sic_int = l_int. 242 i_string = i_string+l_int. 243 l_int = strlen( i_string ). 244 ENDIF. 245 ENDIF. 246 247 ENDFORM. "line_to_cell_esc_sep
上图为Excel单元格结构内表