CLASS zcl_excel_ole DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. TYPES ty_doc_url TYPE c LENGTH 255. CLASS-METHODS bind_alv_ole2 IMPORTING !i_document_url TYPE ty_doc_url DEFAULT space !i_xls TYPE c DEFAULT space !i_save_path TYPE string !io_alv TYPE REF TO cl_gui_alv_grid !it_listheader TYPE slis_t_listheader OPTIONAL !i_top TYPE i DEFAULT 1 !i_left TYPE i DEFAULT 1 !i_columns_header TYPE c DEFAULT 'X' !i_columns_autofit TYPE c DEFAULT 'X' !i_format_col_header TYPE soi_format_item OPTIONAL !i_format_subtotal TYPE soi_format_item OPTIONAL !i_format_total TYPE soi_format_item OPTIONAL EXCEPTIONS miss_guide ex_transfer_kkblo_error fatal_error inv_data_range dim_mismatch_vkey dim_mismatch_sema error_in_sema . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_excel_ole IMPLEMENTATION. METHOD bind_alv_ole2. *--------------------------------------------------------------------* * Method description: * Method use to export a CL_GUI_ALV_GRID object to xlsx/xls file * with list header and characteristics of ALV field catalog such as: * + Total, group's subtotal * + Quantity fields, amount fields (dependent fields) * + No_out, no_zero, ... * Technique use in method: * SAP Desktop Office Integration (DOI) *--------------------------------------------------------------------* * Data for session 0: DOI constructor * ------------------------------------------ DATA: lo_control TYPE REF TO i_oi_container_control. DATA: lo_proxy TYPE REF TO i_oi_document_proxy. DATA: lo_spreadsheet TYPE REF TO i_oi_spreadsheet. DATA: lo_error TYPE REF TO i_oi_error. DATA: lc_retcode TYPE soi_ret_string. DATA: li_has TYPE i. "Proxy has spreadsheet interface? DATA: l_is_closed TYPE i. * Data for session 1: Get LVC data from ALV object * ------------------------------------------ DATA: l_has_activex, l_doctype_excel_sheet(11) TYPE c. * LVC DATA: lt_fieldcat_lvc TYPE lvc_t_fcat. DATA: wa_fieldcat_lvc TYPE lvc_s_fcat. DATA: lt_sort_lvc TYPE lvc_t_sort. DATA: lt_filter_idx_lvc TYPE lvc_t_fidx. DATA: lt_grouplevels_lvc TYPE lvc_t_grpl. * KKBLO DATA: lt_fieldcat_kkblo TYPE kkblo_t_fieldcat. DATA: lt_sort_kkblo TYPE kkblo_t_sortinfo. DATA: lt_grouplevels_kkblo TYPE kkblo_t_grouplevels. DATA: lt_filter_idx_kkblo TYPE kkblo_t_sfinfo. DATA: wa_listheader LIKE LINE OF it_listheader. * Subtotal DATA: lt_collect00 TYPE REF TO data. DATA: lt_collect01 TYPE REF TO data. DATA: lt_collect02 TYPE REF TO data. DATA: lt_collect03 TYPE REF TO data. DATA: lt_collect04 TYPE REF TO data. DATA: lt_collect05 TYPE REF TO data. DATA: lt_collect06 TYPE REF TO data. DATA: lt_collect07 TYPE REF TO data. DATA: lt_collect08 TYPE REF TO data. DATA: lt_collect09 TYPE REF TO data. * data table name DATA: l_tabname TYPE kkblo_tabname. * local object DATA: lo_grid TYPE REF TO lcl_gui_alv_grid. * data table get from ALV DATA: lt_alv TYPE REF TO data. * total / subtotal data FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE STANDARD TABLE. * table before append subtotal lines FIELD-SYMBOLS: TYPE STANDARD TABLE. * data for session 2: sort, filter and calculate total/subtotal * ------------------------------------------ * table to save index of subotal / total line in excel tanle * this ideal to control index of subtotal / total line later * for ex, when get subtotal / total line to format TYPES: BEGIN OF st_subtot_indexs, index TYPE i, END OF st_subtot_indexs. DATA: lt_subtot_indexs TYPE TABLE OF st_subtot_indexs. DATA: wa_subtot_indexs LIKE LINE OF lt_subtot_indexs. * data table after append subtotal DATA: lt_excel TYPE REF TO data. DATA: l_tabix TYPE i. DATA: l_save_index TYPE i. * dyn subtotal table name DATA: l_collect TYPE string. * subtotal range, to format subtotal (and total) DATA: subranges TYPE soi_range_list. DATA: subrangeitem TYPE soi_range_item. DATA: l_sub_index TYPE i. * table after append subtotal lines FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE any. * dyn subtotal tables FIELD-SYMBOLS: TYPE STANDARD TABLE. FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: LIKE LINE OF lt_filter_idx_kkblo. FIELD-SYMBOLS: LIKE LINE OF lt_fieldcat_kkblo. FIELD-SYMBOLS: LIKE LINE OF lt_grouplevels_kkblo. FIELD-SYMBOLS: TYPE any. * Data for session 3: map data to semantic table * ------------------------------------------ TYPES: BEGIN OF st_column_index, fieldname TYPE kkblo_fieldname, tabname TYPE kkblo_tabname, col LIKE sy-index, END OF st_column_index. * columns index DATA: lt_column_index TYPE TABLE OF st_column_index. DATA: wa_column_index LIKE LINE OF lt_column_index. * table of dependent field ( currency and quantity unit field) DATA: lt_fieldcat_depf TYPE kkblo_t_fieldcat. DATA: wa_fieldcat_depf TYPE kkblo_fieldcat. * XXL interface: * -XXL: contain exporting columns characteristic DATA: lt_sema TYPE TABLE OF gxxlt_s INITIAL SIZE 0. DATA: wa_sema LIKE LINE OF lt_sema. * -XXL interface: header DATA: lt_hkey TYPE TABLE OF gxxlt_h INITIAL SIZE 0. DATA: wa_hkey LIKE LINE OF lt_hkey. * -XXL interface: header keys DATA: lt_vkey TYPE TABLE OF gxxlt_v INITIAL SIZE 0. DATA: wa_vkey LIKE LINE OF lt_vkey. * Number of H Keys: number of key columns DATA: l_n_hrz_keys TYPE i. * Number of data columns in the list object: non-key columns no DATA: l_n_att_cols TYPE i. * Number of V Keys: number of header row DATA: l_n_vrt_keys TYPE i. * curency to format amount DATA: lt_tcurx TYPE TABLE OF tcurx. DATA: wa_tcurx LIKE LINE OF lt_tcurx. DATA: l_def TYPE flag. " currency / quantity flag DATA: wa_t006 TYPE t006. " decimal place of unit DATA: l_num TYPE i. " table columns number DATA: l_typ TYPE c. " table type DATA: wa TYPE REF TO data. DATA: l_int TYPE i. DATA: l_counter TYPE i. FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: TYPE any. * Data for session 4: write to excel * ------------------------------------------ DATA: sema_type TYPE c. DATA l_error TYPE REF TO c_oi_proxy_error. DATA count TYPE i. DATA datac TYPE i. DATA datareal TYPE i. " exporting column number DATA vkeycount TYPE i. DATA all TYPE i. DATA mit TYPE i VALUE 1. " index of recent row? DATA li_col_pos TYPE i VALUE 1. " column position DATA li_col_num TYPE i. " table columns number FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: TYPE any. DATA td TYPE sydes_desc. DATA: typ. DATA: ranges TYPE soi_range_list. DATA: rangeitem TYPE soi_range_item. DATA: contents TYPE soi_generic_table. DATA: contentsitem TYPE soi_generic_item. DATA: semaitem TYPE gxxlt_s. DATA: hkeyitem TYPE gxxlt_h. DATA: vkeyitem TYPE gxxlt_v. DATA: li_commentary_rows TYPE i. "row number of title lines + 1 DATA: lo_error_w TYPE REF TO i_oi_error. DATA: l_retcode TYPE soi_ret_string. DATA: no_flush TYPE c VALUE 'X'. DATA: li_head_top TYPE i. "header rows position * Data for session 5: Save and clode document * ------------------------------------------ DATA: li_document_size TYPE i. DATA: ls_path TYPE rlgrap-filename. * MACRO: Close_document *------------------------------------------- DEFINE close_document. CLEAR: l_is_closed. IF lo_proxy IS NOT INITIAL. * check proxy detroyed adi CALL METHOD lo_proxy->is_destroyed IMPORTING ret_value = l_is_closed. * if dun detroyed yet: close -> release proxy IF l_is_closed IS INITIAL. CALL METHOD lo_proxy->close_document * EXPORTING * do_save = do_save IMPORTING error = lo_error retcode = lc_retcode. ENDIF. CALL METHOD lo_proxy->release_document IMPORTING error = lo_error retcode = lc_retcode. ELSE. lc_retcode = c_oi_errors=>ret_document_not_open. ENDIF. * Detroy control container IF lo_control IS NOT INITIAL. CALL METHOD lo_control->destroy_control. ENDIF. CLEAR: lo_spreadsheet, lo_proxy, lo_control. * free local CLEAR: l_is_closed. END-OF-DEFINITION. * Macro to catch DOI error *------------------------------------------- DEFINE error_doi. IF lc_retcode NE c_oi_errors=>ret_ok. close_document. CALL METHOD lo_error->raise_message EXPORTING type = 'E'. CLEAR: lo_error. ENDIF. END-OF-DEFINITION. *--------------------------------------------------------------------* * SESSION 0: DOI CONSTRUCTOR *--------------------------------------------------------------------* * check active windown CALL FUNCTION 'GUI_HAS_ACTIVEX' IMPORTING return = l_has_activex. IF l_has_activex IS INITIAL. RAISE miss_guide. ENDIF. * Get Container Object of Screen CALL METHOD c_oi_container_control_creator=>get_container_control IMPORTING control = lo_control retcode = lc_retcode. error_doi. * Initialize Container control CALL METHOD lo_control->init_control EXPORTING parent = cl_gui_container=>default_screen r3_application_name = '' inplace_enabled = 'X' no_flush = 'X' register_on_close_event = 'X' register_on_custom_event = 'X' IMPORTING error = lo_error retcode = lc_retcode. error_doi. * Get Proxy Document: * check exist of document proxy, if exist -> close first IF NOT lo_proxy IS INITIAL. close_document. ENDIF. IF i_xls IS NOT INITIAL. * xls format, doctype = soi_doctype_excel97_sheet l_doctype_excel_sheet = 'Excel.Sheet.8'. ELSE. * xlsx format, doctype = soi_doctype_excel_sheet l_doctype_excel_sheet = 'Excel.Sheet'. ENDIF. CALL METHOD lo_control->get_document_proxy EXPORTING document_type = l_doctype_excel_sheet register_container = 'X' IMPORTING document_proxy = lo_proxy error = lo_error retcode = lc_retcode. error_doi. IF i_document_url IS INITIAL. * create new excel document CALL METHOD lo_proxy->create_document EXPORTING create_view_data = 'X' open_inplace = 'X' no_flush = 'X' IMPORTING error = lo_error retcode = lc_retcode. error_doi. ELSE. * Read excel template for i_DOCUMENT_URL * this excel template can be store in local or server CALL METHOD lo_proxy->open_document EXPORTING document_url = i_document_url open_inplace = 'X' no_flush = 'X' IMPORTING error = lo_error retcode = lc_retcode. error_doi. ENDIF. * Check Spreadsheet Interface of Document Proxy CALL METHOD lo_proxy->has_spreadsheet_interface IMPORTING is_available = li_has error = lo_error retcode = lc_retcode. error_doi. * create Spreadsheet object CHECK li_has IS NOT INITIAL. CALL METHOD lo_proxy->get_spreadsheet_interface IMPORTING sheet_interface = lo_spreadsheet error = lo_error retcode = lc_retcode. error_doi. *--------------------------------------------------------------------* * SESSION 1: GET LVC DATA FROM ALV OBJECT *--------------------------------------------------------------------* * data table CREATE OBJECT lo_grid EXPORTING i_parent = cl_gui_container=>screen0. CALL METHOD lo_grid->get_alv_attributes EXPORTING io_grid = io_alv IMPORTING et_table = lt_alv. ASSIGN lt_alv->* TO . * fieldcat CALL METHOD io_alv->get_frontend_fieldcatalog IMPORTING et_fieldcatalog = lt_fieldcat_lvc. * table name LOOP AT lt_fieldcat_lvc INTO wa_fieldcat_lvc WHERE NOT tabname IS INITIAL. l_tabname = wa_fieldcat_lvc-tabname. EXIT. ENDLOOP. IF sy-subrc NE 0. l_tabname = '1'. ENDIF. CLEAR: wa_fieldcat_lvc. * sort table CALL METHOD io_alv->get_sort_criteria IMPORTING et_sort = lt_sort_lvc. * filter index CALL METHOD io_alv->get_filtered_entries IMPORTING et_filtered_entries = lt_filter_idx_lvc. * group level + subtotal CALL METHOD io_alv->get_subtotals IMPORTING ep_collect00 = lt_collect00 ep_collect01 = lt_collect01 ep_collect02 = lt_collect02 ep_collect03 = lt_collect03 ep_collect04 = lt_collect04 ep_collect05 = lt_collect05 ep_collect06 = lt_collect06 ep_collect07 = lt_collect07 ep_collect08 = lt_collect08 ep_collect09 = lt_collect09 et_grouplevels = lt_grouplevels_lvc. ASSIGN lt_collect00->* TO . ASSIGN lt_collect01->* TO . ASSIGN lt_collect02->* TO . ASSIGN lt_collect03->* TO . ASSIGN lt_collect04->* TO . ASSIGN lt_collect05->* TO . ASSIGN lt_collect06->* TO . ASSIGN lt_collect07->* TO . ASSIGN lt_collect08->* TO . ASSIGN lt_collect09->* TO . * transfer to KKBLO struct CALL FUNCTION 'LVC_TRANSFER_TO_KKBLO' EXPORTING it_fieldcat_lvc = lt_fieldcat_lvc it_sort_lvc = lt_sort_lvc it_filter_index_lvc = lt_filter_idx_lvc it_grouplevels_lvc = lt_grouplevels_lvc IMPORTING et_fieldcat_kkblo = lt_fieldcat_kkblo et_sort_kkblo = lt_sort_kkblo et_filtered_entries_kkblo = lt_filter_idx_kkblo et_grouplevels_kkblo = lt_grouplevels_kkblo TABLES it_data = EXCEPTIONS it_data_missing = 1 it_fieldcat_lvc_missing = 2 OTHERS = 3. IF sy-subrc <> 0. RAISE ex_transfer_kkblo_error. ENDIF. CLEAR: wa_fieldcat_lvc, lt_fieldcat_lvc, lt_sort_lvc, lt_filter_idx_lvc, lt_grouplevels_lvc. CLEAR: lo_grid. *--------------------------------------------------------------------* * SESSION 2: SORT, FILTER AND CALCULATE TOTAL / SUBTOTAL *--------------------------------------------------------------------* * append subtotal & total line CREATE DATA lt_excel LIKE . ASSIGN lt_excel->* TO . LOOP AT ASSIGNING . l_save_index = sy-tabix. * filter base on filter index table READ TABLE lt_filter_idx_kkblo ASSIGNING WITH KEY index = l_save_index BINARY SEARCH. IF sy-subrc NE 0. APPEND TO . ENDIF. * append subtotal lines READ TABLE lt_grouplevels_kkblo ASSIGNING WITH KEY index_to = l_save_index BINARY SEARCH. IF sy-subrc = 0. l_tabix = sy-tabix. DO. IF -subtot EQ 'X' AND -hide_level IS INITIAL AND -cindex_from NE 0. * dynamic append subtotal line to excel table base on grouplevel table * ex -level = 1 * then = '' l_collect = -level. CONDENSE l_collect. CONCATENATE '' * '->*' INTO l_collect. ASSIGN (l_collect) TO . * incase there're more than 1 total line of group, at the same level * for example: subtotal of multi currency LOOP AT ASSIGNING . IF sy-tabix BETWEEN -cindex_from AND -cindex_to. APPEND TO . * save subtotal lines index wa_subtot_indexs-index = sy-tabix. APPEND wa_subtot_indexs TO lt_subtot_indexs. * append sub total ranges table for format later ADD 1 TO l_sub_index. subrangeitem-name = l_sub_index. CONDENSE subrangeitem-name. CONCATENATE 'SUBTOT' subrangeitem-name INTO subrangeitem-name. subrangeitem-rows = wa_subtot_indexs-index. subrangeitem-columns = 1. " start col APPEND subrangeitem TO subranges. CLEAR: subrangeitem. ENDIF. ENDLOOP. UNASSIGN: . UNASSIGN: . CLEAR: l_collect. ENDIF. * check next subtotal level of group UNASSIGN: . ADD 1 TO l_tabix. READ TABLE lt_grouplevels_kkblo ASSIGNING INDEX l_tabix. IF sy-subrc NE 0 OR -index_to NE l_save_index. EXIT. ENDIF. UNASSIGN: , . ENDDO. ENDIF. CLEAR: l_tabix, l_save_index. UNASSIGN: , . ENDLOOP. * free local data UNASSIGN: , , , . * append grand total line IF IS ASSIGNED. ASSIGN TO . IF IS NOT INITIAL. LOOP AT ASSIGNING . APPEND TO . * save total line index wa_subtot_indexs-index = sy-tabix. APPEND wa_subtot_indexs TO lt_subtot_indexs. * append grand total range (to format) ADD 1 TO l_sub_index. subrangeitem-name = l_sub_index. CONDENSE subrangeitem-name. CONCATENATE 'TOTAL' subrangeitem-name INTO subrangeitem-name. subrangeitem-rows = wa_subtot_indexs-index. subrangeitem-columns = 1. " start col APPEND subrangeitem TO subranges. ENDLOOP. ENDIF. ENDIF. CLEAR: subrangeitem, lt_sort_kkblo, , , , , , , , , , . UNASSIGN: , , , , , , , , , , , . *--------------------------------------------------------------------* * SESSION 3: MAP DATA TO SEMANTIC TABLE *--------------------------------------------------------------------* * get dependent field field: currency and quantity CREATE DATA wa LIKE LINE OF . ASSIGN wa->* TO . DESCRIBE FIELD TYPE l_typ COMPONENTS l_num. DO l_num TIMES. l_save_index = sy-index. ASSIGN COMPONENT l_save_index OF STRUCTURE TO . IF sy-subrc NE 0. MESSAGE e801(zabap2xlsx) WITH 'FATAL ERROR' RAISING fatal_error. ENDIF. LOOP AT lt_fieldcat_kkblo ASSIGNING WHERE tabname = l_tabname. ASSIGN COMPONENT -fieldname OF STRUCTURE TO . DESCRIBE DISTANCE BETWEEN AND INTO l_int IN BYTE MODE. * append column index * this columns index is of table, not fieldcat IF l_int = 0. wa_column_index-fieldname = -fieldname. wa_column_index-tabname = -tabname. wa_column_index-col = l_save_index. APPEND wa_column_index TO lt_column_index. ENDIF. * append dependent fields (currency and quantity unit) IF -cfieldname IS NOT INITIAL. CLEAR wa_fieldcat_depf. wa_fieldcat_depf-fieldname = -cfieldname. wa_fieldcat_depf-tabname = -ctabname. COLLECT wa_fieldcat_depf INTO lt_fieldcat_depf. ENDIF. IF -qfieldname IS NOT INITIAL. CLEAR wa_fieldcat_depf. wa_fieldcat_depf-fieldname = -qfieldname. wa_fieldcat_depf-tabname = -qtabname. COLLECT wa_fieldcat_depf INTO lt_fieldcat_depf. ENDIF. * rewrite field data type IF -inttype = 'X' AND -datatype(3) = 'INT'. -inttype = 'I'. ENDIF. ENDLOOP. CLEAR: l_save_index. UNASSIGN: . ENDDO. * build semantic tables l_n_hrz_keys = 1. * Get keyfigures LOOP AT lt_fieldcat_kkblo ASSIGNING WHERE tabname = l_tabname AND tech NE 'X' AND no_out NE 'X'. CLEAR wa_sema. CLEAR wa_hkey. * Units belong to keyfigures -> display as str READ TABLE lt_fieldcat_depf INTO wa_fieldcat_depf WITH KEY fieldname = -fieldname tabname = -tabname. IF sy-subrc = 0. wa_sema-col_typ = 'STR'. wa_sema-col_ops = 'DFT'. * Keyfigures ELSE. CASE -datatype. WHEN 'QUAN'. wa_sema-col_typ = 'N03'. IF -no_sum NE 'X'. wa_sema-col_ops = 'ADD'. ELSE. wa_sema-col_ops = 'NOP'. " no dependent field ENDIF. WHEN 'DATS'. wa_sema-col_typ = 'DAT'. wa_sema-col_ops = 'NOP'. WHEN 'CHAR' OR 'UNIT' OR 'CUKY'. " Added fieldformats UNIT and CUKY - dd. 26-10-2012 Wouter Heuvelmans wa_sema-col_typ = 'STR'. wa_sema-col_ops = 'DFT'. " dependent field * incase numeric, ex '00120' -> display as '12' WHEN 'NUMC'. wa_sema-col_typ = 'STR'. wa_sema-col_ops = 'DFT'. WHEN OTHERS. wa_sema-col_typ = 'NUM'. IF -no_sum NE 'X'. wa_sema-col_ops = 'ADD'. ELSE. wa_sema-col_ops = 'NOP'. ENDIF. ENDCASE. ENDIF. l_counter = l_counter + 1. l_n_att_cols = l_n_att_cols + 1. wa_sema-col_no = l_counter. READ TABLE lt_column_index INTO wa_column_index WITH KEY fieldname = -fieldname tabname = -tabname. IF sy-subrc = 0. wa_sema-col_src = wa_column_index-col. ELSE. RAISE fatal_error. ENDIF. * columns index of ref currency field in table IF NOT -cfieldname IS INITIAL. READ TABLE lt_column_index INTO wa_column_index WITH KEY fieldname = -cfieldname tabname = -ctabname. IF sy-subrc = 0. wa_sema-col_cur = wa_column_index-col. ENDIF. * quantities fields * treat as currency when display on excel ELSEIF NOT -qfieldname IS INITIAL. READ TABLE lt_column_index INTO wa_column_index WITH KEY fieldname = -qfieldname tabname = -qtabname. IF sy-subrc = 0. wa_sema-col_cur = wa_column_index-col. ENDIF. ENDIF. * Treat of fixed currency in the fieldcatalog for column DATA: l_num_help(2) TYPE n. IF NOT -currency IS INITIAL. SELECT * FROM tcurx INTO TABLE lt_tcurx. SORT lt_tcurx. READ TABLE lt_tcurx INTO wa_tcurx WITH KEY currkey = -currency. IF sy-subrc = 0. l_num_help = wa_tcurx-currdec. CONCATENATE 'N' l_num_help INTO wa_sema-col_typ. wa_sema-col_cur = sy-tabix * ( -1 ). ENDIF. ENDIF. wa_hkey-col_no = l_n_att_cols. wa_hkey-row_no = l_n_hrz_keys. wa_hkey-col_name = -reptext. APPEND wa_hkey TO lt_hkey. APPEND wa_sema TO lt_sema. ENDLOOP. * free local data CLEAR: lt_column_index, wa_column_index, lt_fieldcat_depf, wa_fieldcat_depf, lt_tcurx, wa_tcurx, l_num, l_typ, wa, l_int, l_counter. UNASSIGN: , , , . *--------------------------------------------------------------------* * SESSION 4: WRITE TO EXCEL *--------------------------------------------------------------------* CLEAR: wa_tcurx. REFRESH: lt_tcurx. * if spreadsheet dun have proxy yet IF li_has IS INITIAL. l_retcode = c_oi_errors=>ret_interface_not_supported. CALL METHOD c_oi_errors=>create_error_for_retcode EXPORTING retcode = l_retcode no_flush = no_flush IMPORTING error = lo_error_w. RETURN. ENDIF. CREATE OBJECT l_error EXPORTING object_name = 'OLE_DOCUMENT_PROXY' method_name = 'get_ranges_names'. CALL METHOD c_oi_errors=>add_error EXPORTING error = l_error. DESCRIBE TABLE lt_sema LINES datareal. DESCRIBE TABLE LINES datac. DESCRIBE TABLE lt_vkey LINES vkeycount. IF datac = 0. RAISE inv_data_range. ENDIF. IF vkeycount NE l_n_vrt_keys. RAISE dim_mismatch_vkey. ENDIF. all = l_n_vrt_keys + l_n_att_cols. IF datareal NE all. RAISE dim_mismatch_sema. ENDIF. DATA: decimal TYPE c. * get decimal separator format ('.', ',', ...) in Office config CALL METHOD lo_proxy->get_application_property EXPORTING property_name = 'INTERNATIONAL' subproperty_name = 'DECIMAL_SEPARATOR' CHANGING retvalue = decimal. DATA date_format TYPE usr01-datfm. SELECT SINGLE datfm FROM usr01 INTO date_format WHERE bname = sy-uname. DATA: comma_elim(4) TYPE c. FIELD-SYMBOLS TYPE any. DATA search_item(4) VALUE ' #'. CONCATENATE ',' decimal '.' decimal INTO comma_elim. DATA help TYPE i. " table (with subtotal) line number help = datac. DATA: rowmax TYPE i VALUE 1. " header row number DATA: columnmax TYPE i VALUE 0. " header columns number LOOP AT lt_hkey INTO hkeyitem. IF hkeyitem-col_no > columnmax. columnmax = hkeyitem-col_no. ENDIF. IF hkeyitem-row_no > rowmax. rowmax = hkeyitem-row_no. ENDIF. ENDLOOP. DATA: hkeycolumns TYPE i. " header columns no hkeycolumns = columnmax. IF hkeycolumns < l_n_att_cols. hkeycolumns = l_n_att_cols. ENDIF. columnmax = 0. LOOP AT lt_vkey INTO vkeyitem. IF vkeyitem-col_no > columnmax. columnmax = vkeyitem-col_no. ENDIF. ENDLOOP. DATA overflow TYPE i VALUE 1. DATA testname(10) TYPE c. DATA temp2 TYPE i. " 1st item row position in excel DATA realmit TYPE i VALUE 1. DATA realoverflow TYPE i VALUE 1. " row index in content CALL METHOD lo_spreadsheet->screen_update EXPORTING updating = ''. CALL METHOD lo_spreadsheet->load_lib. DATA: str(40) TYPE c. " range names of columns range (w/o col header) DATA: rows TYPE i. " row postion of 1st item line in ecxel * calculate row position of data table DESCRIBE TABLE it_listheader LINES li_commentary_rows. * if grid had title, add 1 empy line between title and table IF li_commentary_rows NE 0. ADD 1 TO li_commentary_rows. ENDIF. * add top position of block data li_commentary_rows = li_commentary_rows + i_top - 1. * write header (commentary rows) DATA: li_commentary_row_index TYPE i VALUE 1. DATA: li_content_index TYPE i VALUE 1. DATA: ls_index(10) TYPE c. DATA ls_commentary_range(40) TYPE c VALUE 'TITLE'. DATA: li_font_bold TYPE i. DATA: li_font_italic TYPE i. DATA: li_font_size TYPE i. LOOP AT it_listheader INTO wa_listheader. li_commentary_row_index = i_top + li_content_index - 1. ls_index = li_content_index. CONDENSE ls_index. CONCATENATE ls_commentary_range(5) ls_index INTO ls_commentary_range. CONDENSE ls_commentary_range. * insert title range CALL METHOD lo_spreadsheet->insert_range_dim EXPORTING name = ls_commentary_range top = li_commentary_row_index left = i_left rows = 1 columns = 1 no_flush = no_flush. * format range CASE wa_listheader-typ. WHEN 'H'. "title li_font_size = 16. li_font_bold = 1. li_font_italic = -1. WHEN 'S'. "subtile li_font_size = -1. li_font_bold = 1. li_font_italic = -1. WHEN OTHERS. "'A' comment li_font_size = -1. li_font_bold = -1. li_font_italic = 1. ENDCASE. CALL METHOD lo_spreadsheet->set_font EXPORTING rangename = ls_commentary_range family = '' size = li_font_size bold = li_font_bold italic = li_font_italic align = 0 no_flush = no_flush. * title: range content rangeitem-name = ls_commentary_range. rangeitem-columns = 1. rangeitem-rows = 1. APPEND rangeitem TO ranges. contentsitem-row = li_content_index. contentsitem-column = 1. CONCATENATE wa_listheader-key wa_listheader-info INTO contentsitem-value SEPARATED BY space. CONDENSE contentsitem-value. APPEND contentsitem TO contents. ADD 1 TO li_content_index. CLEAR: rangeitem, contentsitem, ls_index. ENDLOOP. * set range data title CALL METHOD lo_spreadsheet->set_ranges_data EXPORTING ranges = ranges contents = contents no_flush = no_flush. REFRESH: ranges, contents. rows = rowmax + li_commentary_rows + 1. all = date_format. all = all + 3. LOOP AT lt_sema INTO semaitem. IF semaitem-col_typ = 'DAT' OR semaitem-col_typ = 'MON' OR semaitem-col_typ = 'N00' OR semaitem-col_typ = 'N01' OR semaitem-col_typ = 'N02' OR semaitem-col_typ = 'N03' OR semaitem-col_typ = 'PCT' OR semaitem-col_typ = 'STR' OR semaitem-col_typ = 'NUM'. CLEAR str. str = semaitem-col_no. CONDENSE str. CONCATENATE 'DATA' str INTO str. mit = semaitem-col_no. li_col_pos = semaitem-col_no + i_left - 1. * range from data1 to data(n), for each columns of table CALL METHOD lo_spreadsheet->insert_range_dim EXPORTING name = str top = rows left = li_col_pos rows = help columns = 1 no_flush = no_flush. DATA dec TYPE i VALUE -1. DATA typeinfo TYPE sydes_typeinfo. LOOP AT ASSIGNING . ASSIGN COMPONENT semaitem-col_no OF STRUCTURE TO . DESCRIBE FIELD INTO td. READ TABLE td-types INDEX 1 INTO typeinfo. IF typeinfo-type = 'P'. dec = typeinfo-decimals. ELSEIF typeinfo-type = 'I'. dec = 0. ENDIF. DESCRIBE FIELD TYPE typ COMPONENTS count. mit = 1. DO count TIMES. IF mit = semaitem-col_src. ASSIGN COMPONENT sy-index OF STRUCTURE TO . DESCRIBE FIELD INTO td. READ TABLE td-types INDEX 1 INTO typeinfo. IF typeinfo-type = 'P'. dec = typeinfo-decimals. ENDIF. EXIT. ENDIF. mit = mit + 1. ENDDO. EXIT. ENDLOOP. * format for each columns of table (w/o columns headers) IF semaitem-col_typ = 'DAT'. IF semaitem-col_no > vkeycount. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = all no_flush = no_flush. ELSE. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 0 no_flush = no_flush. ENDIF. ELSEIF semaitem-col_typ = 'STR'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 0 no_flush = no_flush. ELSEIF semaitem-col_typ = 'MON'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 10 no_flush = no_flush. ELSEIF semaitem-col_typ = 'N00'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = 0 no_flush = no_flush. ELSEIF semaitem-col_typ = 'N01'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = 1 no_flush = no_flush. ELSEIF semaitem-col_typ = 'N02'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = 2 no_flush = no_flush. ELSEIF semaitem-col_typ = 'N03'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = 3 no_flush = no_flush. ELSEIF semaitem-col_typ = 'N04'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = 4 no_flush = no_flush. ELSEIF semaitem-col_typ = 'NUM'. IF dec EQ -1. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = 2 no_flush = no_flush. ELSE. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 1 decimals = dec no_flush = no_flush. ENDIF. ELSEIF semaitem-col_typ = 'PCT'. CALL METHOD lo_spreadsheet->set_format EXPORTING rangename = str currency = '' typ = 3 decimals = 0 no_flush = no_flush. ENDIF. ENDIF. ENDLOOP. * get item contents for set_range_data method * get currency cell also mit = 1. DATA: currcells TYPE soi_cell_table. DATA: curritem TYPE soi_cell_item. curritem-rows = 1. curritem-columns = 1. curritem-front = -1. curritem-back = -1. curritem-font = ''. curritem-size = -1. curritem-bold = -1. curritem-italic = -1. curritem-align = -1. curritem-frametyp = -1. curritem-framecolor = -1. curritem-currency = ''. curritem-number = 1. curritem-input = -1. DATA: const TYPE i. * Change for Correction request * Initial 10000 lines are missing in Excel Export * if there are only 2 columns in exported List object. IF datareal GT 2. const = 20000 / datareal. ELSE. const = 20000 / ( datareal + 2 ). ENDIF. DATA: lines TYPE i. DATA: innerlines TYPE i. DATA: counter TYPE i. DATA: curritem2 LIKE curritem. DATA: curritem3 LIKE curritem. DATA: length TYPE i. DATA: found. * append content table (for method set_range_content) LOOP AT ASSIGNING . * save line index to compare with lt_subtot_indexs, * to discover line is a subtotal / totale line or not * ex use to set 'dun display zero in subtotal / total line' l_save_index = sy-tabix. DO datareal TIMES. READ TABLE lt_sema INTO semaitem WITH KEY col_no = sy-index. IF semaitem-col_src NE 0. ASSIGN COMPONENT semaitem-col_src OF STRUCTURE TO . ELSE. ASSIGN COMPONENT sy-index OF STRUCTURE TO . ENDIF. contentsitem-row = realoverflow. IF sy-subrc = 0. MOVE semaitem-col_ops TO search_item(3). SEARCH 'ADD#CNT#MIN#MAX#AVG#NOP#DFT#' FOR search_item. IF sy-subrc NE 0. RAISE error_in_sema. ENDIF. MOVE semaitem-col_typ TO search_item(3). SEARCH 'NUM#N00#N01#N02#N03#N04#PCT#DAT#MON#STR#' FOR search_item. IF sy-subrc NE 0. RAISE error_in_sema. ENDIF. contentsitem-column = sy-index. IF semaitem-col_typ EQ 'DAT' OR semaitem-col_typ EQ 'MON'. IF semaitem-col_no > vkeycount. " Hinweis 512418 " EXCEL bezieht Datumsangaben " auf den 31.12.1899, behandelt " aber 1900 als ein Schaltjahr " d.h. ab 1.3.1900 korrekt " 1.3.1900 als Zahl = 61 DATA: genesis TYPE d VALUE '18991230'. DATA: number_of_days TYPE p. * change for date in char format & sema_type = X DATA: temp_date TYPE d. IF NOT IS INITIAL AND NOT CO ' ' AND NOT CO '0'. * change for date in char format & sema_type = X starts IF sema_type = 'X'. DESCRIBE FIELD TYPE typ. IF typ = 'C'. temp_date = . number_of_days = temp_date - genesis. ELSE. number_of_days = - genesis. ENDIF. ELSE. number_of_days = - genesis. ENDIF. * change for date in char format & sema_type = X ends IF number_of_days < 61. number_of_days = number_of_days - 1. ENDIF. SET COUNTRY 'DE'. WRITE number_of_days TO contentsitem-value NO-GROUPING LEFT-JUSTIFIED. SET COUNTRY space. TRANSLATE contentsitem-value USING comma_elim. ELSE. CLEAR contentsitem-value. ENDIF. ELSE. MOVE TO contentsitem-value. ENDIF. ELSEIF semaitem-col_typ EQ 'NUM' OR semaitem-col_typ EQ 'N00' OR semaitem-col_typ EQ 'N01' OR semaitem-col_typ EQ 'N02' OR semaitem-col_typ EQ 'N03' OR semaitem-col_typ EQ 'N04' OR semaitem-col_typ EQ 'PCT'. SET COUNTRY 'DE'. DESCRIBE FIELD TYPE typ. IF semaitem-col_cur IS INITIAL. IF typ NE 'F'. WRITE TO contentsitem-value NO-GROUPING NO-SIGN DECIMALS 14. ELSE. WRITE TO contentsitem-value NO-GROUPING NO-SIGN. ENDIF. ELSE. * Treat of fixed curreny for column >>Y9CK007319 IF semaitem-col_cur < 0. semaitem-col_cur = semaitem-col_cur * ( -1 ). SELECT * FROM tcurx INTO TABLE lt_tcurx. SORT lt_tcurx. READ TABLE lt_tcurx INTO wa_tcurx INDEX semaitem-col_cur. IF sy-subrc = 0. IF typ NE 'F'. WRITE TO contentsitem-value NO-GROUPING CURRENCY wa_tcurx-currkey NO-SIGN DECIMALS 14. ELSE. WRITE TO contentsitem-value NO-GROUPING CURRENCY wa_tcurx-currkey NO-SIGN. ENDIF. ENDIF. ELSE. ASSIGN COMPONENT semaitem-col_cur OF STRUCTURE TO . * mit = index of recent row curritem-top = rowmax + mit + li_commentary_rows. li_col_pos = sy-index + i_left - 1. curritem-left = li_col_pos. * if filed is quantity field (qfieldname ne space) * or amount field (cfieldname ne space), then format decimal place * corresponding with config CLEAR: l_def. READ TABLE lt_fieldcat_kkblo ASSIGNING WITH KEY tabname = l_tabname tech = space no_out = space col_pos = semaitem-col_no. IF sy-subrc = 0. IF -cfieldname IS NOT INITIAL. l_def = 'C'. ELSE."if -qfieldname is not initial. l_def = 'Q'. ENDIF. ENDIF. * if field is amount field * exporting of amount field base on currency decimal table: TCURX IF l_def = 'C'. "field is amount field SELECT SINGLE * FROM tcurx INTO wa_tcurx WHERE currkey = . * if amount ref to un-know currency -> default decimal = 2 IF sy-subrc EQ 0. curritem-decimals = wa_tcurx-currdec. ELSE. curritem-decimals = 2. ENDIF. APPEND curritem TO currcells. IF typ NE 'F'. WRITE TO contentsitem-value CURRENCY NO-SIGN NO-GROUPING. ELSE. WRITE TO contentsitem-value DECIMALS 14 CURRENCY NO-SIGN NO-GROUPING. ENDIF. * if field is quantity field * exporting of quantity field base on quantity decimal table: T006 ELSE."if l_def = 'Q'. " field is quantity field CLEAR: wa_t006. SELECT SINGLE * FROM t006 INTO wa_t006 WHERE msehi = . * if quantity ref to un-know unit-> default decimal = 2 IF sy-subrc EQ 0. curritem-decimals = wa_t006-decan. ELSE. curritem-decimals = 2. ENDIF. APPEND curritem TO currcells. WRITE TO contentsitem-value UNIT NO-SIGN NO-GROUPING. CONDENSE contentsitem-value. ENDIF. ENDIF. "Y9CK007319 ENDIF. CONDENSE contentsitem-value. * add function fieldcat-no zero display LOOP AT lt_fieldcat_kkblo ASSIGNING WHERE tabname = l_tabname AND tech NE 'X' AND no_out NE 'X'. IF -col_pos = semaitem-col_no. IF -no_zero = 'X'. IF = '0'. CLEAR: contentsitem-value. ENDIF. * dun display zero in total/subtotal line too ELSE. CLEAR: wa_subtot_indexs. READ TABLE lt_subtot_indexs INTO wa_subtot_indexs WITH KEY index = l_save_index. IF sy-subrc = 0 AND = '0'. CLEAR: contentsitem-value. ENDIF. ENDIF. ENDIF. ENDLOOP. UNASSIGN: . IF LT 0. SEARCH contentsitem-value FOR 'E'. IF sy-fdpos EQ 0. * use prefix notation for signed numbers TRANSLATE contentsitem-value USING '- '. CONDENSE contentsitem-value NO-GAPS. CONCATENATE '-' contentsitem-value INTO contentsitem-value. ELSE. CONCATENATE '-' contentsitem-value INTO contentsitem-value. ENDIF. ENDIF. SET COUNTRY space. * Hier wird nur die korrekte Kommaseparatierung gemacht, wenn die * Zeichen einer * Zahl enthalten sind. Das ist für Timestamps, die auch ":" enthalten. * Für die * darf keine Kommaseparierung stattfinden. * Changing for correction request - Y6BK041073 IF contentsitem-value CO '0123456789.,-+E '. TRANSLATE contentsitem-value USING comma_elim. ENDIF. ELSE. CLEAR contentsitem-value. * if type is not numeric -> dun display with zero WRITE TO contentsitem-value NO-ZERO. SHIFT contentsitem-value LEFT DELETING LEADING space. ENDIF. APPEND contentsitem TO contents. ENDIF. ENDDO. realmit = realmit + 1. realoverflow = realoverflow + 1. mit = mit + 1. * overflow = current row index in content table overflow = overflow + 1. ENDLOOP. UNASSIGN: . * set item range for set_range_data method testname = mit / const. CONDENSE testname. CONCATENATE 'TEST' testname INTO testname. realoverflow = realoverflow - 1. realmit = realmit - 1. help = realoverflow. rangeitem-name = testname. rangeitem-columns = datareal. rangeitem-rows = help. APPEND rangeitem TO ranges. * insert item range dim temp2 = rowmax + 1 + li_commentary_rows + realmit - realoverflow. * items data CALL METHOD lo_spreadsheet->insert_range_dim EXPORTING name = testname top = temp2 left = i_left rows = help columns = datareal no_flush = no_flush. * get columns header contents for set_range_data method * export columns header only if no columns header option = space DATA: rowcount TYPE i. DATA: columncount TYPE i. IF i_columns_header = 'X'. * append columns header to contents: hkey rowcount = 1. DO rowmax TIMES. columncount = 1. DO hkeycolumns TIMES. LOOP AT lt_hkey INTO hkeyitem WHERE col_no = columncount AND row_no = rowcount. ENDLOOP. IF sy-subrc = 0. str = hkeyitem-col_name. contentsitem-value = hkeyitem-col_name. ELSE. contentsitem-value = str. ENDIF. contentsitem-column = columncount. contentsitem-row = rowcount. APPEND contentsitem TO contents. columncount = columncount + 1. ENDDO. rowcount = rowcount + 1. ENDDO. * incase columns header in multiline DATA: rowmaxtemp TYPE i. IF rowmax > 1. rowmaxtemp = rowmax - 1. rowcount = 1. DO rowmaxtemp TIMES. columncount = 1. DO columnmax TIMES. contentsitem-column = columncount. contentsitem-row = rowcount. contentsitem-value = ''. APPEND contentsitem TO contents. columncount = columncount + 1. ENDDO. rowcount = rowcount + 1. ENDDO. ENDIF. * append columns header to contents: vkey columncount = 1. DO columnmax TIMES. LOOP AT lt_vkey INTO vkeyitem WHERE col_no = columncount. ENDLOOP. contentsitem-value = vkeyitem-col_name. contentsitem-row = rowmax. contentsitem-column = columncount. APPEND contentsitem TO contents. columncount = columncount + 1. ENDDO. *--------------------------------------------------------------------* * set header range for method set_range_data * insert header keys range dim li_head_top = li_commentary_rows + 1. li_col_pos = i_left. * insert range headers IF hkeycolumns NE 0. rangeitem-name = 'TESTHKEY'. rangeitem-rows = rowmax. rangeitem-columns = hkeycolumns. APPEND rangeitem TO ranges. CLEAR: rangeitem. CALL METHOD lo_spreadsheet->insert_range_dim EXPORTING name = 'TESTHKEY' top = li_head_top left = li_col_pos rows = rowmax columns = hkeycolumns no_flush = no_flush. ENDIF. ENDIF. * format for columns header + total + subtotal * ------------------------------------------ help = rowmax + realmit. " table + header lines DATA: lt_format TYPE soi_format_table. DATA: wa_format LIKE LINE OF lt_format. DATA: wa_format_temp LIKE LINE OF lt_format. FIELD-SYMBOLS: TYPE any. FIELD-SYMBOLS: TYPE any. * columns header format wa_format-front = -1. wa_format-back = 15. "grey wa_format-font = space. wa_format-size = -1. wa_format-bold = 1. wa_format-align = 0. wa_format-frametyp = -1. wa_format-framecolor = -1. * get column header format from input record * -> map input format IF i_columns_header = 'X'. wa_format-name = 'TESTHKEY'. IF i_format_col_header IS NOT INITIAL. DESCRIBE FIELD i_format_col_header TYPE l_typ COMPONENTS li_col_num. DO li_col_num TIMES. IF sy-index NE 1. " dun map range name ASSIGN COMPONENT sy-index OF STRUCTURE i_format_col_header TO . IF IS NOT INITIAL. ASSIGN COMPONENT sy-index OF STRUCTURE wa_format TO . = . UNASSIGN: . ENDIF. UNASSIGN: . ENDIF. ENDDO. CLEAR: li_col_num. ENDIF. APPEND wa_format TO lt_format. ENDIF. * Zusammenfassen der Spalten mit gleicher Nachkommastellenzahl * collect vertical cells (col) with the same number of decimal places * to increase perfomance in currency cell format DESCRIBE TABLE currcells LINES lines. lines = lines - 1. DO lines TIMES. DESCRIBE TABLE currcells LINES innerlines. innerlines = innerlines - 1. SORT currcells BY left top. CLEAR found. DO innerlines TIMES. READ TABLE currcells INDEX sy-index INTO curritem. counter = sy-index + 1. READ TABLE currcells INDEX counter INTO curritem2. IF curritem-left EQ curritem2-left. length = curritem-top + curritem-rows. IF length EQ curritem2-top AND curritem-decimals EQ curritem2-decimals. MOVE curritem TO curritem3. curritem3-rows = curritem3-rows + curritem2-rows. curritem-left = -1. MODIFY currcells INDEX sy-index FROM curritem. curritem2-left = -1. MODIFY currcells INDEX counter FROM curritem2. APPEND curritem3 TO currcells. found = 'X'. ENDIF. ENDIF. ENDDO. IF found IS INITIAL. EXIT. ENDIF. DELETE currcells WHERE left = -1. ENDDO. * Zusammenfassen der Zeilen mit gleicher Nachkommastellenzahl * collect horizontal cells (row) with the same number of decimal places * to increase perfomance in currency cell format DESCRIBE TABLE currcells LINES lines. lines = lines - 1. DO lines TIMES. DESCRIBE TABLE currcells LINES innerlines. innerlines = innerlines - 1. SORT currcells BY top left. CLEAR found. DO innerlines TIMES. READ TABLE currcells INDEX sy-index INTO curritem. counter = sy-index + 1. READ TABLE currcells INDEX counter INTO curritem2. IF curritem-top EQ curritem2-top AND curritem-rows EQ curritem2-rows. length = curritem-left + curritem-columns. IF length EQ curritem2-left AND curritem-decimals EQ curritem2-decimals. MOVE curritem TO curritem3. curritem3-columns = curritem3-columns + curritem2-columns. curritem-left = -1. MODIFY currcells INDEX sy-index FROM curritem. curritem2-left = -1. MODIFY currcells INDEX counter FROM curritem2. APPEND curritem3 TO currcells. found = 'X'. ENDIF. ENDIF. ENDDO. IF found IS INITIAL. EXIT. ENDIF. DELETE currcells WHERE left = -1. ENDDO. * Ende der Zusammenfassung * item data: format for currency cell, corresponding with currency CALL METHOD lo_spreadsheet->cell_format EXPORTING cells = currcells no_flush = no_flush. * item data: write item table content CALL METHOD lo_spreadsheet->set_ranges_data EXPORTING ranges = ranges contents = contents no_flush = no_flush. * whole table range to format all table IF i_columns_header = 'X'. li_head_top = li_commentary_rows + 1. ELSE. li_head_top = li_commentary_rows + 2. help = help - 1. ENDIF. CALL METHOD lo_spreadsheet->insert_range_dim EXPORTING name = 'WHOLE_TABLE' top = li_head_top left = i_left rows = help columns = datareal no_flush = no_flush. * columns width auto fix * this parameter = space in case use with exist template IF i_columns_autofit = 'X'. CALL METHOD lo_spreadsheet->fit_widest EXPORTING name = 'WHOLE_TABLE' no_flush = no_flush. ENDIF. * frame * The parameter has 8 bits *0 Left margin *1 Top marginT *2 Bottom margin *3 Right margin *4 Horizontal line *5 Vertical line *6 Thinness *7 Thickness * here 127 = 1111111 6-5-4-3-2-1 mean Thin-ver-hor-right-bot-top-left * ( final DOI method call, set no_flush = space * equal to call method CL_GUI_CFW=>FLUSH ) CALL METHOD lo_spreadsheet->set_frame EXPORTING rangename = 'WHOLE_TABLE' typ = 127 color = 1 no_flush = space IMPORTING error = lo_error retcode = lc_retcode. error_doi. * reformat subtotal / total line after format wholw table LOOP AT subranges INTO subrangeitem. l_sub_index = subrangeitem-rows + li_commentary_rows + rowmax. CALL METHOD lo_spreadsheet->insert_range_dim EXPORTING name = subrangeitem-name left = i_left top = l_sub_index rows = 1 columns = datareal no_flush = no_flush. wa_format-name = subrangeitem-name. * default format: * - clolor: subtotal = light yellow, subtotal = yellow * - frame: box IF subrangeitem-name(3) = 'SUB'. wa_format-back = 36. "subtotal line wa_format_temp = i_format_subtotal. ELSE. wa_format-back = 27. "total line wa_format_temp = i_format_total. ENDIF. wa_format-frametyp = 79. wa_format-framecolor = 1. wa_format-number = -1. wa_format-align = -1. * get subtoal + total format from intput parameter * overwrite default format IF wa_format_temp IS NOT INITIAL. DESCRIBE FIELD wa_format_temp TYPE l_typ COMPONENTS li_col_num. DO li_col_num TIMES. IF sy-index NE 1. " dun map range name ASSIGN COMPONENT sy-index OF STRUCTURE wa_format_temp TO . IF IS NOT INITIAL. ASSIGN COMPONENT sy-index OF STRUCTURE wa_format TO . = . UNASSIGN: . ENDIF. UNASSIGN: . ENDIF. ENDDO. CLEAR: li_col_num. ENDIF. APPEND wa_format TO lt_format. CLEAR: wa_format-name. CLEAR: l_sub_index. CLEAR: wa_format_temp. ENDLOOP. IF lt_format[] IS NOT INITIAL. CALL METHOD lo_spreadsheet->set_ranges_format EXPORTING formattable = lt_format no_flush = no_flush. REFRESH: lt_format. ENDIF. *--------------------------------------------------------------------* CALL METHOD lo_spreadsheet->screen_update EXPORTING updating = 'X'. CALL METHOD c_oi_errors=>flush_errors. lo_error_w = l_error. lc_retcode = lo_error_w->error_code. ** catch no_flush -> led to dump ( optional ) * go_error = l_error. * gc_retcode = go_error->error_code. * error_doi. CLEAR: lt_sema, wa_sema, lt_hkey, wa_hkey, lt_vkey, wa_vkey, l_n_hrz_keys, l_n_att_cols, l_n_vrt_keys, count, datac, datareal, vkeycount, all, mit, li_col_pos, li_col_num, ranges, rangeitem, contents, contentsitem, semaitem, hkeyitem, vkeyitem, li_commentary_rows, l_retcode, li_head_top, . CLEAR: lo_error_w. UNASSIGN: , , . *--------------------------------------------------------------------* * SESSION 5: SAVE AND CLOSE FILE *--------------------------------------------------------------------* * ex of save path: 'FILE://C:\temp\test.xlsx' CONCATENATE 'FILE://' i_save_path INTO ls_path. CALL METHOD lo_proxy->save_document_to_url EXPORTING no_flush = 'X' url = ls_path IMPORTING error = lo_error retcode = lc_retcode CHANGING document_size = li_document_size. error_doi. * if save successfully -> raise successful message MESSAGE i400(zabap2xlsx). CLEAR: ls_path, li_document_size. close_document. ENDMETHOD. "BIND_ALV_OLE2 ENDCLASS.