From 8f4157624c36e8417b38d88d9208ee8b2d7925d3 Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 24 Feb 2014 16:12:43 -0600 Subject: [PATCH] New daily build --- build/ABAP2XLSX_V_7_0.nugg | 31409 +++++++++++++++++------------------ build/ABAP2XLSX_V_7_0.zip | Bin 288666 -> 288183 bytes 2 files changed, 15310 insertions(+), 16099 deletions(-) diff --git a/build/ABAP2XLSX_V_7_0.nugg b/build/ABAP2XLSX_V_7_0.nugg index 7ec9fb7..ac5677b 100644 --- a/build/ABAP2XLSX_V_7_0.nugg +++ b/build/ABAP2XLSX_V_7_0.nugg @@ -1,7 +1,12582 @@ + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + " Initialise instance variables + formula1 = ''. + formula2 = ''. + type = me->c_type_none. + errorstyle = me->c_style_stop. + operator = ''. + allowblank = abap_false. + showdropdown = abap_false. + showinputmessage = abap_true. + showerrormessage = abap_true. + errortitle = ''. + error = ''. + prompttitle = ''. + prompt = ''. +* inizialize dimension range + cell_row = 1. + cell_column = 'A'. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + method ADD. + data_validations->add( ip_data_validation ). + endmethod. + + + method CLEAR. + data_validations->clear( ). + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT data_validations. + + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= data_validations->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = data_validations->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + data_validations->remove( ip_data_validation ). + endmethod. + + + + method SIZE. + ep_size = data_validations->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + CALL FUNCTION 'GUID_CREATE' + IMPORTING + ev_guid_16 = me->guid. + + IF ip_title IS NOT INITIAL. + title = ip_title. + ELSE. + title = me->guid. + ENDIF. + + me->type = ip_type. + +* inizialize dimension range + anchor = anchor_one_cell. + from_loc-col = 1. + from_loc-row = 1. + endmethod. + + + + method CREATE_MEDIA_NAME. + +* if media name is initial, create unique name + CHECK media_name IS INITIAL. + + index = ip_index. + CONCATENATE me->type index INTO media_name. + CONDENSE media_name NO-GAPS. + endmethod. + + + + method GET_FROM_COL. + r_from_col = me->from_loc-col. + endmethod. + + + + method GET_FROM_ROW. + r_from_row = me->from_loc-row. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + method GET_HEIGHT_EMU_STR. + r_height = pixel2emu( size-height ). + CONDENSE r_height NO-GAPS. + endmethod. + + + + method GET_INDEX. + rp_index = me->index. + endmethod. + + + + method GET_MEDIA. + CASE media_source. + WHEN c_media_source_xstring. + r_media = media. + WHEN c_media_source_www. + DATA: lt_mime TYPE tsfmime, + lv_filesize TYPE i, + lv_filesizec(10). + + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = media_key_www + TABLES + mime = lt_mime + EXCEPTIONS + OTHERS = 1. + + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = media_key_www-relid + objid = media_key_www-objid + name = 'filesize' + IMPORTING + value = lv_filesizec. + + lv_filesize = lv_filesizec. + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filesize + IMPORTING + buffer = r_media + TABLES + binary_tab = lt_mime + EXCEPTIONS + failed = 1 + OTHERS = 2. + WHEN c_media_source_mime. + DATA: lt_bin_mime TYPE sdokcntbins. + cl_wb_mime_repository=>load_mime( EXPORTING + io = me->io + IMPORTING + filesize = lv_filesize + bin_data = lt_bin_mime + CHANGING + language = sy-langu ). + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filesize + IMPORTING + buffer = r_media + TABLES + binary_tab = lt_bin_mime + EXCEPTIONS + failed = 1 + OTHERS = 2. + ENDCASE. + endmethod. + + + + method GET_MEDIA_NAME. + CONCATENATE media_name `.` media_type INTO r_name. + endmethod. + + + + method GET_MEDIA_TYPE. + r_type = media_type. + endmethod. + + + + method GET_NAME. + r_name = title. + endmethod. + + + + method GET_POSITION. + rp_position-anchor = anchor. + rp_position-from = from_loc. + rp_position-to = to_loc. + rp_position-size = size. + endmethod. + + + + method GET_TO_COL. + r_to_col = me->to_loc-col. + endmethod. + + + + method GET_TO_ROW. + r_to_row = me->to_loc-row. + endmethod. + + + + method GET_TYPE. + rp_type = me->type. + endmethod. + + + + method GET_WIDTH_EMU_STR. + r_width = pixel2emu( size-width ). + CONDENSE r_width NO-GAPS. + endmethod. + + + + method LOAD_CHART_ATTRIBUTES. + DATA: node TYPE REF TO if_ixml_element. + DATA: node2 TYPE REF TO if_ixml_element. + DATA: node3 TYPE REF TO if_ixml_element. + DATA: node4 TYPE REF TO if_ixml_element. + DATA: iterator TYPE REF TO if_ixml_node_iterator. + + DATA: chartspace TYPE REF TO if_ixml_node_collection. + DATA: coll_length TYPE i. + DATA: chartelem TYPE REF TO if_ixml_element. + + DATA lo_barchart TYPE REF TO zcl_excel_graph_bars. + DATA lo_piechart TYPE REF TO zcl_excel_graph_pie. + DATA lo_linechart TYPE REF TO zcl_excel_graph_line. + + TYPES: BEGIN OF t_prop, + val TYPE string, + rtl TYPE string, + lang TYPE string, + formatcode TYPE string, + sourcelinked TYPE string, + END OF t_prop. + + TYPES: BEGIN OF t_pagemargins, + b TYPE string, + l TYPE string, + r TYPE string, + t TYPE string, + header TYPE string, + footer TYPE string, + END OF t_pagemargins. + + DATA ls_prop TYPE t_prop. + DATA ls_pagemargins TYPE t_pagemargins. + + DATA lo_collection TYPE REF TO if_ixml_node_collection. + DATA lo_node TYPE REF TO if_ixml_node. + DATA lo_iterator TYPE REF TO if_ixml_node_iterator. + DATA lv_idx TYPE i. + DATA lv_order TYPE i. + DATA lv_invertifnegative TYPE string. + DATA lv_symbol TYPE string. + DATA lv_smooth TYPE c. + DATA lv_sername TYPE string. + DATA lv_label TYPE string. + DATA lv_value TYPE string. + DATA lv_axid TYPE string. + DATA lv_orientation TYPE string. + DATA lv_delete TYPE string. + DATA lv_axpos TYPE string. + DATA lv_formatcode TYPE string. + DATA lv_sourcelinked TYPE string. + DATA lv_majortickmark TYPE string. + DATA lv_minortickmark TYPE string. + DATA lv_ticklblpos TYPE string. + DATA lv_crossax TYPE string. + DATA lv_crosses TYPE string. + DATA lv_auto TYPE string. + DATA lv_lblalgn TYPE string. + DATA lv_lbloffset TYPE string. + DATA lv_nomultilvllbl TYPE string. + DATA lv_crossbetween TYPE string. + + node ?= ip_chart->if_ixml_node~get_first_child( ). + CHECK node IS NOT INITIAL. + + CASE me->graph_type. + WHEN c_graph_bars. + CREATE OBJECT lo_barchart. + me->graph = lo_barchart. + WHEN c_graph_pie. + CREATE OBJECT lo_piechart. + me->graph = lo_piechart. + WHEN c_graph_line. + CREATE OBJECT lo_linechart. + me->graph = lo_linechart. + WHEN OTHERS. + ENDCASE. + + "Fill properties + node2 ?= node->find_from_name( name = 'date1904' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_1904val = ls_prop-val. + node2 ?= node->find_from_name( name = 'lang' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_langval = ls_prop-val. + node2 ?= node->find_from_name( name = 'roundedCorners' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_roundedcornersval = ls_prop-val. + + "style + node2 ?= node->find_from_name( name = 'style' namespace = 'c14' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_c14styleval = ls_prop-val. + node2 ?= node->find_from_name( name = 'style' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_styleval = ls_prop-val. + "---------------------------Read graph properties + node2 ?= node->find_from_name( name = 'autoTitleDeleted' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_autotitledeletedval = ls_prop-val. + + "plotArea + CASE me->graph_type. + WHEN c_graph_bars. + node2 ?= node->find_from_name( name = 'barDir' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_bardirval = ls_prop-val. + node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_groupingval = ls_prop-val. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'invertIfNegative' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_invertifnegative = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_barchart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_invertifnegative = lv_invertifnegative + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showbubblesizeval = ls_prop-val. + node2 ?= node->find_from_name( name = 'gapWidth' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_gapwidthval = ls_prop-val. + + "Load axes + node2 ?= node->find_from_name( name = 'barChart' namespace = 'c' ). + CALL METHOD node2->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'axId' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lv_axid = ls_prop-val. + IF sy-index EQ 1. "catAx + node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_auto = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lblalgn = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lbloffset = ls_prop-val. + node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_nomultilvllbl = ls_prop-val. + CALL METHOD lo_barchart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_bars=>c_catax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_auto = lv_auto + ip_lblalgn = lv_lblalgn + ip_lbloffset = lv_lbloffset + ip_nomultilvllbl = lv_nomultilvllbl. + ELSEIF sy-index EQ 2. "valAx + node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossbetween = ls_prop-val. + CALL METHOD lo_barchart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_bars=>c_valax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_crossbetween = lv_crossbetween. + ENDIF. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + + WHEN c_graph_pie. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_piechart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showbubblesizeval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showLeaderLines' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showleaderlinesval = ls_prop-val. + node2 ?= node->find_from_name( name = 'firstSliceAng' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_firstsliceangval = ls_prop-val. + WHEN c_graph_line. + node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_groupingval = ls_prop-val. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'symbol' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_symbol = ls_prop-val. + node3 ?= node2->find_from_name( name = 'smooth' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_smooth = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_linechart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_symbol = lv_symbol + ip_smooth = lv_smooth + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showbubblesizeval = ls_prop-val. + + node ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). + node2 ?= node->find_from_name( name = 'marker' namespace = 'c' DEPTH = '1' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->NS_MARKERVAL = ls_prop-val. + node2 ?= node->find_from_name( name = 'smooth' namespace = 'c' DEPTH = '1' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->NS_SMOOTHVAL = ls_prop-val. + node ?= ip_chart->if_ixml_node~get_first_child( ). + CHECK node IS NOT INITIAL. + + "Load axes + node2 ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). + CALL METHOD node2->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'axId' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lv_axid = ls_prop-val. + IF sy-index EQ 1. "catAx + node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. +* node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). +* zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). +* lv_formatcode = ls_prop-formatcode. +* lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_auto = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lblalgn = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lbloffset = ls_prop-val. + node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_nomultilvllbl = ls_prop-val. + CALL METHOD lo_linechart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_line=>c_catax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_auto = lv_auto + ip_lblalgn = lv_lblalgn + ip_lbloffset = lv_lbloffset + ip_nomultilvllbl = lv_nomultilvllbl. + ELSEIF sy-index EQ 2. "valAx + node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossbetween = ls_prop-val. + CALL METHOD lo_linechart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_line=>c_valax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_crossbetween = lv_crossbetween. + ENDIF. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + WHEN OTHERS. + ENDCASE. + + "legend + CASE me->graph_type. + WHEN c_graph_bars. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_overlayval = ls_prop-val. + WHEN c_graph_line. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_overlayval = ls_prop-val. + WHEN c_graph_pie. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_overlayval = ls_prop-val. + node2 ?= node->find_from_name( name = 'pPr' namespace = 'a' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_pprrtl = ls_prop-rtl. + node2 ?= node->find_from_name( name = 'endParaRPr' namespace = 'a' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_endpararprlang = ls_prop-lang. + + WHEN OTHERS. + ENDCASE. + + node2 ?= node->find_from_name( name = 'plotVisOnly' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_plotvisonlyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'dispBlanksAs' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_dispblanksasval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showDLblsOverMax' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_showdlblsovermaxval = ls_prop-val. + "--------------------- + + node2 ?= node->find_from_name( name = 'pageMargins' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_pagemargins ). + me->graph->pagemargins = ls_pagemargins. + + + endmethod. + + + + + + method PIXEL2EMU. +* suppose 96 DPI + IF ip_dpi IS SUPPLIED. + r_emu = ip_pixel * 914400 / ip_dpi. + ELSE. +* suppose 96 DPI + r_emu = ip_pixel * 914400 / 96. + ENDIF. + endmethod. + + + + + + + method SET_MEDIA. + IF ip_media IS SUPPLIED. + media = ip_media. + ENDIF. + media_type = ip_media_type. + media_source = c_media_source_xstring. + IF ip_width IS SUPPLIED. + size-width = ip_width. + ENDIF. + IF ip_height IS SUPPLIED. + size-height = ip_height. + ENDIF. + endmethod. + + + + + + method SET_MEDIA_MIME. + + io = ip_io. + media_source = c_media_source_mime. + size-width = ip_width. + size-height = ip_height. + + cl_wb_mime_repository=>load_mime( EXPORTING + io = ip_io + IMPORTING + filename = media_name + "mimetype = media_type + CHANGING + language = sy-langu ). + + SPLIT media_name AT '.' INTO media_name media_type. + + + + endmethod. + + + + + + method SET_MEDIA_WWW. + DATA: lv_value(20). + + media_key_www = ip_key. + media_source = c_media_source_www. + + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = media_key_www-relid + objid = media_key_www-objid + name = 'fileextension' + IMPORTING + value = lv_value. + media_type = lv_value. + SHIFT media_type LEFT DELETING LEADING '.'. + + size-width = ip_width. + size-height = ip_height. + endmethod. + + + + + + + method SET_POSITION. + from_loc-col = zcl_excel_common=>convert_column2int( ip_from_col ) - 1. + IF ip_coloff IS SUPPLIED. + from_loc-col_offset = ip_coloff. + ENDIF. + from_loc-row = ip_from_row - 1. + IF ip_rowoff IS SUPPLIED. + from_loc-row_offset = ip_rowoff. + ENDIF. + anchor = anchor_one_cell. + endmethod. + + + + + + method SET_POSITION2. + + data: lv_anchor type zexcel_drawing_anchor. + lv_anchor = ip_anchor. + + IF lv_anchor IS INITIAL. + IF ip_to IS NOT INITIAL. + lv_anchor = anchor_two_cell. + ELSE. + lv_anchor = anchor_one_cell. + ENDIF. + ENDIF. + + CASE lv_anchor. + WHEN anchor_absolute OR anchor_one_cell. + CLEAR: me->to_loc. + WHEN anchor_two_cell. + CLEAR: me->size. + ENDCASE. + + me->from_loc = ip_from. + me->to_loc = ip_to. + me->anchor = lv_anchor. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + method ADD. + DATA: lv_index TYPE i. + + drawings->add( ip_drawing ). + lv_index = drawings->if_object_collection~size( ). + ip_drawing->create_media_name( + ip_index = lv_index ). + endmethod. + + + method CLEAR. + + drawings->clear( ). + endmethod. + + + + method CONSTRUCTOR. + + CREATE OBJECT drawings. + type = ip_type. + + endmethod. + + + + + method GET. + + DATA lv_index TYPE i. + lv_index = ip_index. + eo_drawing ?= drawings->if_object_collection~get( lv_index ). + endmethod. + + + + method GET_ITERATOR. + + eo_iterator ?= drawings->if_object_collection~get_iterator( ). + endmethod. + + + + method GET_TYPE. + rp_type = me->type. + endmethod. + + + + method INCLUDE. + drawings->add( ip_drawing ). + endmethod. + + + + method IS_EMPTY. + + is_empty = drawings->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + + drawings->remove( ip_drawing ). + endmethod. + + + + method SIZE. + + ep_size = drawings->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + method CREATE. + data: lo_hyperlink type REF TO zcl_excel_hyperlink. + + create OBJECT lo_hyperlink. + + lo_hyperlink->location = iv_url. + lo_hyperlink->internal = iv_internal. + + ov_link = lo_hyperlink. + endmethod. + + + + + method CREATE_EXTERNAL_LINK. + + ov_link = zcl_excel_hyperlink=>create( iv_url = iv_url + iv_internal = abap_false ). + endmethod. + + + + + method CREATE_INTERNAL_LINK. + ov_link = zcl_excel_hyperlink=>create( iv_url = iv_location + iv_internal = abap_true ). + endmethod. + + + + method GET_REF. + ev_ref = row. + CONDENSE ev_ref. + CONCATENATE column ev_ref INTO ev_ref. + endmethod. + + + + method GET_URL. + ev_url = me->location. + endmethod. + + + + method IS_INTERNAL. + ev_ret = me->internal. + endmethod. + + + + + + method SET_CELL_REFERENCE. + me->column = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column + me->row = ip_row. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method CONSTRUCTOR. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + method GET_VALUE. + + ep_value = me->value. + + endmethod. + + + + method SET_RANGE_VALUE. + me->value = ip_value. + endmethod. + + + + + + + + method SET_VALUE. + DATA: lv_start_row_c TYPE char7, + lv_stop_row_c TYPE char7, + lv_value TYPE string. + lv_stop_row_c = ip_stop_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_start_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + lv_value = ip_sheet_name. + me->value = zcl_excel_common=>escape_string( ip_value = lv_value ). + + CONCATENATE me->value '!$' ip_start_column '$' lv_start_row_c ':$' ip_stop_column '$' lv_stop_row_c INTO me->value. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + ranges->add( ip_range ). + endmethod. + + + method CLEAR. + ranges->clear( ). + endmethod. + + + method CONSTRUCTOR. + + + CREATE OBJECT ranges. + + endmethod. + + + + + method GET. + eo_range ?= ranges->if_object_collection~get( ip_index ). + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= ranges->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = ranges->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + ranges->remove( ip_range ). + endmethod. + + + + method SIZE. + ep_size = ranges->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + method CONSTRUCTOR. + endmethod. + + + + method IS_SECURITY_ENABLED. + IF lockrevision EQ abap_true OR lockstructure EQ abap_true OR lockwindows EQ abap_true. + ep_security_enabled = abap_true. + ENDIF. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + orientation = me->c_orientation_default. + +* default margins + margin_bottom = '0.75'. + margin_footer = '0.3'. + margin_header = '0.3'. + margin_left = '0.7'. + margin_right = '0.7'. + margin_top = '0.75'. + +* clear page settings + CLEAR: black_and_white, + cell_comments, + copies, + draft, + errors, + first_page_number, + fit_to_page, + fit_to_height, + fit_to_width, + horizontal_dpi, + orientation, + page_order, + paper_height, + paper_size, + paper_width, + scale, + use_first_page_num, + use_printer_defaults, + vertical_dpi. + endmethod. + + + + + + + method GET_HEADER_FOOTER_STRING. +* ---------------------------------------------------------------------- + DATA: lc_marker_left(2) TYPE c VALUE '&L' + , lc_marker_right(2) TYPE c VALUE '&R' + , lc_marker_center(2) TYPE c VALUE '&C' + , lv_value TYPE string + . +* ---------------------------------------------------------------------- + IF ep_odd_header IS SUPPLIED. + + IF me->odd_header-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_odd_header. + ENDIF. + + IF me->odd_header-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'CENTER' ). + CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_header. + ENDIF. + + IF me->odd_header-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'RIGHT' ). + CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_header. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_odd_footer IS SUPPLIED. + + IF me->odd_footer-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_odd_footer. + ENDIF. + + IF me->odd_footer-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'CENTER' ). + CONCATENATE ep_odd_footer lc_marker_center lv_value INTO ep_odd_footer. + ENDIF. + + IF me->odd_footer-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'RIGHT' ). + CONCATENATE ep_odd_footer lc_marker_right lv_value INTO ep_odd_footer. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_even_header IS SUPPLIED. + + IF me->even_header-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_even_header. + ENDIF. + + IF me->even_header-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'CENTER' ). + CONCATENATE ep_even_header lc_marker_center lv_value INTO ep_even_header. + ENDIF. + + IF me->even_header-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'RIGHT' ). + CONCATENATE ep_even_header lc_marker_right lv_value INTO ep_even_header. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_even_footer IS SUPPLIED. + + IF me->even_footer-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_even_footer. + ENDIF. + + IF me->even_footer-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'CENTER' ). + CONCATENATE ep_even_footer lc_marker_center lv_value INTO ep_even_footer. + ENDIF. + + IF me->even_footer-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'RIGHT' ). + CONCATENATE ep_even_footer lc_marker_right lv_value INTO ep_even_footer. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + endmethod. + + + + + + method PROCESS_HEADER_FOOTER. + +* ---------------------------------------------------------------------- +* Only Basic font/text formatting possible: +* Bold (yes / no), Font Type, Font Size + + DATA: lv_fname(12) TYPE c + , lv_string TYPE string + . + + FIELD-SYMBOLS: <lv_value> TYPE string + , <ls_font> TYPE zexcel_s_style_font + . + +* ---------------------------------------------------------------------- + CONCATENATE ip_side '_VALUE' INTO lv_fname. + ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <lv_value>. + + CONCATENATE ip_side '_FONT' INTO lv_fname. + ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <ls_font>. + + IF <ls_font> IS ASSIGNED AND <lv_value> IS ASSIGNED. + + IF <ls_font>-name IS NOT INITIAL. + CONCATENATE '&"' <ls_font>-name ',' INTO rv_processed_string. + ELSE. + rv_processed_string = '&"-,'. + ENDIF. + + IF <ls_font>-bold = abap_true. + CONCATENATE rv_processed_string 'Bold"' INTO rv_processed_string. + ELSE. + CONCATENATE rv_processed_string 'Standard"' INTO rv_processed_string. + ENDIF. + + IF <ls_font>-size IS NOT INITIAL. + lv_string = <ls_font>-size. + CONCATENATE rv_processed_string '&' lv_string INTO rv_processed_string. + ENDIF. + + CONCATENATE rv_processed_string <lv_value> INTO rv_processed_string. + + ENDIF. +* ---------------------------------------------------------------------- + + endmethod. + + + + + + + method SET_HEADER_FOOTER. + +* Only Basic font/text formatting possible: +* Bold (yes / no), Font Type, Font Size +* +* usefull placeholders, which can be used in header/footer value strings +* '&P' - page number +* '&N' - total number of pages +* '&D' - Date +* '&T' - Time +* '&F' - File Name +* '&Z' - Path +* '&A' - Sheet name +* new line via class constant CL_ABAP_CHAR_UTILITIES=>newline +* +* Example Value String 'page &P of &N' +* +* DO NOT USE &L , &C or &R which automatically created as position markers + + me->odd_header = ip_odd_header. + me->odd_footer = ip_odd_footer. + me->even_header = ip_even_header. + me->even_footer = ip_even_footer. + + IF me->even_header IS NOT INITIAL OR me->even_footer IS NOT INITIAL. + me->diff_oddeven_headerfooter = abap_true. + ENDIF. + + + endmethod. + + + + + + + + + + method SET_PAGE_MARGINS. + DATA: lv_coef TYPE f, + lv_unit TYPE string. + + lv_unit = ip_unit. + TRANSLATE lv_unit TO UPPER CASE. + + CASE lv_unit. + WHEN 'IN'. lv_coef = 1. + WHEN 'CM'. lv_coef = '0.393700787'. + WHEN 'MM'. lv_coef = '0.0393700787'. + ENDCASE. + + IF ip_bottom IS SUPPLIED. margin_bottom = lv_coef * ip_bottom. ENDIF. + IF ip_footer IS SUPPLIED. margin_footer = lv_coef * ip_footer. ENDIF. + IF ip_header IS SUPPLIED. margin_header = lv_coef * ip_header. ENDIF. + IF ip_left IS SUPPLIED. margin_left = lv_coef * ip_left. ENDIF. + IF ip_right IS SUPPLIED. margin_right = lv_coef * ip_right. ENDIF. + IF ip_top IS SUPPLIED. margin_top = lv_coef * ip_top. ENDIF. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + method CONSTRUCTOR. + + + CREATE OBJECT font. + CREATE OBJECT fill. + CREATE OBJECT borders. + CREATE OBJECT alignment. + CREATE OBJECT number_format. + CREATE OBJECT protection. + +* Start of insertion # issue 139 - Dateretention of cellstyles + IF ip_guid IS NOT INITIAL. + me->guid = ip_guid. + ELSE. +* End of insertion # issue 139 - Dateretention of cellstyles + CALL FUNCTION 'GUID_CREATE' + IMPORTING + ev_guid_16 = me->guid. +* Start of insertion # issue 139 - Dateretention of cellstyles + ENDIF. +* End of insertion # issue 139 - Dateretention of cellstyles + + endmethod. + + + + method GET_GUID. + + + ep_guid = me->guid. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + + + styles->add( ip_style ). + endmethod. + + + method CLEAR. + + + styles->clear( ). + endmethod. + + + method CONSTRUCTOR. + + + CREATE OBJECT styles. + endmethod. + + + + + method GET. + + + eo_style ?= styles->if_object_collection~get( ip_index ). + endmethod. + + + + method GET_ITERATOR. + + + eo_iterator ?= styles->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + + + is_empty = styles->if_object_collection~is_empty( ). + endmethod. + + + + + method REGISTER_NEW_STYLE. + + + me->add( io_style ). + ep_style_code = me->size( ) - 1. "style count starts from 0 + endmethod. + + + + method REMOVE. + + + styles->remove( ip_style ). + endmethod. + + + + method SIZE. + + + ep_size = styles->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + styles_conditional->add( ip_style_conditional ). + endmethod. + + + method CLEAR. + styles_conditional->clear( ). + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT styles_conditional. + + endmethod. + + + + + method GET. + DATA lv_index TYPE i. + lv_index = ip_index. + eo_style_conditional ?= styles_conditional->if_object_collection~get( lv_index ). + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= styles_conditional->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = styles_conditional->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + styles_conditional->remove( ip_style_conditional ). + endmethod. + + + + method SIZE. + ep_size = styles_conditional->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + horizontal = me->c_horizontal_general. + vertical = me->c_vertical_bottom. + wrapText = abap_false. + shrinkToFit = abap_false. + endmethod. + + + + method GET_STRUCTURE. + + es_alignment-horizontal = me->horizontal. + es_alignment-vertical = me->vertical. + es_alignment-textrotation = me->textrotation. + es_alignment-wraptext = me->wraptext. + es_alignment-shrinktofit = me->shrinktofit. + es_alignment-indent = me->indent. + + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + method CREATE. + + +* Office 2007 file format is a cab of several xml files with extension .xlsx + + DATA: lo_zip TYPE REF TO cl_abap_zip, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_active_worksheet TYPE REF TO zcl_excel_worksheet, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_nested_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_drawings TYPE REF TO zcl_excel_drawings. + + DATA: lv_content TYPE xstring, + lv_active TYPE flag, + lv_xl_sheet TYPE string, + lv_xl_sheet_rels TYPE string, + lv_xl_drawing TYPE string, + lv_xl_drawing_rels TYPE string, + lv_syindex TYPE string, + lv_value TYPE string, + lv_drawing_index TYPE i. + +********************************************************************** +* Start of insertion # issue 139 - Dateretention of cellstyles + me->excel->add_static_styles( ). +* End of insertion # issue 139 - Dateretention of cellstyles + +********************************************************************** +* STEP 1: Create archive object file (ZIP) + CREATE OBJECT lo_zip. + +********************************************************************** +* STEP 2: Add [Content_Types].xml to zip + lv_content = me->create_content_types( ). + lo_zip->add( name = me->c_content_types + content = lv_content ). + +********************************************************************** +* STEP 3: Add _rels/.rels to zip + lv_content = me->create_relationships( ). + lo_zip->add( name = me->c_relationships + content = lv_content ). + +********************************************************************** +* STEP 4: Add docProps/app.xml to zip + lv_content = me->create_docprops_app( ). + lo_zip->add( name = me->c_docprops_app + content = lv_content ). + +********************************************************************** +* STEP 5: Add docProps/core.xml to zip + lv_content = me->create_docprops_core( ). + lo_zip->add( name = me->c_docprops_core + content = lv_content ). + +********************************************************************** +* STEP 6: Add xl/_rels/workbook.xml.rels to zip + lv_content = me->create_xl_relationships( ). + lo_zip->add( name = me->c_xl_relationships + content = lv_content ). + +********************************************************************** +* STEP 6: Add xl/_rels/workbook.xml.rels to zip + lv_content = me->create_xl_theme( ). + lo_zip->add( name = me->c_xl_theme + content = lv_content ). + +********************************************************************** +* STEP 7: Add xl/workbook.xml to zip + lv_content = me->create_xl_workbook( ). + lo_zip->add( name = me->c_xl_workbook + content = lv_content ). + +********************************************************************** +* STEP 8: Add xl/workbook.xml to zip +* lv_content = me->create_xl_styles_static( ). + lv_content = me->create_xl_styles( ). + lo_zip->add( name = me->c_xl_styles + content = lv_content ). + +********************************************************************** +* STEP 9: Add sharedStrings.xml to zip + lv_content = me->create_xl_sharedstrings( ). + lo_zip->add( name = me->c_xl_sharedstrings + content = lv_content ). + +********************************************************************** +* STEP 10: Add sheet#.xml and drawing#.xml to zip + lo_iterator = me->excel->get_worksheets_iterator( ). + lo_active_worksheet = me->excel->get_active_worksheet( ). + lv_drawing_index = 1. + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF lo_active_worksheet->get_guid( ) EQ lo_worksheet->get_guid( ). + lv_active = abap_true. + ELSE. + lv_active = abap_false. + ENDIF. + + lv_content = me->create_xl_sheet( io_worksheet = lo_worksheet + iv_active = lv_active ). + lv_xl_sheet = me->c_xl_sheet. + MOVE sy-index TO lv_syindex. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet WITH lv_syindex. + lo_zip->add( name = lv_xl_sheet + content = lv_content ). + + lv_xl_sheet_rels = me->c_xl_sheet_rels. + lv_content = me->create_xl_sheet_rels( io_worksheet = lo_worksheet + iv_drawing_index = lv_drawing_index ). + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet_rels WITH lv_syindex. + lo_zip->add( name = lv_xl_sheet_rels + content = lv_content ). + + lo_nested_iterator = lo_worksheet->get_tables_iterator( ). + + WHILE lo_nested_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_nested_iterator->if_object_collection_iterator~get_next( ). + lv_content = me->create_xl_table( lo_table ). + + lv_value = lo_table->get_name( ). + CONCATENATE 'xl/tables/' lv_value '.xml' INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +* Add drawings ********************************** + lo_drawings = lo_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + MOVE lv_drawing_index TO lv_syindex. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + + lv_content = me->create_xl_drawings( lo_worksheet ). + lv_xl_drawing = me->c_xl_drawings. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing WITH lv_syindex. + lo_zip->add( name = lv_xl_drawing + content = lv_content ). + + lv_content = me->create_xl_drawings_rels( lo_worksheet ). + lv_xl_drawing_rels = me->c_xl_drawings_rels. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing_rels WITH lv_syindex. + lo_zip->add( name = lv_xl_drawing_rels + content = lv_content ). + ADD 1 TO lv_drawing_index. + ENDIF. + ENDWHILE. + +********************************************************************** +* STEP 11: Add media + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_image ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_content = lo_drawing->get_media( ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/media/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +********************************************************************** +* STEP 12: Add charts + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_chart ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_content = lo_drawing->get_media( ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/charts/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +********************************************************************** +* STEP 9: Add vbaProject.bin to zip + lo_zip->add( name = me->c_xl_vbaproject + content = me->excel->zif_excel_book_vba_project~vbaproject ). + +********************************************************************** +* STEP 12: Create the final zip + ep_excel = lo_zip->save( ). + + endmethod. + + + method CREATE_CONTENT_TYPES. +** Constant node name + DATA: lc_xml_node_workb_ct TYPE string VALUE 'application/vnd.ms-excel.sheet.macroEnabled.main+xml', + lc_xml_node_default TYPE string VALUE 'Default', + " Node attributes + lc_xml_attr_partname TYPE string VALUE 'PartName', + lc_xml_attr_extension TYPE string VALUE 'Extension', + lc_xml_attr_contenttype TYPE string VALUE 'ContentType', + lc_xml_attr_codename TYPE string VALUE 'codeName', + lc_xml_node_workb_pn TYPE string VALUE '/xl/workbook.xml', + lc_xml_node_bin_ext TYPE string VALUE 'bin', + lc_xml_node_bin_ct TYPE string VALUE 'application/vnd.ms-office.vbaProject'. + + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_collection TYPE REF TO if_ixml_node_collection, + lo_iterator TYPE REF TO if_ixml_node_iterator, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_subrc TYPE sysubrc, + lv_contenttype TYPE string, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard contentType + ep_content = super->create_content_types( ). + +********************************************************************** +* STEP 2: modify XML adding the extension bin definition + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + " extension node + lo_element = lo_document->create_simple_element( name = lc_xml_node_default + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_extension + value = lc_xml_node_bin_ext ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_bin_ct ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 3: modify XML changing the contentType of node Override /xl/workbook.xml + + lo_collection = lo_document->get_elements_by_tag_name( 'Override' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lv_contenttype = lo_element->get_attribute_ns( lc_xml_attr_partname ). + IF lv_contenttype EQ lc_xml_node_workb_pn. + lo_element->remove_attribute_ns( lc_xml_attr_contenttype ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_workb_ct ). + EXIT. + ENDIF. + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + method CREATE_XL_RELATIONSHIPS. + +** Constant node name + DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'Id', + lc_xml_attr_type TYPE string VALUE 'Type', + lc_xml_attr_target TYPE string VALUE 'Target', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#', + " Node type + lc_xml_node_rid_vba_tp TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', + " Node target + lc_xml_node_rid_vba_tg TYPE string VALUE 'vbaProject.bin'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_xml_node_ridx_tg TYPE string, + lv_xml_node_ridx_id TYPE string, + lv_size TYPE i, + lv_subrc TYPE sysubrc, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard relationship + ep_content = super->create_xl_relationships( ). + +********************************************************************** +* STEP 2: modify XML adding the vbaProject relation + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + + lv_size = excel->get_worksheets_size( ). + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + ADD 4 TO lv_size. + lv_syindex = lv_size. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_xml_node_ridx_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_vba_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_vba_tg ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + method CREATE_XL_SHEET. + +** Constant node name + DATA: lc_xml_attr_codename TYPE string VALUE 'codeName'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_collection TYPE REF TO if_ixml_node_collection, + lo_iterator TYPE REF TO if_ixml_node_iterator, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_subrc TYPE sysubrc, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard relationship + ep_content = super->create_xl_sheet( io_worksheet = io_worksheet + iv_active = iv_active ). + +********************************************************************** +* STEP 2: modify XML adding the vbaProject relation + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + +* lo_collection = lo_document->get_elements_by_tag_name( 'fileVersion' ). +* lo_iterator = lo_collection->create_iterator( ). +* lo_element ?= lo_iterator->get_next( ). +* WHILE lo_element IS BOUND. +* lo_element->set_attribute_ns( name = lc_xml_attr_codename +* value = me->excel->zif_excel_book_vba_project~codename ). +* lo_element ?= lo_iterator->get_next( ). +* ENDWHILE. + + lo_collection = lo_document->get_elements_by_tag_name( 'sheetPr' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lo_element->set_attribute_ns( name = lc_xml_attr_codename + value = io_worksheet->zif_excel_sheet_vba_project~codename_pr ). + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + endmethod. + + + method CREATE_XL_WORKBOOK. + +** Constant node name + DATA: lc_xml_attr_codename TYPE string VALUE 'codeName'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_collection TYPE REF TO if_ixml_node_collection, + lo_iterator TYPE REF TO if_ixml_node_iterator, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_subrc TYPE sysubrc, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard relationship + ep_content = super->create_xl_workbook( ). + +********************************************************************** +* STEP 2: modify XML adding the vbaProject relation + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + lo_collection = lo_document->get_elements_by_tag_name( 'fileVersion' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lo_element->set_attribute_ns( name = lc_xml_attr_codename + value = me->excel->zif_excel_book_vba_project~codename ). + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + + lo_collection = lo_document->get_elements_by_tag_name( 'workbookPr' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lo_element->set_attribute_ns( name = lc_xml_attr_codename + value = me->excel->zif_excel_book_vba_project~codename_pr ). + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + method LOAD_DATA. + DATA: lo_columns TYPE REF TO cl_salv_columns_table, + lo_aggregations TYPE REF TO cl_salv_aggregations, + lo_sorts TYPE REF TO cl_salv_sorts, + lo_filters TYPE REF TO cl_salv_filters, + lo_functional TYPE REF TO cl_salv_functional_settings, + lo_display TYPE REF TO cl_salv_display_settings, + lo_selections TYPE REF TO cl_salv_selections. + + DATA: ls_vari TYPE disvariant, + lo_layout TYPE REF TO cl_salv_layout. + + DATA: lr_form_tol TYPE REF TO cl_salv_form, + lr_form_eol TYPE REF TO cl_salv_form. + + DATA lt_kkblo_fieldcat TYPE kkblo_t_fieldcat. + DATA ls_kkblo_layout TYPE kkblo_layout. + DATA lt_kkblo_filter TYPE kkblo_t_filter. + DATA lt_kkblo_sort TYPE kkblo_t_sortinfo. + + lo_layout = io_salv->get_layout( ) . + lo_columns = io_salv->get_columns( ). + lo_aggregations = io_salv->get_aggregations( ) . + lo_sorts = io_salv->get_sorts( ) . + lo_filters = io_salv->get_filters( ) . + lo_display = io_salv->get_display_settings( ) . + lo_functional = io_salv->get_functional_settings( ) . + + REFRESH: wt_fcat, + wt_sort, + wt_filt. + +* First update metadata if we can. + IF io_salv->is_offline( ) = abap_false. + io_salv->get_metadata( ) . + ELSE. +* If we are offline we need to build this. + cl_salv_controller_metadata=>get_variant( + EXPORTING + r_layout = lo_layout + CHANGING + s_variant = ls_vari ). + ENDIF. + +*... get the column information + wt_fcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog( + r_columns = lo_columns + r_aggregations = lo_aggregations ). + +*... get the layout information + cl_salv_controller_metadata=>get_lvc_layout( + EXPORTING + r_functional_settings = lo_functional + r_display_settings = lo_display + r_columns = lo_columns + r_aggregations = lo_aggregations + CHANGING + s_layout = ws_layo ). + +* the fieldcatalog is not complete yet! + CALL FUNCTION 'LVC_FIELDCAT_COMPLETE' + EXPORTING + i_complete = 'X' + i_refresh_buffer = space + i_buffer_active = space + is_layout = ws_layo + i_test = '1' + i_fcat_complete = 'X' + IMPORTING +* E_EDIT = + es_layout = ws_layo + CHANGING + ct_fieldcat = wt_fcat. + + IF ls_vari IS NOT INITIAL AND io_salv->is_offline( ) = abap_true. + CALL FUNCTION 'LVC_TRANSFER_TO_KKBLO' + EXPORTING + it_fieldcat_lvc = wt_fcat + is_layout_lvc = ws_layo + IMPORTING + et_fieldcat_kkblo = lt_kkblo_fieldcat + es_layout_kkblo = ls_kkblo_layout + TABLES + it_data = it_table + EXCEPTIONS + it_data_missing = 1 + it_fieldcat_lvc_missing = 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. + + CALL FUNCTION 'LT_VARIANT_LOAD' + EXPORTING +* I_TOOL = 'LT' + i_tabname = '1' +* I_TABNAME_SLAVE = + i_dialog = ' ' +* I_USER_SPECIFIC = ' ' +* I_DEFAULT = 'X' +* I_NO_REPTEXT_OPTIMIZE = +* I_VIA_GRID = + i_fcat_complete = 'X' + IMPORTING +* E_EXIT = + et_fieldcat = lt_kkblo_fieldcat + et_sort = lt_kkblo_sort + et_filter = lt_kkblo_filter + CHANGING + cs_layout = ls_kkblo_layout + ct_default_fieldcat = lt_kkblo_fieldcat + cs_variant = ls_vari + EXCEPTIONS + wrong_input = 1 + fc_not_complete = 2 + not_found = 3 + OTHERS = 4 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ENDIF. + + CALL FUNCTION 'LVC_TRANSFER_FROM_KKBLO' + EXPORTING +* I_TECH_COMPLETE = +* I_STRUCTURE_NAME = + it_fieldcat_kkblo = lt_kkblo_fieldcat + it_sort_kkblo = lt_kkblo_sort + it_filter_kkblo = lt_kkblo_filter +* IT_SPECIAL_GROUPS_KKBLO = +* IT_FILTERED_ENTRIES_KKBLO = +* IT_GROUPLEVELS_KKBLO = +* IS_SUBTOT_OPTIONS_KKBLO = + is_layout_kkblo = ls_kkblo_layout +* IS_REPREP_ID_KKBLO = +* I_CALLBACK_PROGRAM_KKBLO = +* IT_ADD_FIELDCAT = +* IT_EXCLUDING_KKBLO = +* IT_EXCEPT_QINFO_KKBLO = + IMPORTING + et_fieldcat_lvc = wt_fcat + et_sort_lvc = wt_sort + et_filter_lvc = wt_filt +* ET_SPECIAL_GROUPS_LVC = +* ET_FILTER_INDEX_LVC = +* ET_GROUPLEVELS_LVC = +* ES_TOTAL_OPTIONS_LVC = + es_layout_lvc = ws_layo +* ES_VARIANT_LVC = +* E_VARIANT_SAVE_LVC = +* ES_PRINT_INFO_LVC = +* ES_REPREP_LVC = +* E_REPREP_ACTIVE_LVC = +* ET_EXCLUDING_LVC = +* ET_EXCEPT_QINFO_LVC = + TABLES + it_data = it_table + EXCEPTIONS + it_data_missing = 1 + OTHERS = 2 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ENDIF. + + ELSE. +* ... get the sort information + wt_sort = cl_salv_controller_metadata=>get_lvc_sort( lo_sorts ). + +* ... get the filter information + wt_filt = cl_salv_controller_metadata=>get_lvc_filter( lo_filters ). + ENDIF. + + endmethod. + + + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + +TYPES: BEGIN OF ts_alv_types, + seoclass TYPE seoclsname, + clsname TYPE seoclsname, + END OF ts_alv_types, + tt_alv_types TYPE HASHED TABLE OF ts_alv_types WITH UNIQUE KEY seoclass. + +TYPES: BEGIN OF ts_sort_values, + fieldname TYPE fieldname, + row_int TYPE zexcel_cell_row, + value TYPE REF TO data, + new TYPE flag, + sort_level TYPE int4, + is_collapsed type flag, + END OF ts_sort_values, + + tt_sort_values TYPE HASHED TABLE OF ts_sort_values WITH UNIQUE KEY fieldname. +TYPES: BEGIN OF ts_subtotal_rows, + row_int TYPE zexcel_cell_row, + row_int_start TYPE zexcel_cell_row, + columnname TYPE fieldname, + END OF ts_subtotal_rows, + + tt_subtotal_rows TYPE HASHED TABLE OF ts_subtotal_rows WITH UNIQUE KEY row_int. + +TYPES: BEGIN OF ts_styles, + type TYPE char1, + alignment TYPE zexcel_alignment, + inttype TYPE inttype, + decimals TYPE int1, + style TYPE REF TO zcl_excel_style, + guid TYPE zexcel_cell_style, + END OF ts_styles, + + tt_styles TYPE HASHED TABLE OF ts_styles WITH UNIQUE KEY type alignment inttype decimals. + +TYPES: BEGIN OF ts_color_styles, + guid_old TYPE zexcel_cell_style, + fontcolor TYPE zexcel_style_color_argb, + fillcolor TYPE zexcel_style_color_argb, + style_new TYPE REF TO zcl_excel_style, + END OF ts_color_styles, + + tt_color_styles TYPE HASHED TABLE OF ts_color_styles WITH UNIQUE KEY guid_old fontcolor fillcolor. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + ABAP + SLIS + SOI + + + + + + + + + + + + + + + + + + + + + + + + + + + + method ASK_OPTION. + DATA: ls_sval TYPE sval, + lt_sval TYPE STANDARD TABLE OF sval, + l_returncode TYPE string, + lt_fields TYPE ddfields, + ls_fields TYPE dfies. + + FIELD-SYMBOLS: <fs> TYPE ANY. + + rs_option = ws_option. + + CALL FUNCTION 'DDIF_FIELDINFO_GET' + EXPORTING + tabname = 'ZEXCEL_S_CONVERTER_OPTION' +* FIELDNAME = ' ' +* LANGU = sy-langu +* LFIELDNAME = ' ' +* ALL_TYPES = ' ' +* GROUP_NAMES = ' ' +* UCLEN = +* IMPORTING +* X030L_WA = +* DDOBJTYPE = +* DFIES_WA = +* LINES_DESCR = + TABLES + dfies_tab = lt_fields +* FIXED_VALUES = + EXCEPTIONS + not_found = 1 + internal_error = 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. + + LOOP AT lt_fields INTO ls_fields. + ASSIGN COMPONENT ls_fields-fieldname OF STRUCTURE ws_option TO <fs>. + IF sy-subrc = 0. + CLEAR ls_sval. + ls_sval-tabname = ls_fields-tabname. + ls_sval-fieldname = ls_fields-fieldname. + ls_sval-value = <fs>. + ls_sval-field_attr = space. + ls_sval-field_obl = space. + ls_sval-comp_code = space. + ls_sval-fieldtext = ls_fields-scrtext_m. + ls_sval-comp_tab = space. + ls_sval-comp_field = space. + ls_sval-novaluehlp = space. + INSERT ls_sval INTO TABLE lt_sval. + ENDIF. + ENDLOOP. + + CALL FUNCTION 'POPUP_GET_VALUES' + EXPORTING +* NO_VALUE_CHECK = space + popup_title = 'Excel creation options'(008) +* START_COLUMN = '5' +* START_ROW = '5' + IMPORTING + returncode = l_returncode + TABLES + fields = lt_sval + EXCEPTIONS + error_in_fields = 1 + OTHERS = 2 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ELSE. + IF l_returncode = 'A'. + RAISE EXCEPTION TYPE zcx_excel. + ELSE. + LOOP AT lt_sval INTO ls_sval. + ASSIGN COMPONENT ls_sval-fieldname OF STRUCTURE ws_option TO <fs>. + IF sy-subrc = 0. + <fs> = ls_sval-value. + ENDIF. + ENDLOOP. + set_option( is_option = ws_option ) . + rs_option = ws_option. + ENDIF. + ENDIF. + endmethod. + + + + + method BIND_CELLS. + +* Do we need subtotals with grouping + READ TABLE wt_fieldcatalog TRANSPORTING NO FIELDS WITH KEY is_subtotalled = abap_true. + IF sy-subrc = 0 . + r_freeze_col = loop_subtotal( i_row_int = w_row_int + i_col_int = w_col_int ) . + ELSE. + r_freeze_col = loop_normal( i_row_int = w_row_int + i_col_int = w_col_int ) . + ENDIF. + + endmethod. + + + + + + method BIND_TABLE. + data: lt_field_catalog type zexcel_t_fieldcatalog, + ls_field_catalog type zexcel_s_fieldcatalog, + ls_fcat type zexcel_s_converter_fcat, + lo_col_dim type ref to zcl_excel_worksheet_columndime, + lo_row_dim type ref to zcl_excel_worksheet_rowdimensi, + l_col_int type zexcel_cell_column, + l_col_alpha type zexcel_cell_column_alpha, + ls_settings type zexcel_s_table_settings, + l_line type i. + + field-symbols: <fs_tab> type any table. + + assign wo_data->* to <fs_tab> . + + ls_settings-table_style = i_style_table. + ls_settings-top_left_column = zcl_excel_common=>convert_column2alpha( ip_column = w_col_int ). + ls_settings-top_left_row = w_row_int. + ls_settings-show_row_stripes = ws_layout-is_stripped. + + describe table wt_fieldcatalog lines l_line. + l_line = l_line + 1 + w_col_int. + ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( ip_column = l_line ). + + describe table <fs_tab> lines l_line. + ls_settings-bottom_right_row = l_line + 1 + w_row_int. + sort wt_fieldcatalog by position. + loop at wt_fieldcatalog into ls_fcat. + move-corresponding ls_fcat to ls_field_catalog. + ls_field_catalog-dynpfld = abap_true. + insert ls_field_catalog into table lt_field_catalog. + endloop. + + wo_worksheet->bind_table( + exporting + ip_table = <fs_tab> + it_field_catalog = lt_field_catalog + is_table_settings = ls_settings + importing + es_table_settings = ls_settings + ). + loop at wt_fieldcatalog into ls_fcat. + l_col_int = w_col_int + ls_fcat-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). +* Freeze panes + if ls_fcat-fix_column = abap_true. + add 1 to r_freeze_col. + endif. +* Now let's check for optimized + if ls_fcat-is_optimized = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + endif. +* Now let's check for visible + if ls_fcat-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + endif. + endloop. + + endmethod. + + + method CLASS_CONSTRUCTOR. + DATA: ls_objects TYPE ts_alv_types. + DATA: ls_option TYPE zexcel_s_converter_option, + l_uname TYPE sy-uname. + + GET PARAMETER ID 'ZUS' FIELD l_uname. + IF l_uname IS INITIAL OR l_uname = space. + l_uname = sy-uname. + ENDIF. + +* Object CL_GUI_ALV_GRID + ls_objects-seoclass = 'CL_GUI_ALV_GRID'. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_ALV_GRID'. + INSERT ls_objects INTO TABLE wt_objects. + +* Object CL_SALV_TABLE + ls_objects-seoclass = 'CL_SALV_TABLE'. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_SALV_TABLE'. + INSERT ls_objects INTO TABLE wt_objects. + +* Object CL_SALV_RESULT + ls_objects-seoclass = 'CL_SALV_EX_RESULT_DATA_TABLE '. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_RESULT_EX'. + INSERT ls_objects INTO TABLE wt_objects. +* Object CL_SALV_WD_RESULT + ls_objects-seoclass = 'CL_SALV_WD_RESULT_DATA_TABLE '. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_RESULT_WD'. + INSERT ls_objects INTO TABLE wt_objects. + + CONCATENATE 'EXCEL_' sy-uname INTO ws_indx-srtfd. + + IMPORT p1 = ls_option FROM DATABASE indx(xl) TO ws_indx ID ws_indx-srtfd. + + IF sy-subrc = 0. + ws_option = ls_option. + ELSE. + init_option( ) . + ENDIF. + + endmethod. + + + method CLEAN_FIELDCATALOG. + DATA: l_position TYPE int1. + + FIELD-SYMBOLS: <fs_sfcat> TYPE zexcel_s_converter_fcat. + + SORT wt_fieldcatalog BY position col_id. + + CLEAR l_position. + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + ADD 1 TO l_position. + <fs_sfcat>-position = l_position. +* Default stype with alignment and format + <fs_sfcat>-style_hdr = get_style( i_type = c_type_hdr + i_alignment = <fs_sfcat>-alignment ). + IF ws_layout-is_stripped = abap_true. + <fs_sfcat>-style_stripped = get_style( i_type = c_type_str + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + ENDIF. + <fs_sfcat>-style_normal = get_style( i_type = c_type_nor + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + <fs_sfcat>-style_subtotal = get_style( i_type = c_type_sub + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + <fs_sfcat>-style_total = get_style( i_type = c_type_tot + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + ENDLOOP. + + endmethod. + + + + + + + + + + + + + method CONVERT. + + IF is_option IS SUPPLIED. + ws_option = is_option. + ENDIF. + + TRY. + execute_converter( EXPORTING io_object = io_alv + it_table = it_table ) . + ENDTRY. + + IF io_worksheet IS SUPPLIED AND io_worksheet IS BOUND. + wo_worksheet = io_worksheet. + ENDIF. + IF co_excel IS SUPPLIED. + IF co_excel IS NOT BOUND. + CREATE OBJECT co_excel. + co_excel->zif_excel_book_properties~creator = sy-uname. + ENDIF. + wo_excel = co_excel. + ENDIF. + +* Move table to data object and clean it up + IF wt_fieldcatalog IS NOT INITIAL. + create_table( ). + ELSE. + wo_data = wo_table . + ENDIF. + + IF wo_excel IS NOT BOUND. + CREATE OBJECT wo_excel. + wo_excel->zif_excel_book_properties~creator = sy-uname. + ENDIF. + IF wo_worksheet IS NOT BOUND. + " Get active sheet + wo_worksheet = wo_excel->get_active_worksheet( ). + wo_worksheet->set_title( ip_title = 'Sheet1'(001) ). + ENDIF. + + IF i_row_int <= 0. + w_row_int = 1. + ELSE. + w_row_int = i_row_int. + ENDIF. + IF i_column_int <= 0. + w_col_int = 1. + ELSE. + w_col_int = i_column_int. + ENDIF. + + create_worksheet( i_table = i_table + i_style_table = i_style_table ) . + + endmethod. + + + + + + method CREATE_COLOR_STYLE. + DATA: ls_styles TYPE ts_styles. + DATA: lo_style TYPE REF TO zcl_excel_style. + + READ TABLE wt_styles INTO ls_styles WITH KEY guid = i_style. + IF sy-subrc = 0. + lo_style = wo_excel->add_new_style( ). +* lo_style->borders = ls_styles-style->borders. +* lo_style->protection = ls_styles-style->protection. + lo_style->font->bold = ls_styles-style->font->bold. + lo_style->alignment->horizontal = ls_styles-style->alignment->horizontal. + lo_style->number_format->format_code = ls_styles-style->number_format->format_code. + + lo_style->font->color-rgb = is_colors-fontcolor. + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = is_colors-fillcolor. + + ro_style = lo_style. + ENDIF. + endmethod. + + + + + + + + method CREATE_FORMULAR_SUBTOTAL. + data: l_row_alpha_start type string, + l_row_alpha_end type string, + l_func_num type string. + + l_row_alpha_start = i_row_int_start. + l_row_alpha_end = i_row_int_end. + + l_func_num = get_function_number( i_totals_function = i_totals_function ). + concatenate 'SUBTOTAL(' l_func_num ',' i_column l_row_alpha_start ':' i_column l_row_alpha_end ')' into r_formula. + endmethod. + + + + + + + method CREATE_FORMULAR_TOTAL. + data: l_row_alpha type string, + l_row_e_alpha type string. + + l_row_alpha = w_row_int + 1. + l_row_e_alpha = i_row_int. + + concatenate i_totals_function '(' i_column l_row_alpha ':' i_column l_row_e_alpha ')' into r_formula. + endmethod. + + + + method CREATE_PATH. + DATA: l_sep TYPE c , + l_path TYPE string, + l_return TYPE i . + + CLEAR r_path. + + " Save the file + cl_gui_frontend_services=>get_sapgui_workdir( + CHANGING + sapworkdir = l_path + EXCEPTIONS + get_sapworkdir_failed = 1 + cntl_error = 2 + error_no_gui = 3 + not_supported_by_gui = 4 + ). + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + CONCATENATE 'Excel_' w_fcount '.xlsx' INTO r_path. + ELSE. + DO. + ADD 1 TO w_fcount. +*-obtain file separator character--------------------------------------- + CALL METHOD cl_gui_frontend_services=>get_file_separator + CHANGING + file_separator = l_sep + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + l_sep = ''. + ENDIF. + + CONCATENATE l_path l_sep 'Excel_' w_fcount '.xlsx' INTO r_path. + + IF cl_gui_frontend_services=>file_exist( file = r_path ) = abap_true. + cl_gui_frontend_services=>file_delete( EXPORTING filename = r_path + CHANGING rc = l_return + EXCEPTIONS OTHERS = 1 ). + IF sy-subrc = 0 . + RETURN. + ENDIF. + ELSE. + RETURN. + ENDIF. + ENDDO. + ENDIF. + + endmethod. + + + + + method CREATE_STYLE_HDR. + data: lo_style type ref to zcl_excel_style. + + lo_style = wo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + lo_style->font->color-rgb = zcl_excel_style_color=>c_white. + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = 'FF4F81BD'. + if i_alignment is supplied and i_alignment is not initial. + lo_style->alignment->horizontal = i_alignment. + endif. + ro_style = lo_style . + endmethod. + + + + + + + method CREATE_STYLE_NORMAL. + DATA: lo_style TYPE REF TO zcl_excel_style, + l_format TYPE zexcel_number_format. + + IF i_inttype IS SUPPLIED AND i_inttype IS NOT INITIAL. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + ENDIF. + IF l_format IS NOT INITIAL OR + ( i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL ) . + + lo_style = wo_excel->add_new_style( ). + + IF i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL. + lo_style->alignment->horizontal = i_alignment. + ENDIF. + + IF l_format IS NOT INITIAL. + lo_style->number_format->format_code = l_format. + ENDIF. + + ro_style = lo_style . + + ENDIF. + endmethod. + + + + + + + method CREATE_STYLE_STRIPPED. + data: lo_style type ref to zcl_excel_style. + data: l_format type zexcel_number_format. + + lo_style = wo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = 'FFDBE5F1'. + if i_alignment is supplied and i_alignment is not initial. + lo_style->alignment->horizontal = i_alignment. + endif. + if i_inttype is supplied and i_inttype is not initial. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + if l_format is not initial. + lo_style->number_format->format_code = l_format. + endif. + endif. + ro_style = lo_style. + + endmethod. + + + + + + + method CREATE_STYLE_SUBTOTAL. + data: lo_style type ref to zcl_excel_style. + data: l_format type zexcel_number_format. + + lo_style = wo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + + if i_alignment is supplied and i_alignment is not initial. + lo_style->alignment->horizontal = i_alignment. + endif. + if i_inttype is supplied and i_inttype is not initial. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + if l_format is not initial. + lo_style->number_format->format_code = l_format. + endif. + endif. + + ro_style = lo_style . + + endmethod. + + + + + + + method CREATE_STYLE_TOTAL. + DATA: lo_style TYPE REF TO zcl_excel_style. + DATA: l_format TYPE zexcel_number_format. + + lo_style = wo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + + CREATE OBJECT lo_style->borders->top. + lo_style->borders->top->border_style = zcl_excel_style_border=>c_border_thin. + lo_style->borders->top->border_color-rgb = zcl_excel_style_color=>c_black. + + CREATE OBJECT lo_style->borders->right. + lo_style->borders->right->border_style = zcl_excel_style_border=>c_border_none. + lo_style->borders->right->border_color-rgb = zcl_excel_style_color=>c_black. + + CREATE OBJECT lo_style->borders->down. + lo_style->borders->down->border_style = zcl_excel_style_border=>c_border_double. + lo_style->borders->down->border_color-rgb = zcl_excel_style_color=>c_black. + + CREATE OBJECT lo_style->borders->left. + lo_style->borders->left->border_style = zcl_excel_style_border=>c_border_none. + lo_style->borders->left->border_color-rgb = zcl_excel_style_color=>c_black. + + IF i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL. + lo_style->alignment->horizontal = i_alignment. + ENDIF. + IF i_inttype IS SUPPLIED AND i_inttype IS NOT INITIAL. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + IF l_format IS NOT INITIAL. + lo_style->number_format->format_code = l_format. + ENDIF. + ENDIF. + + ro_style = lo_style . + + endmethod. + + + method CREATE_TABLE. + TYPES: BEGIN OF ts_output, + fieldname TYPE fieldname, + function TYPE funcname, + END OF ts_output. + + DATA: lo_data TYPE REF TO data. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + lt_components_tab TYPE cl_abap_structdescr=>component_table, + ls_components TYPE abap_componentdescr, + lo_table TYPE REF TO cl_abap_tabledescr, + lo_struc TYPE REF TO cl_abap_structdescr, + lt_fieldcatalog TYPE zexcel_t_converter_fcat. + + FIELD-SYMBOLS: <fs_scat> TYPE zexcel_s_converter_fcat, + <fs_stab> TYPE ANY, + <fs_ttab> TYPE STANDARD TABLE, + <fs> TYPE ANY, + <fs_table> TYPE STANDARD TABLE. + + SORT wt_fieldcatalog BY position. + ASSIGN wo_table->* TO <fs_table>. + + READ TABLE <fs_table> ASSIGNING <fs_stab> INDEX 1. + IF sy-subrc EQ 0 . + LOOP AT wt_fieldcatalog ASSIGNING <fs_scat>. + ASSIGN COMPONENT <fs_scat>-columnname OF STRUCTURE <fs_stab> TO <fs>. + IF sy-subrc = 0. + ls_components-name = <fs_scat>-columnname. + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). + CATCH cx_sy_move_cast_error. + CLEAR lo_addit. + DELETE TABLE wt_fieldcatalog FROM <fs_scat>. + ENDTRY. + IF lo_addit IS BOUND. + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ENDIF. + ENDIF. + ENDLOOP. + IF lt_components_tab IS NOT INITIAL. + "create new line type + TRY. + lo_struc = cl_abap_structdescr=>create( P_COMPONENTS = lt_components_tab + P_STRICT = abap_false ). + CATCH cx_sy_struct_creation. + RETURN. " We can not do anything in this case. + ENDTRY. + + lo_table = cl_abap_tabledescr=>create( lo_struc ). + + CREATE DATA wo_data TYPE HANDLE lo_table. + CREATE DATA lo_data TYPE HANDLE lo_struc. + + ASSIGN wo_data->* TO <fs_ttab>. + ASSIGN lo_data->* TO <fs_stab>. + LOOP AT <fs_table> ASSIGNING <fs>. + CLEAR <fs_stab>. + MOVE-CORRESPONDING <fs> TO <fs_stab>. + APPEND <fs_stab> TO <fs_ttab>. + ENDLOOP. + ENDIF. + ENDIF. + + endmethod. + + + + + + method CREATE_TEXT_SUBTOTAL. + DATA: l_string(256) TYPE c, + l_func TYPE string. + + CASE i_totals_function. + WHEN zcl_excel_table=>totals_function_sum. " Total + l_func = 'Total'(003). + WHEN zcl_excel_table=>totals_function_min. " Minimum + l_func = 'Minimum'(004). + WHEN zcl_excel_table=>totals_function_max. " Maximum + l_func = 'Maximum'(005). + WHEN zcl_excel_table=>totals_function_average. " Mean Value + l_func = 'Average'(006). + WHEN zcl_excel_table=>totals_function_count. " Count + l_func = 'Count'(007). + WHEN OTHERS. + CLEAR l_func. + ENDCASE. + + WRITE i_value TO l_string. + + CONCATENATE l_string l_func INTO r_text SEPARATED BY space. + + endmethod. + + + + + + method CREATE_WORKSHEET. + DATA: l_freeze_col TYPE i. + DATA: l_guid TYPE oltpguid16. + + IF wo_data IS BOUND AND wo_worksheet IS BOUND. + + wo_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. " By default is on + + IF wt_fieldcatalog IS INITIAL. + set_fieldcatalog( ) . + ELSE. + clean_fieldcatalog( ) . + ENDIF. + + IF i_table = abap_true. + l_freeze_col = bind_table( i_style_table = i_style_table ) . + ELSE. +* Let's check for filter. + IF wt_filter IS NOT INITIAL. + wo_autofilter = wo_excel->add_new_autofilter( io_sheet = wo_worksheet ). + l_freeze_col = bind_cells( ) . + set_autofilter_area( ) . + ELSE. + l_freeze_col = bind_cells( ) . + ENDIF. + + ENDIF. + +* Check for freeze panes + IF ws_layout-is_fixed = abap_true. + IF l_freeze_col = 0. + l_freeze_col = w_col_int. + ENDIF. + wo_worksheet->freeze_panes( EXPORTING ip_num_columns = l_freeze_col + ip_num_rows = w_row_int ) . + ENDIF. + ENDIF. + + endmethod. + + + + + + method EXECUTE_CONVERTER. + DATA: lt_fieldcatalog TYPE zexcel_t_fieldcatalog, + ls_fieldcatalog TYPE zexcel_s_converter_fcat, + lo_if TYPE REF TO zif_excel_converter, + ls_types TYPE ts_alv_types, + lo_addit TYPE REF TO cl_abap_classdescr. + + IF io_object IS BOUND. + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_object_ref( io_object ). + CATCH cx_sy_move_cast_error. + RAISE EXCEPTION TYPE zcx_excel. + ENDTRY. + ls_types-seoclass = lo_addit->get_relative_name( ). + READ TABLE wt_objects INTO ls_types WITH TABLE KEY seoclass = ls_types-seoclass. + IF sy-subrc = 0. + CREATE OBJECT lo_if TYPE (ls_types-clsname). + + TRY. + lo_if->create_fieldcatalog( + EXPORTING + is_option = ws_option + io_object = io_object + it_table = it_table + IMPORTING + es_layout = ws_layout + et_fieldcatalog = wt_fieldcatalog + eo_table = wo_table + et_colors = wt_colors + et_filter = wt_filter + ). + ENDTRY. +* data lines of highest level. + IF ws_layout-max_subtotal_level > 0. + ADD 1 TO ws_layout-max_subtotal_level. + ENDIF. + ELSE. + RAISE EXCEPTION TYPE zcx_excel. + ENDIF. + ELSE. + REFRESH wt_fieldcatalog. + GET REFERENCE OF it_table INTO wo_table. + ENDIF. + + endmethod. + + + + + + + method GET_COLOR_STYLE. + DATA: ls_colors TYPE zexcel_s_converter_col, + ls_color_styles TYPE ts_color_styles, + lo_style TYPE REF TO zcl_excel_style. + + r_style = i_style. " Default we change nothing + + IF wt_colors IS NOT INITIAL. +* Full line has color + READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row + columnname = space. + IF sy-subrc = 0. + READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style + fontcolor = ls_colors-fontcolor + fillcolor = ls_colors-fillcolor. + IF sy-subrc = 0. + r_style = ls_color_styles-style_new->get_guid( ). + ELSE. + lo_style = create_color_style( i_style = i_style + is_colors = ls_colors ) . + r_style = lo_style->get_guid( ) . + ls_color_styles-guid_old = i_style. + ls_color_styles-fontcolor = ls_colors-fontcolor. + ls_color_styles-fillcolor = ls_colors-fillcolor. + ls_color_styles-style_new = lo_style. + INSERT ls_color_styles INTO TABLE wt_color_styles. + ENDIF. + ELSE. +* Only field has color + READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row + columnname = i_fieldname. + IF sy-subrc = 0. + READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style + fontcolor = ls_colors-fontcolor + fillcolor = ls_colors-fillcolor. + IF sy-subrc = 0. + r_style = ls_color_styles-style_new->get_guid( ). + ELSE. + lo_style = create_color_style( i_style = i_style + is_colors = ls_colors ) . + ls_color_styles-guid_old = i_style. + ls_color_styles-fontcolor = ls_colors-fontcolor. + ls_color_styles-fillcolor = ls_colors-fillcolor. + ls_color_styles-style_new = lo_style. + INSERT ls_color_styles INTO TABLE wt_color_styles. + r_style = ls_color_styles-style_new->get_guid( ). + ENDIF. + ELSE. + r_style = i_style. + ENDIF. + ENDIF. + ELSE. + r_style = i_style. + ENDIF. + + endmethod. + + + + + + method GET_FILE. + data: lo_excel_writer type ref to zif_excel_writer, + lo_excel type ref to zcl_excel. + + data: ls_seoclass type seoclass. + + + if wo_excel is bound. + create object lo_excel_writer type zcl_excel_writer_2007. + e_file = lo_excel_writer->write_file( wo_excel ). + + select single * into ls_seoclass + from seoclass + where clsname = 'CL_BCS_CONVERT'. + + if sy-subrc = 0. + call method (ls_seoclass-clsname)=>xstring_to_solix + exporting + iv_xstring = e_file + receiving + et_solix = et_file. + e_bytecount = xstrlen( e_file ). + else. + " Convert to binary + call function 'SCMS_XSTRING_TO_BINARY' + exporting + buffer = e_file + importing + output_length = e_bytecount + tables + binary_tab = et_file. + endif. + endif. + + endmethod. + + + + + method GET_FUNCTION_NUMBER. +*Number Function +*1 AVERAGE +*2 COUNT +*3 COUNTA +*4 MAX +*5 MIN +*6 PRODUCT +*7 STDEV +*8 STDEVP +*9 SUM +*10 VAR +*11 VARP + + case i_totals_function. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_SUM. " Total + r_function_number = 9. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MIN. " Minimum + r_function_number = 5. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MAX. " Maximum + r_function_number = 4. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_AVERAGE. " Mean Value + r_function_number = 1. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_count. " Count + r_function_number = 2. + when others. + clear r_function_number. + endcase. + endmethod. + + + + method GET_OPTION. + + rs_option = ws_option. + + endmethod. + + + + + + + + method GET_STYLE. + DATA: ls_styles TYPE ts_styles, + lo_style TYPE REF TO zcl_excel_style. + + CLEAR r_style. + + READ TABLE wt_styles INTO ls_styles WITH TABLE KEY type = i_type + alignment = i_alignment + inttype = i_inttype + decimals = i_decimals. + IF sy-subrc = 0. + r_style = ls_styles-guid. + ELSE. + CASE i_type. + WHEN c_type_hdr. " Header + lo_style = create_style_hdr( i_alignment = i_alignment ). + WHEN c_type_str. "Stripped + lo_style = create_style_stripped( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_nor. "Normal + lo_style = create_style_normal( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_sub. "Subtotals + lo_style = create_style_subtotal( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_tot. "Totals + lo_style = create_style_total( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + ENDCASE. + IF lo_style IS NOT INITIAL. + r_style = lo_style->get_guid( ). + ls_styles-type = i_type. + ls_styles-alignment = i_alignment. + ls_styles-inttype = i_inttype. + ls_styles-decimals = i_decimals. + ls_styles-guid = r_style. + ls_styles-style = lo_style. + INSERT ls_styles INTO TABLE wt_styles. + ENDIF. + ENDIF. + endmethod. + + + method INIT_OPTION. + + ws_option-filter = abap_true. + ws_option-hidenc = abap_true. + ws_option-subtot = abap_true. + + endmethod. + + + + + + + method LOOP_NORMAL. + DATA: lo_data TYPE REF TO data, + l_row_header TYPE zexcel_cell_row VALUE '2', + l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + l_row_int_start TYPE zexcel_cell_row, + l_row_int_end TYPE zexcel_cell_row, + l_row_int TYPE zexcel_cell_row, + l_col_int TYPE zexcel_cell_column, + l_col_alpha TYPE zexcel_cell_column_alpha, + l_col_alpha_start TYPE zexcel_cell_column_alpha, + l_cell_value TYPE zexcel_cell_value, + l_s_color TYPE abap_bool, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + l_formula TYPE zexcel_cell_formula, + l_style TYPE zexcel_cell_style, + l_cells TYPE i, + l_count TYPE i, + l_table_row TYPE i. + + FIELD-SYMBOLS: <fs_stab> TYPE ANY, + <fs_tab> TYPE STANDARD TABLE, + <fs_sfcat> TYPE zexcel_s_converter_fcat, + <fs_fldval> TYPE ANY, + <fs_cell_value> TYPE zexcel_cell_value. + + ASSIGN wo_data->* TO <fs_tab> . + + DESCRIBE TABLE wt_fieldcatalog LINES l_cells. + DESCRIBE TABLE <fs_tab> LINES l_count. + l_cells = l_cells * l_count. + +* It is better to loop column by column + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + l_row_int = i_row_int. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + +* Freeze panes + IF <fs_sfcat>-fix_column = abap_true. + ADD 1 TO r_freeze_col. + ENDIF. + l_s_color = abap_true. + + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + +* Only if the Header is required create it. + IF ws_option-hidehd IS INITIAL. + " First of all write column header + l_cell_value = <fs_sfcat>-scrtext_m. + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_style = <fs_sfcat>-style_hdr ). + ADD 1 TO l_row_int. + ENDIF. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_table_row = sy-tabix. +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. +* Now let's write the cell values + IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_stripped ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + CLEAR l_s_color. + ELSE. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_normal ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + l_s_color = abap_true. + ENDIF. + READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row + columnname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + wo_worksheet->get_cell( EXPORTING + ip_column = l_col_alpha + ip_row = l_row_int + IMPORTING + ep_value = l_cell_value ). + wo_autofilter->set_value( i_column = l_col_int + i_value = l_cell_value ). + ENDIF. + ADD 1 TO l_row_int. + ENDLOOP. +* Now let's check for optimized + IF <fs_sfcat>-is_optimized = abap_true . + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + ENDIF. +* Now let's check for visible + IF <fs_sfcat>-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + ENDIF. +* Now let's check for total versus subtotal. + IF <fs_sfcat>-totals_function IS NOT INITIAL. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_total( i_row_int = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_total ). + ENDIF. + ENDLOOP. + endmethod. + + + + + + + method LOOP_SUBTOTAL. + + DATA: lo_data TYPE REF TO data, + l_row_header TYPE zexcel_cell_row VALUE '2', + l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + l_row_int_start TYPE zexcel_cell_row, + l_row_int_end TYPE zexcel_cell_row, + l_row_int TYPE zexcel_cell_row, + l_col_int TYPE zexcel_cell_column, + l_col_alpha TYPE zexcel_cell_column_alpha, + l_col_alpha_start TYPE zexcel_cell_column_alpha, + l_cell_value TYPE zexcel_cell_value, + l_s_color TYPE abap_bool, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + l_formula TYPE zexcel_cell_formula, + l_style TYPE zexcel_cell_style, + l_subtotalled TYPE flag, + l_text TYPE string, + ls_sort_values TYPE ts_sort_values, + ls_subtotal_rows TYPE ts_subtotal_rows, + l_sort_level TYPE int4, + l_hidden TYPE int4, + l_line TYPE i, + l_guid TYPE guid_22, + l_tabix TYPE sy-tabix, + l_cells TYPE i, + l_count TYPE i, + l_table_row TYPE i, + lt_fcat TYPE zexcel_t_converter_fcat. + + FIELD-SYMBOLS: <fs_stab> TYPE ANY, + <fs_tab> TYPE STANDARD TABLE, + <fs_sfcat> TYPE zexcel_s_converter_fcat, + <fs_fldval> TYPE ANY, + <fs_sortval> TYPE ANY, + <fs_sortv> TYPE ts_sort_values, + <fs_cell_value> TYPE zexcel_cell_value. + + ASSIGN wo_data->* TO <fs_tab> . + + REFRESH: wt_sort_values, + wt_subtotal_rows. + + DESCRIBE TABLE wt_fieldcatalog LINES l_cells. + DESCRIBE TABLE <fs_tab> LINES l_count. + l_cells = l_cells * l_count. + + READ TABLE <fs_tab> ASSIGNING <fs_stab> INDEX 1. + IF sy-subrc = 0. + l_row_int = i_row_int + 1. + lt_fcat = wt_fieldcatalog. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. + ls_sort_values-fieldname = <fs_sfcat>-columnname. + ls_sort_values-row_int = l_row_int. + ls_sort_values-sort_level = <fs_sfcat>-sort_level. + ls_sort_values-is_collapsed = <fs_sfcat>-is_collapsed. + CREATE DATA ls_sort_values-value LIKE <fs_fldval>. + ASSIGN ls_sort_values-value->* TO <fs_sortval>. + <fs_sortval> = <fs_fldval>. + INSERT ls_sort_values INTO TABLE wt_sort_values. + ENDLOOP. + ENDIF. + l_row_int = i_row_int. +* Let's check if we need to hide a sort level. + DESCRIBE TABLE wt_sort_values LINES l_line. + IF l_line <= 1. + CLEAR l_hidden. + ELSE. + LOOP AT wt_sort_values INTO ls_sort_values WHERE is_collapsed = abap_false. + IF l_hidden < ls_sort_values-sort_level. + l_hidden = ls_sort_values-sort_level. + ENDIF. + ENDLOOP. + ENDIF. + ADD 1 TO l_hidden. " As this is the first level we show. +* First loop without formular only addtional rows with subtotal text. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + ADD 1 TO l_row_int. " 1 is for header row. + l_row_int_start = l_row_int. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. + IF sy-subrc = 0. + READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + ASSIGN <fs_sortv>-value->* TO <fs_sortval>. + IF <fs_sortval> <> <fs_fldval> OR <fs_sortv>-new = abap_true. +* First let's remmember the subtotal values as it has to appear later. + ls_subtotal_rows-row_int = l_row_int. + ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. + ls_subtotal_rows-columnname = <fs_sfcat>-columnname. + INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. +* Now let's write the subtotal line + l_cell_value = create_text_subtotal( i_value = <fs_sortval> + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = <fs_sfcat>-sort_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. +* Now let's change the key + ADD 1 TO l_row_int. + <fs_sortval> = <fs_fldval>. + <fs_sortv>-new = abap_false. + l_line = <fs_sortv>-sort_level. + LOOP AT wt_sort_values ASSIGNING <fs_sortv> WHERE sort_level >= l_line. + <fs_sortv>-row_int = l_row_int. + ENDLOOP. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + ENDLOOP. + ADD 1 TO l_row_int. + l_row_int_start = l_row_int. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + ASSIGN <fs_sortv>-value->* TO <fs_sortval>. + ls_subtotal_rows-row_int = l_row_int. + ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. + ls_subtotal_rows-columnname = <fs_sfcat>-columnname. + INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. +* First let's write the value as it has to appear. + l_cell_value = create_text_subtotal( i_value = <fs_sortval> + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + + l_sort_level = <fs_sfcat>-sort_level. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. + ADD 1 TO l_row_int. + ENDIF. + ENDLOOP. +* Let's write the Grand total + l_sort_level = 0. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . +* lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . Not on grand total + + l_text = create_text_subtotal( i_value = 'Grand'(002) + i_totals_function = <fs_sfcat>-totals_function ). + + l_col_alpha_start = zcl_excel_common=>convert_column2alpha( i_col_int ). + wo_worksheet->set_cell( ip_column = l_col_alpha_start + ip_row = l_row_int + ip_value = l_text + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + +* It is better to loop column by column second time around +* Second loop with formular and data. + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + l_row_int = i_row_int. + l_col_int = i_col_int + <fs_sfcat>-position - 1. +* Freeze panes + IF <fs_sfcat>-fix_column = abap_true. + ADD 1 TO r_freeze_col. + ENDIF. + l_s_color = abap_true. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + " First of all write column header + l_cell_value = <fs_sfcat>-scrtext_m. + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_hdr ). + ADD 1 TO l_row_int. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_table_row = sy-tabix. +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. +* Let's check for subtotal lines + DO. + READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + DO. + READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + l_row_int_start = ls_subtotal_rows-row_int_start. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + ENDIF. + ADD 1 TO l_row_int. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + ADD 1 TO l_row_int. + ENDIF. + ELSE. + EXIT. + ENDIF. + ENDDO. +* Let's set the row dimension values + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = ws_layout-max_subtotal_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim->set_visible( ip_visible = abap_false ) . + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. +* Now let's write the cell values + IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_stripped ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + CLEAR l_s_color. + ELSE. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_normal ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + l_s_color = abap_true. + ENDIF. + READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row + columnname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + wo_worksheet->get_cell( EXPORTING + ip_column = l_col_alpha + ip_row = l_row_int + IMPORTING + ep_value = l_cell_value ). + wo_autofilter->set_value( i_column = l_col_int + i_value = l_cell_value ). + ENDIF. + ADD 1 TO l_row_int. + ENDLOOP. +* Let's check for subtotal lines + DO. + READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + DO. + READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + l_row_int_start = ls_subtotal_rows-row_int_start. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). + ENDIF. + ADD 1 TO l_row_int. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + ADD 1 TO l_row_int. + ENDIF. + ELSE. + EXIT. + ENDIF. + ENDDO. +* Now let's check for Grand total + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + l_row_int_start = i_row_int + 1. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + ENDIF. +* Now let's check for optimized + IF <fs_sfcat>-is_optimized = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + ENDIF. +* Now let's check for visible + IF <fs_sfcat>-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + ENDLOOP. + + endmethod. + + + method OPEN_FILE. + data: l_bytecount type i, + lt_file type solix_tab, + l_dir type string, + l_sep type c. + + field-symbols: <fs_data> type any table. + + assign wo_data->* to <fs_data>. + +* catch zcx_excel . +*endtry. + if wo_excel is bound. + get_file( importing e_bytecount = l_bytecount + et_file = lt_file ) . + + l_dir = create_path( ) . + + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_dir + filetype = 'BIN' + changing data_tab = lt_file ). + cl_gui_frontend_services=>execute( + exporting + document = l_dir +* application = +* parameter = +* default_directory = +* maximized = +* minimized = +* synchronous = +* operation = 'OPEN' + exceptions + cntl_error = 1 + error_no_gui = 2 + bad_parameter = 3 + file_not_found = 4 + path_not_found = 5 + file_extension_unknown = 6 + error_execute_failed = 7 + synchronous_failed = 8 + not_supported_by_gui = 9 + ). + if sy-subrc <> 0. + message id sy-msgid type sy-msgty number sy-msgno + with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + endif. + + endif. + + + endmethod. + + + method SET_AUTOFILTER_AREA. + DATA: ls_area TYPE zexcel_s_autofilter_area, + l_lines TYPE i, + lt_values TYPE zexcel_t_autofilter_values, + ls_values TYPE zexcel_s_autofilter_values. + +* Let's check for filter. + IF wo_autofilter IS BOUND. + ls_area-row_start = 1. + lt_values = wo_autofilter->get_values( ) . + SORT lt_values BY column ASCENDING. + DESCRIBE TABLE lt_values LINES l_lines. + READ TABLE lt_values INTO ls_values INDEX 1. + IF sy-subrc = 0. + ls_area-col_start = ls_values-column. + ENDIF. + READ TABLE lt_values INTO ls_values INDEX l_lines. + IF sy-subrc = 0. + ls_area-col_end = ls_values-column. + ENDIF. + wo_autofilter->set_filter_area( is_area = ls_area ) . + ENDIF. + + endmethod. + + + + + + method SET_CELL_FORMAT. + DATA: l_format TYPE zexcel_number_format. + + CLEAR r_format. + CASE i_inttype. + WHEN cl_abap_typedescr=>typekind_date. + r_format = wo_worksheet->get_default_excel_date_format( ). + WHEN cl_abap_typedescr=>typekind_time. + r_format = wo_worksheet->get_default_excel_time_format( ). + WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. + IF i_decimals > 0 . + l_format = '#,##0.'. + DO i_decimals TIMES. + CONCATENATE l_format '0' INTO l_format. + ENDDO. + r_format = l_format. + ENDIF. + WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. + r_format = '#,##0'. + ENDCASE. + + endmethod. + + + method SET_FIELDCATALOG. + + DATA: lr_data TYPE REF TO data, + lo_structdescr TYPE REF TO cl_abap_structdescr, + lt_dfies TYPE ddfields, + ls_dfies TYPE dfies, + ls_fieldcatalog TYPE zexcel_s_fieldcatalog. + DATA: ls_fcat TYPE zexcel_s_converter_fcat. + + FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. + + ASSIGN wo_data->* TO <fs_tab> . + + CREATE DATA lr_data LIKE LINE OF <fs_tab>. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + + LOOP AT lt_dfies INTO ls_dfies. + MOVE-CORRESPONDING ls_dfies TO ls_fcat. + ls_fcat-columnname = ls_dfies-fieldname. + INSERT ls_fcat INTO TABLE wt_fieldcatalog. + ENDLOOP. + + clean_fieldcatalog( ). + + endmethod. + + + + method SET_OPTION. + + IF ws_indx-begdt IS INITIAL. + ws_indx-begdt = sy-datum. + ENDIF. + + ws_indx-aedat = sy-datum. + ws_indx-usera = sy-uname. + ws_indx-pgmid = sy-cprog. + + EXPORT p1 = is_option TO DATABASE indx(xl) FROM ws_indx ID ws_indx-srtfd. + + IF sy-subrc = 0. + ws_option = is_option. + ENDIF. + + endmethod. + + + + method WRITE_FILE. + data: l_bytecount type i, + lt_file type solix_tab, + l_dir type string. + + field-symbols: <fs_data> type any table. + + assign wo_data->* to <fs_data>. + +* catch zcx_excel . +*endtry. + if wo_excel is bound. + get_file( importing e_bytecount = l_bytecount + et_file = lt_file ) . + if i_path is initial. + l_dir = create_path( ) . + else. + l_dir = i_path. + endif. + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_dir + filetype = 'BIN' + changing data_tab = lt_file ). + endif. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method CONSTRUCTOR. + worksheet = io_sheet. + endmethod. + + + + method GET_FILTER_AREA. + + validate_area( ). + + rs_area = filter_area. + + endmethod. + + + + method GET_FILTER_RANGE. + DATA: l_row_start_c TYPE string, + l_row_end_c TYPE string, + l_col_start_c TYPE string, + l_col_end_c TYPE string, + l_value TYPE string. + + validate_area( ). + + l_row_end_c = filter_area-row_end. + CONDENSE l_row_end_c NO-GAPS. + + l_row_start_c = filter_area-row_start. + CONDENSE l_row_start_c NO-GAPS. + + l_col_start_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_start ) . + l_col_end_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_end ) . + + CONCATENATE l_col_start_c l_row_start_c ':' l_col_end_c l_row_end_c INTO r_range. + + endmethod. + + + + method GET_FILTER_REFERENCE. + DATA: l_row_start_c TYPE string, + l_row_end_c TYPE string, + l_col_start_c TYPE string, + l_col_end_c TYPE string, + l_value TYPE string. + + validate_area( ). + + l_row_end_c = filter_area-row_end. + CONDENSE l_row_end_c NO-GAPS. + + l_row_start_c = filter_area-row_start. + CONDENSE l_row_start_c NO-GAPS. + + l_col_start_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_start ) . + l_col_end_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_end ) . + l_value = worksheet->get_title( ) . + + r_ref = zcl_excel_common=>escape_string( ip_value = l_value ). + + CONCATENATE r_ref '!$' l_col_start_c '$' l_row_start_c ':$' l_col_end_c '$' l_row_end_c INTO r_ref. + + endmethod. + + + + method GET_VALUES. + + rt_filter = values. + + endmethod. + + + + method SET_FILTER_AREA. + + filter_area = is_area. + + endmethod. + + + + + method SET_VALUE. + DATA: ls_values TYPE zexcel_s_autofilter_values. + +* Checks a re missing. + ls_values-column = i_column. + ls_values-value = i_value. + + INSERT ls_values INTO TABLE values. +* Now we need to be sure we don't get the same value again. + DELETE ADJACENT DUPLICATES FROM values COMPARING column value. + + endmethod. + + + + method SET_VALUES. + +* Checks are missing. + values = it_values. + DELETE ADJACENT DUPLICATES FROM values COMPARING column value. + + endmethod. + + + method VALIDATE_AREA. + DATA: l_col TYPE zexcel_cell_column, + l_row TYPE zexcel_cell_row. + + l_row = worksheet->get_highest_row( ) . + l_col = worksheet->get_highest_column( ) . + + IF filter_area IS INITIAL. + filter_area-row_start = 1. + filter_area-col_start = 1. + filter_area-row_end = l_row . + filter_area-col_end = l_col . + ENDIF. + + IF filter_area-row_start < 1. + filter_area-row_start = 1. + ENDIF. + IF filter_area-col_start < 1. + filter_area-col_start = 1. + ENDIF. + IF filter_area-row_end > l_row OR + filter_area-row_end < 1. + filter_area-row_end = l_row. + ENDIF. + IF filter_area-col_end > l_col OR + filter_area-col_end < 1. + filter_area-col_end = l_col. + ENDIF. + IF filter_area-row_start >= filter_area-row_end. + filter_area-row_start = filter_area-row_end - 1. + IF filter_area-row_start < 1. + filter_area-row_start = 1. + filter_area-row_end = 2. + ENDIF. + ENDIF. + IF filter_area-col_start > filter_area-col_end. + filter_area-col_start = filter_area-col_end. + ENDIF. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature +TYPES: BEGIN OF ts_objects, + sheet_guid TYPE uuid, + autofilter TYPE REF TO zcl_excel_autofilter, + END OF ts_objects, + + tt_objects TYPE HASHED TABLE OF ts_objects WITH UNIQUE KEY sheet_guid. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + method ADD. + DATA: ls_autofilters TYPE ts_objects, + l_guid TYPE uuid. + l_guid = io_sheet->get_guid( ) . + READ TABLE autofilters INTO ls_autofilters WITH TABLE KEY sheet_guid = l_guid. + IF sy-subrc = 0. + ro_autofilter = ls_autofilters-autofilter. + ELSE. + CREATE OBJECT ro_autofilter + EXPORTING + io_sheet = io_sheet. + ls_autofilters-autofilter = ro_autofilter. + ls_autofilters-sheet_guid = l_guid. + INSERT ls_autofilters INTO TABLE autofilters . + ENDIF. + endmethod. + + + method CLEAR. + + REFRESH autofilters. + + endmethod. + + + + + method GET. + + DATA: ls_autofilters TYPE ts_objects. + + READ TABLE autofilters INTO ls_autofilters WITH TABLE KEY sheet_guid = i_sheet_guid. + IF sy-subrc = 0. + ro_autofilter = ls_autofilters-autofilter. + ELSE. + CLEAR ro_autofilter. + ENDIF. + + endmethod. + + + + method IS_EMPTY. + IF autofilters IS INITIAL. + r_empty = abap_true. + ENDIF. + endmethod. + + + + method REMOVE. + DATA: ls_autofilters TYPE ts_objects. + + DELETE autofilters WHERE sheet_guid = i_sheet_guid. + + endmethod. + + + + method SIZE. + DESCRIBE TABLE autofilters LINES r_size. + endmethod. + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature +TYPES: BEGIN OF ts_col_converter, + col TYPE lvc_col, + int TYPE lvc_int, + inv TYPE lvc_inv, + fontcolor TYPE zexcel_style_color_argb, + fillcolor TYPE zexcel_style_color_argb, + END OF ts_col_converter, + + tt_col_converter TYPE HASHED TABLE OF ts_col_converter WITH UNIQUE KEY col int inv. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + ABAP + KKBLO + + + + + + + + + + method APPLY_SORT. + DATA: lt_otab TYPE abap_sortorder_tab, + ls_otab TYPE abap_sortorder. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE, + <fs_sort> TYPE lvc_s_sort. + + CREATE DATA eo_table LIKE it_table. + ASSIGN eo_table->* TO <fs_table>. + + <fs_table> = it_table. + + SORT wt_sort BY spos. + LOOP AT wt_sort ASSIGNING <fs_sort>. + IF <fs_sort>-up = abap_true. + ls_otab-name = <fs_sort>-fieldname. + ls_otab-descending = abap_false. +* ls_otab-astext = abap_true. " not only text fields + INSERT ls_otab INTO TABLE lt_otab. + ENDIF. + IF <fs_sort>-down = abap_true. + ls_otab-name = <fs_sort>-fieldname. + ls_otab-descending = abap_true. +* ls_otab-astext = abap_true. " not only text fields + INSERT ls_otab INTO TABLE lt_otab. + ENDIF. + ENDLOOP. + IF lt_otab IS NOT INITIAL. + SORT <fs_table> BY (lt_otab). + ENDIF. + + endmethod. + + + method CLASS_CONSTRUCTOR. +* let's fill the color conversion routines. + DATA: ls_color TYPE ts_col_converter. +* 0 all combination the same + ls_color-col = 0. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 0. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 0. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 0. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* Blue + ls_color-col = 1. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFB0E4FC'. " 176 228 252 blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 1. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFB0E4FC'. " 176 228 252 blue + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 1. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FF5FCBFE'. " 095 203 254 Int blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 1. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF5FCBFE'. " 095 203 254 + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 + INSERT ls_color INTO TABLE wt_colors. + +* Gray + ls_color-col = 2. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. + ls_color-fillcolor = 'FFE5EAF0'. " 229 234 240 gray + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 2. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFE5EAF0'. " 229 234 240 gray + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 2. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFD8E8F4'. " 216 234 244 int gray + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 2. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FFD8E8F4'. " 216 234 244 int gray + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +*Yellow + ls_color-col = 3. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFEFEB8'. " 254 254 184 yellow + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 3. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFFEFEB8'. " 254 254 184 yellow + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 3. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFF9ED5D'. " 249 237 093 int yellow + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 3. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FFF9ED5D'. " 249 237 093 int yellow + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* light blue + ls_color-col = 4. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFCEE7FB'. " 206 231 251 light blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 4. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFCEE7FB'. " 206 231 251 light blue + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 4. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FF9ACCEF'. " 154 204 239 int light blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 4. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF9ACCEF'. " 154 204 239 int light blue + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* Green + ls_color-col = 5. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFCEF8AE'. " 206 248 174 Green + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 5. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFCEF8AE'. " 206 248 174 Green + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 5. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FF7AC769'. " 122 199 105 int Green + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 5. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF7AC769'. " 122 199 105 int Green + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* Red + ls_color-col = 6. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFDBBBC'. " 253 187 188 Red + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 6. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFFDBBBC'. " 253 187 188 Red + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 6. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFB6B6B'. " 251 107 107 int Red + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 6. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FFFB6B6B'. " 251 107 107 int Red + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + endmethod. + + + + + method GET_COLOR. + DATA: ls_con_col TYPE zexcel_s_converter_col, + ls_color TYPE ts_col_converter, + l_line TYPE i, + l_color(4) TYPE c. + FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE, + <fs_stab> TYPE ANY, + <fs> TYPE ANY, + <fs_tcol> TYPE lvc_t_scol, + <fs_scol> TYPE lvc_s_scol. + +* Loop trough the table to set the color properties of each line. The color properties field is +* Char 4 and the characters is set as follows: +* Char 1 = C = This is a color property +* Char 2 = 6 = Color code (1 - 7) +* Char 3 = Intensified on/of = 1 = on +* Char 4 = Inverse display = 0 = of + + ASSIGN io_table->* TO <fs_tab>. + + IF ws_layo-info_fname IS NOT INITIAL OR + ws_layo-ctab_fname IS NOT INITIAL. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_line = sy-tabix. + IF ws_layo-info_fname IS NOT INITIAL. + ASSIGN COMPONENT ws_layo-info_fname OF STRUCTURE <fs_stab> TO <fs>. + IF sy-subrc = 0. + IF <fs> IS NOT INITIAL. + l_color = <fs>. + IF l_color(1) = 'C'. + READ TABLE wt_colors INTO ls_color WITH TABLE KEY col = l_color+1(1) + int = l_color+2(1) + inv = l_color+3(1). + IF sy-subrc = 0. + ls_con_col-rownumber = l_line. + ls_con_col-columnname = space. + ls_con_col-fontcolor = ls_color-fontcolor. + ls_con_col-fillcolor = ls_color-fillcolor. + INSERT ls_con_col INTO TABLE et_colors. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + IF ws_layo-ctab_fname IS NOT INITIAL. + ASSIGN COMPONENT ws_layo-ctab_fname OF STRUCTURE <fs_stab> TO <fs_tcol>. + IF sy-subrc = 0. + LOOP AT <fs_tcol> ASSIGNING <fs_scol>. + READ TABLE wt_colors INTO ls_color WITH TABLE KEY col = <fs_scol>-color-col + int = <fs_scol>-color-int + inv = <fs_scol>-color-inv. + IF sy-subrc = 0. + ls_con_col-rownumber = l_line. + ls_con_col-columnname = <fs_scol>-fname. + ls_con_col-fontcolor = ls_color-fontcolor. + ls_con_col-fillcolor = ls_color-fillcolor. + ls_con_col-nokeycol = <fs_scol>-nokeycol. + INSERT ls_con_col INTO TABLE et_colors. + ENDIF. + ENDLOOP. + ENDIF. + ENDIF. + ENDLOOP. + ENDIF. + endmethod. + + + + + method GET_FILTER. + DATA: ls_filt TYPE lvc_s_filt, + l_line TYPE i, + ls_filter TYPE zexcel_s_converter_fil. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + lt_components_tab TYPE cl_abap_structdescr=>component_table, + ls_components TYPE abap_componentdescr, + lo_table TYPE REF TO cl_abap_tabledescr, + lo_struc TYPE REF TO cl_abap_structdescr, + lo_trange TYPE REF TO data, + lo_srange TYPE REF TO data, + lo_ltabdata TYPE REF TO data. + + FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE, + <fs_ltab> TYPE STANDARD TABLE, + <fs_stab> TYPE ANY, + <fs> TYPE ANY, + <fs1> TYPE ANY, + <fs_srange> TYPE ANY, + <fs_trange> TYPE STANDARD TABLE. + + IF ws_option-filter = abap_false. + REFRESH et_filter. + RETURN. + ENDIF. + + ASSIGN xo_table->* TO <fs_tab>. + + CREATE DATA lo_ltabdata LIKE <fs_tab>. + ASSIGN lo_ltabdata->* TO <fs_ltab>. + + LOOP AT wt_filt INTO ls_filt. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_line = sy-tabix. + ASSIGN COMPONENT ls_filt-fieldname OF STRUCTURE <fs_stab> TO <fs>. + IF sy-subrc = 0. + IF l_line = 1. + REFRESH lt_components_tab. + ls_components-name = 'SIGN'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ls_filt-sign ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ls_components-name = 'OPTION'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ls_filt-option ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ls_components-name = 'LOW'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ls_components-name = 'HIGH'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + "create new line type + TRY. + lo_struc = cl_abap_structdescr=>create( p_components = lt_components_tab + p_strict = abap_false ). + CATCH cx_sy_struct_creation. + CONTINUE. + ENDTRY. + lo_table = cl_abap_tabledescr=>create( lo_struc ). + + CREATE DATA lo_trange TYPE HANDLE lo_table. + CREATE DATA lo_srange TYPE HANDLE lo_struc. + + ASSIGN lo_trange->* TO <fs_trange>. + ASSIGN lo_srange->* TO <fs_srange>. + ENDIF. + REFRESH <fs_trange>. + ASSIGN COMPONENT 'SIGN' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-sign. + ASSIGN COMPONENT 'OPTION' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-option. + ASSIGN COMPONENT 'LOW' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-low. + ASSIGN COMPONENT 'HIGH' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-high. + INSERT <fs_srange> INTO TABLE <fs_trange>. + IF <fs> IN <fs_trange>. + IF ws_option-filter = abap_true. + ls_filter-rownumber = l_line. + ls_filter-columnname = ls_filt-fieldname. + INSERT ls_filter INTO TABLE et_filter. + ELSE. + INSERT <fs_stab> INTO TABLE <fs_ltab>. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + IF ws_option-filter = abap_undefined. + <fs_tab> = <fs_ltab>. + REFRESH <fs_ltab>. + ENDIF. + ENDLOOP. + + endmethod. + + + + + method UPDATE_CATALOG. + DATA: ls_fieldcatalog TYPE zexcel_s_converter_fcat, + ls_ref TYPE salv_s_ddic_reference, + ls_fcat TYPE lvc_s_fcat, + ls_sort TYPE lvc_s_sort, + l_decimals TYPE lvc_decmls. + + FIELD-SYMBOLS: <fs_scat> TYPE zexcel_s_converter_fcat. + + IF ws_layo-zebra IS NOT INITIAL. + cs_layout-is_stripped = abap_true. + ENDIF. + IF ws_layo-no_keyfix IS INITIAL OR + ws_layo-no_keyfix = '0'. + cs_layout-is_fixed = abap_true. + ENDIF. + + LOOP AT wt_fcat INTO ls_fcat. + CLEAR: ls_fieldcatalog, + l_decimals. + CASE ws_option-hidenc. + WHEN abap_false. " We make hiden columns visible + CLEAR ls_fcat-no_out. + WHEN abap_true. +* We convert column and hide it. + WHEN abap_undefined. "We don't convert hiden columns + IF ls_fcat-no_out = abap_true. + ls_fcat-tech = abap_true. + ENDIF. + ENDCASE. + IF ls_fcat-tech = abap_false. + ls_fieldcatalog-tabname = ls_fcat-tabname. + ls_fieldcatalog-fieldname = ls_fcat-fieldname . + ls_fieldcatalog-columnname = ls_fcat-fieldname . + ls_fieldcatalog-position = ls_fcat-col_pos. + ls_fieldcatalog-col_id = ls_fcat-col_id. + ls_fieldcatalog-convexit = ls_fcat-convexit. + ls_fieldcatalog-inttype = ls_fcat-inttype. + ls_fieldcatalog-scrtext_s = ls_fcat-scrtext_s . + ls_fieldcatalog-scrtext_m = ls_fcat-scrtext_m . + ls_fieldcatalog-scrtext_l = ls_fcat-scrtext_l. + l_decimals = ls_fcat-decimals_o. + IF l_decimals IS NOT INITIAL. + ls_fieldcatalog-decimals = l_decimals. + ELSE. + ls_fieldcatalog-decimals = ls_fcat-decimals . + ENDIF. + CASE ws_option-subtot. + WHEN abap_false. " We ignore subtotals + CLEAR ls_fcat-do_sum. + WHEN abap_true. " We convert subtotals and detail + + WHEN abap_undefined. " We should only take subtotals and displayed detail +* for now abap_true + ENDCASE. + CASE ls_fcat-do_sum. + WHEN abap_true. + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_sum. + WHEN 'A'. + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_min. + WHEN 'B' . + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_max. + WHEN 'C' . + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_average. + WHEN OTHERS. + CLEAR ls_fieldcatalog-totals_function . + ENDCASE. + ls_fieldcatalog-fix_column = ls_fcat-fix_column. + IF ws_layo-cwidth_opt IS INITIAL. + IF ls_fcat-col_opt IS NOT INITIAL. + ls_fieldcatalog-is_optimized = abap_true. + ENDIF. + ELSE. + ls_fieldcatalog-is_optimized = abap_true. + ENDIF. + IF ls_fcat-no_out IS NOT INITIAL. + ls_fieldcatalog-is_hidden = abap_true. + ls_fieldcatalog-position = ls_fieldcatalog-col_id. " We hide based on orginal data structure + ENDIF. +* Alignment in each cell + CASE ls_fcat-just. + WHEN 'R'. + ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_right. + WHEN 'L'. + ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_left. + WHEN 'C'. + ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_center. + WHEN OTHERS. + CLEAR ls_fieldcatalog-alignment. + ENDCASE. +* Check for subtotals. + READ TABLE wt_sort INTO ls_sort WITH KEY fieldname = ls_fcat-fieldname. + IF sy-subrc = 0 AND ws_option-subtot <> abap_false. + ls_fieldcatalog-sort_level = 0 . +* IF ls_fieldcatalog-totals_function IS INITIAL. " Not clear why not +* CLEAR ls_fieldcatalog-is_subtotalled. +* ELSE. + ls_fieldcatalog-is_subtotalled = ls_sort-subtot. +* ENDIF. + ls_fieldcatalog-is_collapsed = ls_sort-expa. + IF ls_fieldcatalog-is_subtotalled = abap_true. + ls_fieldcatalog-sort_level = ls_sort-spos. + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_sum. " we need function for text + ENDIF. + ENDIF. + APPEND ls_fieldcatalog TO ct_fieldcatalog. + ENDIF. + ENDLOOP. + + SORT ct_fieldcatalog BY sort_level ASCENDING. + cs_layout-max_subtotal_level = 0. + LOOP AT ct_fieldcatalog ASSIGNING <fs_scat> WHERE sort_level > 0. + cs_layout-max_subtotal_level = cs_layout-max_subtotal_level + 1. + <fs_scat>-sort_level = cs_layout-max_subtotal_level. + ENDLOOP. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + method GET_TABLE. + DATA: lo_object TYPE REF TO object, + ls_seoclass TYPE seoclass, + l_method TYPE string. + + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'IF_SALV_BS_DATA_SOURCE'. + + IF sy-subrc = 0. + l_method = 'GET_TABLE_REF'. + lo_object ?= io_object. + CALL METHOD lo_object->(l_method) + RECEIVING + value = ro_data. + ELSE. + l_method = 'GET_REF_TO_TABLE'. + lo_object ?= io_object. + CALL METHOD lo_object->(l_method) + RECEIVING + value = ro_data. + ENDIF. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + method CREATE_WT_FCAT. + DATA: lr_data TYPE REF TO data, + lo_structdescr TYPE REF TO cl_abap_structdescr, + lt_dfies TYPE ddfields, + ls_dfies TYPE dfies, + lv_sytabix TYPE sytabix. + + DATA: ls_fcat TYPE lvc_s_fcat. + + FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. + + ASSIGN io_table->* TO <fs_tab> . + CREATE DATA lr_data LIKE LINE OF <fs_tab>. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + + loop at lt_dfies into ls_dfies. + MOVE-CORRESPONDING ls_dfies TO ls_fcat. +* ls_fcat-columnname = ls_dfies-fieldname. + ls_fcat-col_pos = ls_dfies-position. + ls_fcat-key = ls_dfies-keyflag. + get_fields_info( CHANGING xs_fcat = ls_fcat ) . + + ls_fcat-col_opt = abap_true. + + get_columns_info( CHANGING xs_fcat = ls_fcat ) . + + INSERT ls_fcat INTO TABLE wt_fcat. + endloop. + + endmethod. + + + method CREATE_WT_FILT. +* No neeed for superclass. +* Only for WD + DATA: lt_otab TYPE abap_sortorder_tab, + ls_otab TYPE abap_sortorder. + DATA: lt_filters TYPE salv_wd_t_filter_rule_ref, + ls_filt TYPE lvc_s_filt. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref, + <fs_filter> TYPE salv_wd_s_filter_rule_ref. + + LOOP AT wt_fields ASSIGNING <fs_fields>. + REFRESH lt_filters. + lt_filters = <fs_fields>-r_field->if_salv_wd_filter~get_filter_rules( ) . + LOOP AT lt_filters ASSIGNING <fs_filter>. + ls_filt-fieldname = <fs_fields>-fieldname. + IF <fs_filter>-r_filter_rule->get_included( ) = abap_true. + ls_filt-sign = 'I'. + ELSE. + ls_filt-sign = 'E'. + ENDIF. + ls_filt-option = <fs_filter>-r_filter_rule->get_operator( ). + ls_filt-high = <fs_filter>-r_filter_rule->get_high_value( ) . + ls_filt-low = <fs_filter>-r_filter_rule->get_low_value( ) . + INSERT ls_filt INTO TABLE wt_filt. + ENDLOOP. + ENDLOOP. + + endmethod. + + + method CREATE_WT_SORT. + DATA: lo_sort TYPE REF TO cl_salv_wd_sort_rule, + l_sort_order TYPE salv_wd_constant, + ls_sort TYPE lvc_s_sort. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. + + LOOP AT wt_fields ASSIGNING <fs_fields>. + lo_sort = <fs_fields>-r_field->if_salv_wd_sort~get_sort_rule( ) . + IF lo_sort IS BOUND. + l_sort_order = lo_sort->get_sort_order( ). + IF l_sort_order <> if_salv_wd_c_sort=>sort_order. + CLEAR ls_sort. + ls_sort-spos = lo_sort->get_sort_position( ). + ls_sort-fieldname = <fs_fields>-fieldname. +* ls_sort-GROUP + ls_sort-subtot = lo_sort->get_group_aggregation( ). +* ls_sort-COMP +* ls_sort-EXPA +* ls_sort-SELTEXT +* ls_sort-OBLIGATORY +* ls_sort-LEVEL +* ls_sort-NO_OUT + IF l_sort_order = if_salv_wd_c_sort=>sort_order_ascending. + ls_sort-up = abap_true. + ELSE. + ls_sort-down = abap_true. + ENDIF. + INSERT ls_sort INTO TABLE wt_sort. + ENDIF. + ENDIF. + ENDLOOP. + + endmethod. + + + + method GET_COLUMNS_INFO. + DATA: l_numc2 TYPE salv_wd_constant. + + + FIELD-SYMBOLS: <fs_column> TYPE salv_wd_s_column_ref. + + READ TABLE wt_columns ASSIGNING <fs_column> WITH KEY id = xs_fcat-fieldname . + IF sy-subrc = 0. + xs_fcat-col_pos = <fs_column>-r_column->get_position( ) . + l_numc2 = <fs_column>-r_column->get_fixed_position( ). + IF l_numc2 = '02'. + xs_fcat-fix_column = abap_true . + ENDIF. + l_numc2 = <fs_column>-r_column->get_visible( ). + IF l_numc2 = '01'. + xs_fcat-no_out = abap_true . + ENDIF. + ENDIF. + + endmethod. + + + + method GET_FIELDS_INFO. + DATA: lo_aggr TYPE REF TO cl_salv_wd_aggr_rule, + l_aggrtype TYPE salv_wd_constant. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. + + READ TABLE wt_fields ASSIGNING <fs_fields> WITH KEY fieldname = xs_fcat-fieldname. + IF sy-subrc = 0. + lo_aggr = <fs_fields>-r_field->if_salv_wd_aggr~get_aggr_rule( ) . + IF lo_aggr IS BOUND. + l_aggrtype = lo_aggr->get_aggregation_type( ) . + CASE l_aggrtype. + WHEN if_salv_wd_c_aggregation=>aggrtype_total. + xs_fcat-do_sum = abap_true. + WHEN if_salv_wd_c_aggregation=>aggrtype_minimum. + xs_fcat-do_sum = 'A'. + WHEN if_salv_wd_c_aggregation=>aggrtype_maximum . + xs_fcat-do_sum = 'B'. + WHEN if_salv_wd_c_aggregation=>aggrtype_average . + xs_fcat-do_sum = 'C'. + WHEN OTHERS. + CLEAR xs_fcat-do_sum . + ENDCASE. + ENDIF. + ENDIF. + + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + METHOD load_vbaproject. + + DATA lv_content TYPE xstring. + + lv_content = me->get_from_zip_archive( ip_path ). + + ip_excel->zif_excel_book_vba_project~set_vbaproject( lv_content ). + + ENDMETHOD. + + + method LOAD_WORKBOOK. + super->load_workbook( EXPORTING iv_workbook_full_filename = iv_workbook_full_filename + io_excel = io_excel ). + + CONSTANTS: lc_vba_project TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject'. + + DATA: rels_workbook_path TYPE string, + rels_workbook TYPE REF TO if_ixml_document, + path TYPE string, + node TYPE REF TO if_ixml_element, + workbook TYPE REF TO if_ixml_document, + stripped_name TYPE chkfile, + dirname TYPE string, + relationship TYPE t_relationship, + fileversion TYPE t_fileversion, + workbookpr TYPE t_workbookpr. + + FIELD-SYMBOLS: <worksheet> TYPE t_relationship. + + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = iv_workbook_full_filename + IMPORTING + stripped_name = stripped_name + file_path = dirname. + + " Read Workbook Relationships + CONCATENATE dirname '_rels/' stripped_name '.rels' + INTO rels_workbook_path. + + rels_workbook = me->get_ixml_from_zip_archive( rels_workbook_path ). + + node ?= rels_workbook->find_from_name( 'Relationship' ). + WHILE node IS BOUND. + me->fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). + + CASE relationship-type. + WHEN lc_vba_project. + " Read VBA binary + CONCATENATE dirname relationship-target INTO path. + me->load_vbaproject( ip_path = path + ip_excel = io_excel ). + WHEN OTHERS. + ENDCASE. + + node ?= node->get_next( ). + ENDWHILE. + + " Read Workbook codeName + workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). + node ?= workbook->find_from_name( 'fileVersion' ). + IF node IS BOUND. + + fill_struct_from_attributes( EXPORTING ip_element = node + CHANGING cp_structure = fileversion ). + + io_excel->zif_excel_book_vba_project~set_codename( fileversion-codename ). + ENDIF. + + " Read Workbook codeName + workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). + node ?= workbook->find_from_name( 'workbookPr' ). + IF node IS BOUND. + + fill_struct_from_attributes( EXPORTING ip_element = node + CHANGING cp_structure = workbookpr ). + + io_excel->zif_excel_book_vba_project~set_codename_pr( workbookpr-codename ). + ENDIF. + + endmethod. + + + method LOAD_WORKSHEET. + + super->load_worksheet( EXPORTING ip_path = ip_path + io_worksheet = io_worksheet ). + + DATA: path TYPE string, + node TYPE REF TO if_ixml_element, + worksheet TYPE REF TO if_ixml_document, + sheetpr TYPE t_sheetpr. + + +* " Read Workbook codeName +* workbook = me->get_ixml_from_zip_archive( ip_path ). +* node ?= workbook->find_from_name( 'fileVersion' ). +* IF node IS BOUND. +* +* fill_struct_from_attributes( EXPORTING ip_element = node +* CHANGING cp_structure = fileversion ). +* +* IO_WORKSHEET->zif_excel_book_vba_project~set_codename( fileversion-codename ). +* ENDIF. + + " Read Workbook codeName + worksheet = me->get_ixml_from_zip_archive( ip_path ). + node ?= worksheet->find_from_name( 'sheetPr' ). + IF node IS BOUND. + + fill_struct_from_attributes( EXPORTING ip_element = node + CHANGING cp_structure = sheetpr ). + + io_worksheet->zif_excel_sheet_vba_project~set_codename_pr( sheetpr-codename ). + ENDIF. + endmethod. + + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + +* Signal "not found" +class lcx_not_found implementation. + method constructor. + super->constructor( textid = textid previous = previous ). + me->error = error. + endmethod. + method if_message~get_text. + result = error. + endmethod. +endclass. + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + +* Signal for "Not found" +class lcx_not_found definition inheriting from cx_static_check. + public section. + data error type string. + methods constructor + importing error type string + textid type sotr_conc optional + previous type ref to cx_root optional. + methods if_message~get_text redefinition. +endclass. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes +CLASS lcl_test DEFINITION DEFERRED. +CLASS zcl_excel_reader_huge_file DEFINITION LOCAL FRIENDS lcl_test. + +* +CLASS lcl_test DEFINITION FOR TESTING " #AU Risk_Level Harmless + INHERITING FROM cl_aunit_assert. " #AU Duration Short + + PRIVATE SECTION. + DATA: + out TYPE REF TO zcl_excel_reader_huge_file, " object under test + excel TYPE REF TO zcl_excel, + worksheet TYPE REF TO zcl_excel_worksheet. + METHODS: + setup, + test_number FOR TESTING, + test_shared_string FOR TESTING, + test_shared_string_missing FOR TESTING, + test_inline_string FOR TESTING, + test_boolean FOR TESTING, + test_style FOR TESTING, + test_style_missing FOR TESTING, + test_formula FOR TESTING, + test_read_shared_strings FOR TESTING, + test_skip_to_inexistent FOR TESTING, + get_reader IMPORTING iv_xml TYPE string RETURNING VALUE(eo_reader) TYPE REF TO if_sxml_reader, + assert_value_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_value TYPE string, + assert_formula_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_formula TYPE string, + assert_style_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_style TYPE zexcel_cell_style, + assert_datatype_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_datatype TYPE string. + +ENDCLASS. "lcl_test DEFINITION + +* +CLASS lcl_test IMPLEMENTATION. + +* + METHOD test_number. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="n"><v>17</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `17` ). + assert_datatype_equals( `n` ). + ENDMETHOD. "test_shared_string + +* + METHOD test_shared_string. + DATA lo_reader TYPE REF TO if_sxml_reader. + APPEND `Test` TO out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>0</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Test` ). + assert_datatype_equals( `s` ). + ENDMETHOD. "test_shared_string +* + METHOD test_shared_string_missing. + + DATA: lo_reader TYPE REF TO if_sxml_reader, + lo_ex TYPE REF TO lcx_not_found, + lv_text TYPE string. + lo_reader = get_reader( + `<c r="A1" t="s"><v>0</v></c>` + ). + + TRY. + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + fail(`Index to non-existent shared string should give an error`). + CATCH lcx_not_found INTO lo_ex. + lv_text = lo_ex->get_text( ). " >>> May inspect the message in the debugger + ENDTRY. + + ENDMETHOD. +* + METHOD test_inline_string. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="inlineStr"><is><t>Alpha</t></is></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Alpha` ). + assert_datatype_equals( `inlineStr` ). + ENDMETHOD. "test_inline_string + +* + METHOD test_boolean. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="b"><v>1</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `1` ). + assert_datatype_equals( `b` ). + ENDMETHOD. "test_boolean + +* + METHOD test_formula. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="n"><f>A2*A2</f></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_formula_equals( `A2*A2` ). + assert_datatype_equals( `n` ). + ENDMETHOD. "test_formula + +* + METHOD test_style. + DATA: + lo_reader TYPE REF TO if_sxml_reader, + lo_style TYPE REF TO zcl_excel_style, + lv_guid TYPE zexcel_cell_style. + CREATE OBJECT lo_style. + APPEND lo_style TO out->styles. + lv_guid = lo_style->get_guid( ). + + lo_reader = get_reader( + `<c r="A1" s="0"><v>18</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + + assert_style_equals( lv_guid ). + + ENDMETHOD. "test_style + +* + METHOD test_style_missing. + + DATA: + lo_reader TYPE REF TO if_sxml_reader, + lo_ex TYPE REF TO lcx_not_found, + lv_text TYPE string. + + lo_reader = get_reader( + `<c r="A1" s="0"><v>18</v></c>` + ). + + TRY. + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + fail(`Reference to non-existent style should throw an lcx_not_found exception`). + CATCH lcx_not_found INTO lo_ex. + lv_text = lo_ex->get_text( ). " >>> May inspect the message in the debugger + ENDTRY. + + ENDMETHOD. "test_style + +* + METHOD test_read_shared_strings. + DATA: lo_reader TYPE REF TO if_sxml_reader, + lt_act TYPE stringtab, + lt_exp TYPE stringtab. + lo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( + `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + ) ). + APPEND : + `` TO lt_exp, + `Alpha` TO lt_exp, + `Bravo` TO lt_exp. + + lt_act = out->read_shared_strings( lo_reader ). + + assert_equals( act = lt_act + exp = lt_exp ). + + ENDMETHOD. + +* + METHOD test_skip_to_inexistent. + DATA: lo_reader TYPE REF TO if_sxml_reader, + lo_ex TYPE REF TO lcx_not_found, + lv_text TYPE string. + + lo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( + `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + ) ). + TRY. + out->skip_to( iv_element_name = `nonExistingElement` io_reader = lo_reader ). + fail(`Skipping to non-existing element must raise lcx_not_found exception`). + CATCH lcx_not_found INTO lo_ex. + lv_text = lo_ex->get_text( ). " May inspect exception text in debugger + ENDTRY. + ENDMETHOD. + +* + METHOD get_reader. + DATA: lv_full TYPE string. + CONCATENATE `<root><sheetData><row>` iv_xml `</row></sheetData></root>` INTO lv_full. + eo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( lv_full ) ). + ENDMETHOD. "get_reader +* + METHOD assert_value_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_value + exp = iv_value ). + + ENDMETHOD. "assert_value_equals +** + METHOD assert_formula_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_formula + exp = iv_formula ). + + ENDMETHOD. "assert_formula_equals +* + METHOD assert_style_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_style + exp = iv_style ). + + ENDMETHOD. +* + METHOD assert_datatype_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-data_type + exp = iv_datatype ). + + ENDMETHOD. "assert_datatype_equals + METHOD setup. + CREATE OBJECT out. + CREATE OBJECT excel. + CREATE OBJECT worksheet + EXPORTING + ip_excel = excel. + ENDMETHOD. "setup +ENDCLASS. "lcl_test IMPLEMENTATION + + + + + + + + + + + + + + + method FILL_CELL_FROM_ATTRIBUTES. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_attribute( ). + if io_reader->node_type ne c_attribute. + exit. + endif. + case io_reader->name. + when `t`. + es_cell-datatype = io_reader->value. + when `s`. + if io_reader->value is not initial. + es_cell-style = get_style( io_reader->value ). + endif. + when `r`. + es_cell-coord = get_cell_coord( io_reader->value ). + endcase. + endwhile. + + io_reader->current_node( ). + +endmethod. + + + + + method GET_CELL_COORD. + + zcl_excel_common=>convert_columnrow2column_a_row( + exporting + i_columnrow = iv_coord + importing + e_column = es_coord-column + e_row = es_coord-row + ). + +endmethod. + + + + + + method GET_SHARED_STRING. + data: lv_tabix type i. + lv_tabix = iv_index + 1. + read table shared_strings into ev_value index lv_tabix. + if sy-subrc ne 0. + raise exception type lcx_not_found + exporting + error = |Entry { iv_index } not found in Shared String Table|. + endif. +endmethod. + + + + + + method GET_STYLE. + + data: lv_tabix type i, + lo_style type ref to zcl_excel_style. + + if gs_buffer_style-index ne iv_index. + lv_tabix = iv_index + 1. + read table styles into lo_style index lv_tabix. + if sy-subrc ne 0. + raise exception type lcx_not_found + exporting + error = |Entry { iv_index } not found in Style Table|. + else. + gs_buffer_style-index = iv_index. + gs_buffer_style-guid = lo_style->get_guid( ). + endif. + endif. + + ev_style_guid = gs_buffer_style-guid. + +endmethod. + + + + + + method GET_SXML_READER. + + data: lv_xml type xstring. + + lv_xml = get_from_zip_archive( iv_path ). + eo_reader = cl_sxml_string_reader=>create( lv_xml ). + +endmethod. + + + method LOAD_SHARED_STRINGS. + + data: lo_reader type ref to if_sxml_reader. + + lo_reader = get_sxml_reader( ip_path ). + + shared_strings = read_shared_strings( lo_reader ). + +endmethod. + + + method LOAD_WORKSHEET. + + data: lo_reader type ref to if_sxml_reader. + + lo_reader = get_sxml_reader( ip_path ). + + read_worksheet_data( io_reader = lo_reader + io_worksheet = io_worksheet ). + +endmethod. + + + + + method PUT_CELL_TO_WORKSHEET. + call method io_worksheet->set_cell + exporting + ip_column = is_cell-column + ip_row = is_cell-row + ip_value = is_cell-value + ip_formula = is_cell-formula + ip_data_type = is_cell-datatype + ip_style = is_cell-style. +endmethod. + + + + + method READ_SHARED_STRINGS. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + if io_reader->node_type eq c_element_close and + io_reader->name eq `t`. + append io_reader->value to et_shared_strings. + endif. + endwhile. + +endmethod. + + + + + + method READ_WORKSHEET_DATA. + + data: ls_cell type t_cell. + +* Skip to <sheetData> element + skip_to( iv_element_name = `sheetData` io_reader = io_reader ). + +* Main loop: Evaluate the <c> elements and its children + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + case io_reader->node_type. + when c_element_open. + if io_reader->name eq `c`. + ls_cell = fill_cell_from_attributes( io_reader ). + endif. + when c_element_close. + case io_reader->name. + when `c`. + put_cell_to_worksheet( is_cell = ls_cell io_worksheet = io_worksheet ). + when `f`. + ls_cell-formula = io_reader->value. + when `v`. + if ls_cell-datatype eq `s`. + ls_cell-value = get_shared_string( ls_cell-value ). + else. + ls_cell-value = io_reader->value. + endif. + when `is`. + ls_cell-value = io_reader->value. + when `sheetData`. + exit. + endcase. + endcase. + endwhile. + +endmethod. + + + + + + method SKIP_TO. + +* Skip forward to given element + while io_reader->name ne iv_element_name or + io_reader->node_type ne c_element_open. + io_reader->next_node( ). + if io_reader->node_type = c_end_of_stream. + raise exception type lcx_not_found + exporting + error = |XML error: Didn't find element <{ iv_element_name }>|. + endif. + endwhile. + + +endmethod. + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CREATE_AX. + DATA ls_ax TYPE s_ax. + ls_ax-type = ip_type. + + IF ip_type = c_catax. + IF ip_axid IS SUPPLIED. + ls_ax-axid = ip_axid. + ELSE. + ls_ax-axid = '1'. + ENDIF. + IF ip_orientation IS SUPPLIED. + ls_ax-orientation = ip_orientation. + ELSE. + ls_ax-orientation = 'minMax'. + ENDIF. + IF ip_delete IS SUPPLIED. + ls_ax-delete = ip_delete. + ELSE. + ls_ax-delete = '0'. + ENDIF. + IF ip_axpos IS SUPPLIED. + ls_ax-axpos = ip_axpos. + ELSE. + ls_ax-axpos = 'b'. + ENDIF. + IF ip_formatcode IS SUPPLIED. + ls_ax-formatcode = ip_formatcode. + ELSE. + ls_ax-formatcode = 'General'. + ENDIF. + IF ip_sourcelinked IS SUPPLIED. + ls_ax-sourcelinked = ip_sourcelinked. + ELSE. + ls_ax-sourcelinked = '1'. + ENDIF. + IF ip_majortickmark IS SUPPLIED. + ls_ax-majortickmark = ip_majortickmark. + ELSE. + ls_ax-majortickmark = 'out'. + ENDIF. + IF ip_minortickmark IS SUPPLIED. + ls_ax-minortickmark = ip_minortickmark. + ELSE. + ls_ax-minortickmark = 'none'. + ENDIF. + IF ip_ticklblpos IS SUPPLIED. + ls_ax-ticklblpos = ip_ticklblpos. + ELSE. + ls_ax-ticklblpos = 'nextTo'. + ENDIF. + IF ip_crossax IS SUPPLIED. + ls_ax-crossax = ip_crossax. + ELSE. + ls_ax-crossax = '2'. + ENDIF. + IF ip_crosses IS SUPPLIED. + ls_ax-crosses = ip_crosses. + ELSE. + ls_ax-crosses = 'autoZero'. + ENDIF. + IF ip_auto IS SUPPLIED. + ls_ax-auto = ip_auto. + ELSE. + ls_ax-auto = '1'. + ENDIF. + IF ip_lblalgn IS SUPPLIED. + ls_ax-lblalgn = ip_lblalgn. + ELSE. + ls_ax-lblalgn = 'ctr'. + ENDIF. + IF ip_lbloffset IS SUPPLIED. + ls_ax-lbloffset = ip_lbloffset. + ELSE. + ls_ax-lbloffset = '100'. + ENDIF. + IF ip_nomultilvllbl IS SUPPLIED. + ls_ax-nomultilvllbl = ip_nomultilvllbl. + ELSE. + ls_ax-nomultilvllbl = '0'. + ENDIF. + ELSEIF ip_type = c_valax. + IF ip_axid IS SUPPLIED. + ls_ax-axid = ip_axid. + ELSE. + ls_ax-axid = '2'. + ENDIF. + IF ip_orientation IS SUPPLIED. + ls_ax-orientation = ip_orientation. + ELSE. + ls_ax-orientation = 'minMax'. + ENDIF. + IF ip_delete IS SUPPLIED. + ls_ax-delete = ip_delete. + ELSE. + ls_ax-delete = '0'. + ENDIF. + IF ip_axpos IS SUPPLIED. + ls_ax-axpos = ip_axpos. + ELSE. + ls_ax-axpos = 'l'. + ENDIF. + IF ip_formatcode IS SUPPLIED. + ls_ax-formatcode = ip_formatcode. + ELSE. + ls_ax-formatcode = 'General'. + ENDIF. + IF ip_sourcelinked IS SUPPLIED. + ls_ax-sourcelinked = ip_sourcelinked. + ELSE. + ls_ax-sourcelinked = '1'. + ENDIF. + IF ip_majortickmark IS SUPPLIED. + ls_ax-majortickmark = ip_majortickmark. + ELSE. + ls_ax-majortickmark = 'out'. + ENDIF. + IF ip_minortickmark IS SUPPLIED. + ls_ax-minortickmark = ip_minortickmark. + ELSE. + ls_ax-minortickmark = 'none'. + ENDIF. + IF ip_ticklblpos IS SUPPLIED. + ls_ax-ticklblpos = ip_ticklblpos. + ELSE. + ls_ax-ticklblpos = 'nextTo'. + ENDIF. + IF ip_crossax IS SUPPLIED. + ls_ax-crossax = ip_crossax. + ELSE. + ls_ax-crossax = '1'. + ENDIF. + IF ip_crosses IS SUPPLIED. + ls_ax-crosses = ip_crosses. + ELSE. + ls_ax-crosses = 'autoZero'. + ENDIF. + IF ip_crossbetween IS SUPPLIED. + ls_ax-crossbetween = ip_crossbetween. + ELSE. + ls_ax-crossbetween = 'between'. + ENDIF. + ENDIF. + + APPEND ls_ax TO me->axes. + SORT me->axes BY axid ASCENDING. + endmethod. + + + + method SET_SHOW_CAT_NAME. + ns_showcatnameval = ip_value. + endmethod. + + + + method SET_SHOW_LEGEND_KEY. + ns_showlegendkeyval = ip_value. + endmethod. + + + + method SET_SHOW_PERCENT. + ns_showpercentval = ip_value. + endmethod. + + + + method SET_SHOW_SER_NAME. + ns_showsernameval = ip_value. + endmethod. + + + + method SET_SHOW_VALUES. + ns_showvalval = ip_value. + endmethod. + + + + method SET_VARYCOLOR. + ns_varycolorsval = ip_value. + endmethod. + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + method IF_MESSAGE~GET_LONGTEXT. + + IF me->error IS NOT INITIAL + OR me->syst_at_raise IS NOT INITIAL. +*--------------------------------------------------------------------* +* If message was supplied explicitly use this as longtext as well +*--------------------------------------------------------------------* + result = me->get_text( ). + ELSE. +*--------------------------------------------------------------------* +* otherwise use standard method to derive text +*--------------------------------------------------------------------* + super->if_message~get_longtext( EXPORTING + preserve_newlines = preserve_newlines + RECEIVING + result = result ). + ENDIF. + endmethod. + + + method IF_MESSAGE~GET_TEXT. + + IF me->error IS NOT INITIAL. +*--------------------------------------------------------------------* +* If message was supplied explicitly use this +*--------------------------------------------------------------------* + result = me->error . + ELSEIF me->syst_at_raise IS NOT INITIAL. +*--------------------------------------------------------------------* +* If message was supplied by syst create messagetext now +*--------------------------------------------------------------------* + MESSAGE ID syst_at_raise-msgid TYPE syst_at_raise-msgty NUMBER syst_at_raise-msgno + WITH syst_at_raise-msgv1 syst_at_raise-msgv2 syst_at_raise-msgv3 syst_at_raise-msgv4 + INTO result. + ELSE. +*--------------------------------------------------------------------* +* otherwise use standard method to derive text +*--------------------------------------------------------------------* + CALL METHOD super->if_message~get_text + RECEIVING + result = result. + ENDIF. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + method CONSTRUCTOR. + endmethod. + + + + method GET_STRUCTURE. +*initialize colors to 'not set' + es_fill-left_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-left_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-right_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-right_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-top_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-top_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-bottom_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-bottom_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-diagonal_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-diagonal_color-theme = zcl_excel_style_color=>c_theme_not_set. + +* Check if all borders is set otherwise check single border + IF me->allborders IS BOUND. + es_fill-left_color = me->allborders->border_color. + es_fill-left_style = me->allborders->border_style. + es_fill-right_color = me->allborders->border_color. + es_fill-right_style = me->allborders->border_style. + es_fill-top_color = me->allborders->border_color. + es_fill-top_style = me->allborders->border_style. + es_fill-bottom_color = me->allborders->border_color. + es_fill-bottom_style = me->allborders->border_style. + ELSE. + IF me->left IS BOUND. + es_fill-left_color = me->left->border_color. + es_fill-left_style = me->left->border_style. + ENDIF. + IF me->right IS BOUND. + es_fill-right_color = me->right->border_color. + es_fill-right_style = me->right->border_style. + ENDIF. + IF me->top IS BOUND. + es_fill-top_color = me->top->border_color. + es_fill-top_style = me->top->border_style. + ENDIF. + IF me->down IS BOUND. + es_fill-bottom_color = me->down->border_color. + es_fill-bottom_style = me->down->border_style. + ENDIF. + ENDIF. + +* Check if diagonal is set + IF me->diagonal IS BOUND. + es_fill-diagonal_color = me->diagonal->border_color. + es_fill-diagonal_style = me->diagonal->border_style. + CASE me->diagonal_mode. + WHEN 1. + es_fill-diagonalup = 1. + es_fill-diagonaldown = 0. + WHEN 2. + es_fill-diagonalup = 0. + es_fill-diagonaldown = 1. + WHEN 3. + es_fill-diagonalup = 1. + es_fill-diagonaldown = 1. + WHEN OTHERS. + es_fill-diagonalup = 0. + es_fill-diagonaldown = 0. + ENDCASE. + ENDIF. + + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + method CONSTRUCTOR. + " default Excel palette based on + " http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.indexedcolors.aspx + + APPEND '00000000' TO colors. + APPEND '00FFFFFF' TO colors. + APPEND '00FF0000' TO colors. + APPEND '0000FF00' TO colors. + APPEND '000000FF' TO colors. + APPEND '00FFFF00' TO colors. + APPEND '00FF00FF' TO colors. + APPEND '0000FFFF' TO colors. + APPEND '00000000' TO colors. + APPEND '00FFFFFF' TO colors. + + APPEND '00FF0000' TO colors. + APPEND '0000FF00' TO colors. + APPEND '000000FF' TO colors. + APPEND '00FFFF00' TO colors. + APPEND '00FF00FF' TO colors. + APPEND '0000FFFF' TO colors. + APPEND '00800000' TO colors. + APPEND '00008000' TO colors. + APPEND '00000080' TO colors. + APPEND '00808000' TO colors. + + APPEND '00800080' TO colors. + APPEND '00008080' TO colors. + APPEND '00C0C0C0' TO colors. + APPEND '00808080' TO colors. + APPEND '009999FF' TO colors. + APPEND '00993366' TO colors. + APPEND '00FFFFCC' TO colors. + APPEND '00CCFFFF' TO colors. + APPEND '00660066' TO colors. + APPEND '00FF8080' TO colors. + + APPEND '000066CC' TO colors. + APPEND '00CCCCFF' TO colors. + APPEND '00000080' TO colors. + APPEND '00FF00FF' TO colors. + APPEND '00FFFF00' TO colors. + APPEND '0000FFFF' TO colors. + APPEND '00800080' TO colors. + APPEND '00800000' TO colors. + APPEND '00008080' TO colors. + APPEND '000000FF' TO colors. + + APPEND '0000CCFF' TO colors. + APPEND '00CCFFFF' TO colors. + APPEND '00CCFFCC' TO colors. + APPEND '00FFFF99' TO colors. + APPEND '0099CCFF' TO colors. + APPEND '00FF99CC' TO colors. + APPEND '00CC99FF' TO colors. + APPEND '00FFCC99' TO colors. + APPEND '003366FF' TO colors. + APPEND '0033CCCC' TO colors. + + APPEND '0099CC00' TO colors. + APPEND '00FFCC00' TO colors. + APPEND '00FF9900' TO colors. + APPEND '00FF6600' TO colors. + APPEND '00666699' TO colors. + APPEND '00969696' TO colors. + APPEND '00003366' TO colors. + APPEND '00339966' TO colors. + APPEND '00003300' TO colors. + APPEND '00333300' TO colors. + + APPEND '00993300' TO colors. + APPEND '00993366' TO colors. + APPEND '00333399' TO colors. + APPEND '00333333' TO colors. + + endmethod. + + + + + + method GET_COLOR. + DATA: lv_index type i. + + lv_index = ip_index + 1. + READ TABLE colors INTO ep_color INDEX lv_index. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid color index'. + ENDIF. + endmethod. + + + + method GET_COLORS. + ep_colors = colors. + endmethod. + + + + method IS_MODIFIED. + ep_modified = modified. + endmethod. + + + + + method SET_COLOR. + DATA: lv_index TYPE i. + + FIELD-SYMBOLS: <lv_color> LIKE LINE OF colors. + + lv_index = ip_index + 1. + READ TABLE colors ASSIGNING <lv_color> INDEX lv_index. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid color index'. + ENDIF. + + IF <lv_color> <> ip_color. + modified = abap_true. + <lv_color> = ip_color. + ENDIF. + + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + + endmethod. + + + + + + + method CREATE_NEW_ARGB. + + + CONCATENATE zcl_excel_style_color=>c_alpha ip_red ip_green ip_blu INTO ep_color_argb. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + DATA: ls_iconset TYPE zexcel_conditional_iconset. + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights. + ls_iconset-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo1_value = '0'. + ls_iconset-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo2_value = '20'. + ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo3_value = '40'. + ls_iconset-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo4_value = '60'. + ls_iconset-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo5_value = '80'. + + + me->rule = zcl_excel_style_conditional=>c_rule_none. +* me->iconset->operator = zcl_excel_style_conditional=>c_operator_none. + me->mode_iconset = ls_iconset. + me->priority = 1. + +* inizialize dimension range + me->stop_cell-cell_row = 1. + me->stop_cell-cell_column = 1. + me->start_cell-cell_row = 1. + me->start_cell-cell_column = 1. + endmethod. + + + + method GET_DIMENSION_RANGE. + IF stop_cell EQ start_cell. "only one cell + ep_dimension_range = start_cell-cell_coords. + ELSE. + CONCATENATE start_cell-cell_coords ':' stop_cell-cell_coords INTO ep_dimension_range. + ENDIF. + endmethod. + + + + + + + method SET_RANGE. + DATA: lv_column TYPE zexcel_cell_column, + lv_row_alpha TYPE string. + + lv_column = zcl_excel_common=>convert_column2int( ip_stop_column ). + stop_cell-cell_row = 1. + stop_cell-cell_column = lv_column. + lv_row_alpha = ip_stop_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_stop_column lv_row_alpha INTO stop_cell-cell_coords. + + lv_column = zcl_excel_common=>convert_column2int( ip_start_column ). + start_cell-cell_row = 1. + start_cell-cell_column = lv_column. + lv_row_alpha = ip_start_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_start_column lv_row_alpha INTO start_cell-cell_coords. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + filltype = zcl_excel_style_fill=>c_fill_none. + fgcolor-theme = zcl_excel_style_color=>c_theme_not_set. + fgcolor-indexed = zcl_excel_style_color=>c_indexed_not_set. + bgcolor-theme = zcl_excel_style_color=>c_theme_not_set. + bgcolor-indexed = zcl_excel_style_color=>c_indexed_sys_foreground. + rotation = 0. + endmethod. + + + + method GET_STRUCTURE. + es_fill-rotation = me->rotation. + es_fill-filltype = me->filltype. + es_fill-fgColor = me->fgColor. + es_fill-bgColor = me->bgColor. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CALCULATE_TEXT_WIDTH. + " Addition to solve issue #120, contribution by Stefan Schmöcker + r_width = strlen( i_text ). + " use scale factor based on default 11 + " ( don't know where defaultsetting is stored currently ) + r_width = r_width * me->size / 11. + endmethod. + + + method CONSTRUCTOR. + me->color-rgb = zcl_excel_style_color=>c_black. + me->color-theme = zcl_excel_style_color=>c_theme_not_set. + me->color-indexed = zcl_excel_style_color=>c_indexed_not_set. + me->scheme = zcl_excel_style_font=>c_scheme_minor. + me->underline_mode = zcl_excel_style_font=>c_underline_single. + endmethod. + + + + method GET_STRUCTURE. + + es_font-bold = me->bold. + es_font-italic = me->italic. + es_font-underline = me->underline. + es_font-underline_mode = me->underline_mode. + es_font-strikethrough = me->strikethrough. + es_font-size = me->size. + es_font-color = me->color. + es_font-name = me->name. + es_font-family = me->family. + es_font-scheme = me->scheme. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + format_code = me->c_format_general. + endmethod. + + + + method GET_STRUCTURE. + ep_number_format-numfmt = me->format_code. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + method CONSTRUCTOR. + locked = me->c_protection_locked. + hidden = me->c_protection_unhidden. + endmethod. + + + + method GET_STRUCTURE. + ep_protection-locked = me->locked. + ep_protection-hidden = me->hidden. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + endmethod. + + + + method GET_BOTTOM_ROW_INTEGER. + DATA: lv_table_lines TYPE i. + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + + IF settings-bottom_right_row IS NOT INITIAL. +* ev_row = zcl_excel_common=>convert_column2int( settings-bottom_right_row ). " del issue #246 + ev_row = settings-bottom_right_row . " ins issue #246 + EXIT. + ENDIF. + + ASSIGN table_data->* TO <fs_table>. + DESCRIBE TABLE <fs_table> LINES lv_table_lines. + IF lv_table_lines = 0. + lv_table_lines = 1. "table needs at least 1 data row + ENDIF. + + ev_row = settings-top_left_row + lv_table_lines. + + IF me->has_totals( ) = abap_true." ???? AND ip_include_totals_row = abap_true. + ADD 1 TO ev_row. + ENDIF. + endmethod. + + + + method GET_ID. + ov_id = id. + endmethod. + + + + method GET_NAME. + + IF me->name IS INITIAL. + me->name = zcl_excel_common=>number_to_excel_string( ip_value = me->id ). + CONCATENATE 'table' me->name INTO me->name. + ENDIF. + + ov_name = me->name. + endmethod. + + + + + method GET_REFERENCE. + DATA: lv_column TYPE zexcel_cell_column, + lv_table_lines TYPE i, + lv_right_column TYPE zexcel_cell_column_alpha, + ls_field_catalog TYPE zexcel_s_fieldcatalog, + lv_bottom_row TYPE zexcel_cell_row, + lv_top_row_string(10) TYPE c, + lv_bottom_row_string(10) TYPE c. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + +*column + lv_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). + lv_table_lines = 0. + LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. + ADD 1 TO lv_table_lines. + ENDLOOP. + lv_column = lv_column + lv_table_lines - 1. + lv_right_column = zcl_excel_common=>convert_column2alpha( lv_column ). + +*row + ASSIGN table_data->* TO <fs_table>. + DESCRIBE TABLE <fs_table> LINES lv_table_lines. + IF lv_table_lines = 0. + lv_table_lines = 1. "table needs at least 1 data row + ENDIF. + lv_bottom_row = settings-top_left_row + lv_table_lines . + + IF me->has_totals( ) = abap_true AND ip_include_totals_row = abap_true. + ADD 1 TO lv_bottom_row. + ENDIF. + + lv_top_row_string = zcl_excel_common=>number_to_excel_string( settings-top_left_row ). + lv_bottom_row_string = zcl_excel_common=>number_to_excel_string( lv_bottom_row ). + + CONCATENATE settings-top_left_column lv_top_row_string + ':' + lv_right_column lv_bottom_row_string INTO ov_reference. + + endmethod. + + + + + method GET_RIGHT_COLUMN_INTEGER. + DATA: lv_column TYPE zexcel_cell_column, + lv_table_lines TYPE i, + ls_field_catalog TYPE zexcel_s_fieldcatalog. + + IF settings-bottom_right_column IS NOT INITIAL. + ev_column = zcl_excel_common=>convert_column2int( settings-bottom_right_column ). + EXIT. + ENDIF. + + ev_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). + LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. + ADD 1 TO ev_column. + ENDLOOP. + + endmethod. + + + + + + method GET_TOTALS_FORMULA. + CONSTANTS: lc_function_id_sum TYPE string VALUE '109', + lc_function_id_min TYPE string VALUE '105', + lc_function_id_max TYPE string VALUE '104', + lc_function_id_count TYPE string VALUE '103', + lc_function_id_average TYPE string VALUE '101'. + + DATA: lv_function_id TYPE string. + + CASE ip_function. + WHEN zcl_excel_table=>totals_function_sum. + lv_function_id = lc_function_id_sum. + + WHEN zcl_excel_table=>totals_function_min. + lv_function_id = lc_function_id_min. + + WHEN zcl_excel_table=>totals_function_max. + lv_function_id = lc_function_id_max. + + WHEN zcl_excel_table=>totals_function_count. + lv_function_id = lc_function_id_count. + + WHEN zcl_excel_table=>totals_function_average. + lv_function_id = lc_function_id_average. + + WHEN zcl_excel_table=>totals_function_custom. " issue #292 + RETURN. + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid totals formula. See ZCL_ for possible values'. + ENDCASE. + + CONCATENATE 'SUBTOTAL(' lv_function_id ',[' ip_column '])' INTO ep_formula. + endmethod. + + + + method HAS_TOTALS. + DATA: ls_field_catalog TYPE zexcel_s_fieldcatalog. + + ep_result = abap_false. + + LOOP AT fieldcat INTO ls_field_catalog. + IF ls_field_catalog-totals_function IS NOT INITIAL. + ep_result = abap_true. + EXIT. + ENDIF. + ENDLOOP. + + endmethod. + + + + method SET_DATA. + GET REFERENCE OF ir_data INTO me->table_data. + endmethod. + + + + method SET_ID. + id = iv_id. + endmethod. + + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + +*&---------------------------------------------------------------------* +*& Class (Implementation) C_OI_PROXY_ERROR +*&---------------------------------------------------------------------* +CLASS c_oi_proxy_error IMPLEMENTATION. + METHOD constructor. +* IMPORTING object_name TYPE c +* method_name TYPE c. + error_nr = ret_call_not_flushed. + me->i_oi_error~error_code = c_oi_errors=>ret_call_not_flushed. + me->i_oi_error~is_flushed = ' '. + me->i_oi_error~has_failed = 'X'. + me->i_oi_error~has_succeeded = ' '. + me->message_id = 'SOFFICEINTEGRATION'. + me->message_nr = '899'. + me->param1 = object_name. + me->param2 = method_name. + ENDMETHOD. "constructor + + METHOD i_oi_error~flush_error. + IF error_nr EQ 0. + me->i_oi_error~error_code = c_oi_errors=>ret_ok. + me->i_oi_error~is_flushed = 'X'. + me->i_oi_error~has_failed = ' '. + me->i_oi_error~has_succeeded = 'X'. + me->message_id = ''. + me->message_nr = '000'. + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + IMPORTING + retcode = me->i_oi_error~error_code. + ELSEIF error_nr EQ ret_call_not_flushed. + "call still not flushed + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + errorstring = me->param2 "method name + objectname = me->param1 + IMPORTING + retcode = me->i_oi_error~error_code. + ELSE. + me->i_oi_error~is_flushed = 'X'. + me->i_oi_error~has_succeeded = ' '. + me->i_oi_error~has_failed = 'X'. + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + errorstring = error_string + IMPORTING + retcode = me->i_oi_error~error_code. + CALL METHOD c_oi_errors=>get_message + IMPORTING + message_id = me->message_id + message_number = me->message_nr + param1 = me->param1 + param2 = me->param2 + param3 = me->param3 + param4 = me->param4. + ENDIF. + ENDMETHOD. "i_oi_error~flush_error + + METHOD i_oi_error~raise_message. +* IMPORTING type TYPE c. +* EXCEPTIONS message_raised flush_failed. + IF me->i_oi_error~has_succeeded IS INITIAL. + IF NOT me->i_oi_error~is_flushed IS INITIAL. + MESSAGE ID message_id TYPE type + NUMBER message_nr WITH param1 param2 param3 param4 + RAISING message_raised. + ELSE. + RAISE flush_failed. + ENDIF. + ENDIF. + ENDMETHOD. "i_oi_error~raise_message + + METHOD i_oi_error~get_message. +* EXPORTING message_id TYPE c +* message_number TYPE c +* param1 TYPE c +* param2 TYPE c +* param3 TYPE c +* param4 TYPE c. + param1 = me->param1. param2 = me->param2. + param3 = me->param3. param4 = me->param4. + + message_id = me->message_id. + message_number = me->message_nr. + ENDMETHOD. "i_oi_error~get_message +ENDCLASS. "C_OI_PROXY_ERROR + +*&---------------------------------------------------------------------* +*& Class (Implementation) CL_GRID_ACCESSION +*&---------------------------------------------------------------------* +CLASS lcl_gui_alv_grid IMPLEMENTATION. + + METHOD get_alv_attributes. + CREATE DATA et_table LIKE io_grid->mt_outtab. + et_table = io_grid->mt_outtab. + ENDMETHOD. "get_data + +ENDCLASS. "CL_GRID_ACCESSION + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature +TYPE-POOLS: sydes. +TYPE-POOLS: slis. +*--------------------------------------------------------------------* +* CLASS c_oi_proxy_error +*--------------------------------------------------------------------* +* use for method bind_ALV +*--------------------------------------------------------------------* +CLASS c_oi_proxy_error DEFINITION. + PUBLIC SECTION. + INTERFACES: i_oi_error. + DATA: error_nr TYPE i. + DATA: error_string TYPE sy-msgv1. + + METHODS: constructor IMPORTING object_name TYPE c + method_name TYPE c. + PRIVATE SECTION. + CONSTANTS: + ret_call_not_flushed TYPE i VALUE -999999. + + DATA: message_id TYPE sy-msgid, + message_nr TYPE sy-msgno, + param1 TYPE sy-msgv1, + param2 TYPE sy-msgv2, + param3 TYPE sy-msgv3, + param4 TYPE sy-msgv4. +ENDCLASS. "c_oi_proxy_error DEFINITION + +*--------------------------------------------------------------------* +* CLASS lcl_gui_alv_grid +*--------------------------------------------------------------------* +* to get protected attribute and method of cl_gui_alv_grid +* use for method bind_ALV +*--------------------------------------------------------------------* +CLASS lcl_gui_alv_grid DEFINITION INHERITING FROM cl_gui_alv_grid. + + PUBLIC SECTION. +* get ALV grid data + METHODS: get_alv_attributes + IMPORTING + io_grid TYPE REF TO cl_gui_alv_grid " ALV grid + EXPORTING + et_table TYPE REF TO data. " dta table + +ENDCLASS. "lcl_gui_alv_grid DEFINITION + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + ABAP + SLIS + SOI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~CLEAR_PRINT_REPEAT_COLUMNS. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + CLEAR: me->print_title_col_from, + me->print_title_col_to . + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~CLEAR_PRINT_REPEAT_ROWS. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + CLEAR: me->print_title_row_from, + me->print_title_row_to . + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~GET_PRINT_REPEAT_COLUMNS. + ev_columns_from = me->print_title_col_from. + ev_columns_to = me->print_title_col_to. + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~GET_PRINT_REPEAT_ROWS. + ev_rows_from = me->print_title_row_from. + ev_rows_to = me->print_title_row_to. + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~SET_PRINT_REPEAT_COLUMNS. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + DATA: lv_col_from_int TYPE i, + lv_col_to_int TYPE i, + lv_errormessage TYPE string. + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range. + + + lv_col_from_int = zcl_excel_common=>convert_column2int( iv_columns_from ). + lv_col_to_int = zcl_excel_common=>convert_column2int( iv_columns_to ). + +*--------------------------------------------------------------------* +* Check if valid range is supplied +*--------------------------------------------------------------------* + IF lv_col_from_int < 1. + lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF lv_col_from_int > lv_col_to_int. + lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + me->print_title_col_from = iv_columns_from. + me->print_title_col_to = iv_columns_to. + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~SET_PRINT_REPEAT_ROWS. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + DATA: lv_errormessage TYPE string. + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range. + + + +*--------------------------------------------------------------------* +* Check if valid range is supplied +*--------------------------------------------------------------------* + IF iv_rows_from < 1. + lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF iv_rows_from > iv_rows_to. + lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + me->print_title_row_from = iv_rows_from. + me->print_title_row_to = iv_rows_to. + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~GET_STYLE. + IF zif_excel_sheet_properties~style IS NOT INITIAL. + ep_style = zif_excel_sheet_properties~style. + ELSE. + ep_style = me->excel->get_default_style( ). + ENDIF. + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~INITIALIZE. + + zif_excel_sheet_properties~show_zeros = zif_excel_sheet_properties=>c_showzero. + zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. + zif_excel_sheet_properties~summaryright = zif_excel_sheet_properties=>c_right_on. + +* inizialize zoomscale values + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale = 100. + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_normal = 100. + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_pagelayoutview = 100 . + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_sheetlayoutview = 100 . + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~SET_STYLE. + zif_excel_sheet_properties~style = ip_style. + endmethod. + + + method ZIF_EXCEL_SHEET_PROTECTION~INITIALIZE. + + me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_unprotected. + CLEAR me->zif_excel_sheet_protection~password. + me->zif_excel_sheet_protection~auto_filter = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~delete_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~delete_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_hyperlinks = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_noactive. +* me->zif_excel_sheet_protection~password = zif_excel_sheet_protection=>c_noactive. "issue #68 + me->zif_excel_sheet_protection~pivot_tables = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~select_locked_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~select_unlocked_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~sort = zif_excel_sheet_protection=>c_noactive. + + endmethod. + + + method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME. + me->zif_excel_sheet_vba_project~codename = ip_codename. + endmethod. + + + method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME_PR. + me->zif_excel_sheet_vba_project~codename_pr = ip_codename_pr. + endmethod. + + + + method ADD_DRAWING. + CASE ip_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. + drawings->include( ip_drawing ). + WHEN zcl_excel_drawing=>type_chart. + charts->include( ip_drawing ). + ENDCASE. + endmethod. + + + + method ADD_NEW_CONDITIONAL_STYLE. + + CREATE OBJECT eo_conditional_style. + conditional_styles->add( eo_conditional_style ). + endmethod. + + + + method ADD_NEW_DATA_VALIDATION. + + CREATE OBJECT eo_data_validation. + data_validations->add( eo_data_validation ). + endmethod. + + + + method ADD_NEW_RANGE. +* Create default blank range + CREATE OBJECT eo_range. + ranges->add( eo_range ). + endmethod. + + + + + + + + + method BIND_ALV. + data: lo_converter type ref to zcl_excel_converter. + + create object lo_converter. + + try. + lo_converter->convert( + exporting + io_alv = io_alv + it_table = it_table + i_row_int = i_top + i_column_int = i_left + i_table = abap_true + i_style_table = table_style + io_worksheet = me + changing + co_excel = excel ). + catch zcx_excel . + endtry. + + endmethod. + + + + + + + + + + + + + + + + + + + + + + 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. + data: wa_DOC_HANDLE Type CNTL_HANDLE. + +* 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: <f_collect00> type standard table. + field-symbols: <f_collect01> type standard table. + field-symbols: <f_collect02> type standard table. + field-symbols: <f_collect03> type standard table. + field-symbols: <f_collect04> type standard table. + field-symbols: <f_collect05> type standard table. + field-symbols: <f_collect06> type standard table. + field-symbols: <f_collect07> type standard table. + field-symbols: <f_collect08> type standard table. + field-symbols: <f_collect09> type standard table. + +* table before append subtotal lines + field-symbols: <f_alv_tab> 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: <f_excel_tab> type standard table. + field-symbols: <f_excel_line> type any. + +* dyn subtotal tables + field-symbols: <f_collect_tab> type standard table. + field-symbols: <f_collect_line> type any. + + field-symbols: <f_filter_idx_line> like line of LT_FILTER_IDX_KKBLO. + field-symbols: <f_fieldcat_line> like line of LT_FIELDCAT_KKBLO. + field-symbols: <f_grouplevels_line> like line of LT_GROUPLEVELS_KKBLO. + field-symbols: <f_line> 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: <f_excel_column> type any. + field-symbols: <f_fcat_column> type any. + +* Data for session 4: write to excel +* ------------------------------------------ + + data: data_starting_at type i value 1. + data: data_ending_at type i value -1. + 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: <line> type any. + field-symbols: <item> 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 <f_alv_tab>. + +* 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 <f_collect00>. + assign lt_collect01->* to <f_collect01>. + assign lt_collect02->* to <f_collect02>. + assign lt_collect03->* to <f_collect03>. + assign lt_collect04->* to <f_collect04>. + assign lt_collect05->* to <f_collect05>. + assign lt_collect06->* to <f_collect06>. + assign lt_collect07->* to <f_collect07>. + assign lt_collect08->* to <f_collect08>. + assign lt_collect09->* to <f_collect09>. + +* 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 = <f_alv_tab> + 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 <f_ALV_TAB>. + assign lt_excel->* to <f_excel_tab>. + + loop at <f_alv_tab> assigning <f_line>. + l_save_index = sy-tabix. + +* filter base on filter index table + + read table LT_FILTER_IDX_KKBLO assigning <f_filter_idx_line> + with key index = l_save_index + binary search. + if sy-subrc ne 0. + append <f_line> to <f_excel_tab>. + endif. + +* append subtotal lines + + read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> + with key index_to = l_save_index + binary search. + if sy-subrc = 0. + l_tabix = sy-tabix. + do. + if <f_grouplevels_line>-subtot eq 'X' and + <f_grouplevels_line>-hide_level is initial and + <f_grouplevels_line>-cindex_from ne 0. + +* dynamic append subtotal line to excel table base on grouplevel table +* ex <f_GROUPLEVELS_line>-level = 1 +* then <f_collect_tab> = '<F_COLLECT01>' + + l_collect = <f_grouplevels_line>-level. + condense l_collect. + concatenate '<F_COLLECT0' + l_collect '>' +* '->*' + into l_collect. + + assign (l_collect) to <f_collect_tab>. + +* incase there're more than 1 total line of group, at the same level +* for example: subtotal of multi currency + + LOOP AT <f_collect_tab> assigning <f_collect_line>. + IF sy-tabix between <f_grouplevels_line>-cindex_from + and <f_grouplevels_line>-cindex_to. + + + append <f_collect_line> to <f_excel_tab>. + +* 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: <f_collect_tab>. + unassign: <f_collect_line>. + clear: l_collect. + endif. + +* check next subtotal level of group + + unassign: <f_grouplevels_line>. + add 1 to l_tabix. + + read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> + index l_tabix. + if sy-subrc ne 0 + or <f_grouplevels_line>-index_to ne l_save_index. + exit. + endif. + + unassign: + <f_collect_tab>, + <f_collect_line>. + + enddo. + endif. + + clear: + l_tabix, + l_save_index. + + unassign: + <f_filter_idx_line>, + <f_grouplevels_line>. + + endloop. + +* free local data + + unassign: + <f_line>, + <f_collect_tab>, + <f_collect_line>, + <f_fieldcat_line>. + +* append grand total line + + IF <f_collect00> is assigned. + assign <f_collect00> to <f_collect_tab>. + if <f_collect_tab> is not initial. + LOOP AT <f_collect_tab> assigning <f_collect_line>. + + append <f_collect_line> to <f_excel_tab>. + +* 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, + <f_collect00>, + <f_collect01>, + <f_collect02>, + <f_collect03>, + <f_collect04>, + <f_collect05>, + <f_collect06>, + <f_collect07>, + <f_collect08>, + <f_collect09>. + + unassign: + <f_collect00>, + <f_collect01>, + <f_collect02>, + <f_collect03>, + <f_collect04>, + <f_collect05>, + <f_collect06>, + <f_collect07>, + <f_collect08>, + <f_collect09>, + <f_collect_tab>, + <f_collect_line>. + +*--------------------------------------------------------------------* +* SESSION 3: MAP DATA TO SEMANTIC TABLE +*--------------------------------------------------------------------* + +* get dependent field field: currency and quantity + + create data wa like line of <f_excel_tab>. + assign wa->* to <f_excel_line>. + + describe field <f_excel_line> type l_typ components l_num. + + do l_num times. + l_save_index = sy-index. + assign component l_save_index of structure <f_excel_line> + to <f_excel_column>. + if sy-subrc ne 0. + message e059(0k) with 'FATAL ERROR' raising fatal_error. + endif. + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname. + assign component <f_fieldcat_line>-fieldname + of structure <f_excel_line> to <f_fcat_column>. + + describe distance between <f_excel_column> and <f_fcat_column> + 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 = <f_fieldcat_line>-fieldname. + wa_column_index-tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-cfieldname is not initial. + clear wa_fieldcat_depf. + wa_fieldcat_depf-fieldname = <f_fieldcat_line>-cfieldname. + wa_fieldcat_depf-tabname = <f_fieldcat_line>-ctabname. + collect wa_fieldcat_depf into lt_fieldcat_depf. + endif. + + if <f_fieldcat_line>-qfieldname is not initial. + clear wa_fieldcat_depf. + wa_fieldcat_depf-fieldname = <f_fieldcat_line>-qfieldname. + wa_fieldcat_depf-tabname = <f_fieldcat_line>-qtabname. + collect wa_fieldcat_depf into lt_fieldcat_depf. + endif. + +* rewrite field data type + + if <f_fieldcat_line>-inttype = 'X' + and <f_fieldcat_line>-datatype(3) = 'INT'. + <f_fieldcat_line>-inttype = 'I'. + endif. + + endloop. + + clear: l_save_index. + unassign: <f_fieldcat_line>. + + enddo. + +* build semantic tables + + l_n_hrz_keys = 1. + +* Get keyfigures + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + 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 = <f_fieldcat_line>-fieldname + tabname = <f_fieldcat_line>-tabname. + + if sy-subrc = 0. + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. + +* Keyfigures + + else. + case <f_fieldcat_line>-datatype. + when 'QUAN'. + wa_sema-col_typ = 'N03'. + + if <f_fieldcat_line>-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 <f_fieldcat_line>-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 = <f_fieldcat_line>-fieldname + tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-cfieldname is initial. + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-cfieldname + tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-qfieldname is initial. + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-qfieldname + tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-currency is initial. + + select * from tcurx into table lt_tcurx. + sort lt_tcurx. + read table lt_tcurx into wa_tcurx + with key currkey = <f_fieldcat_line>-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 = <f_fieldcat_line>-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: + <f_fieldcat_line>, + <f_excel_line>, + <f_excel_column>, + <f_fcat_column>. + +*--------------------------------------------------------------------* +* 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. + exit. + 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 <f_excel_tab> 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: wa_usr type usr01. + select * from usr01 into wa_usr where bname = sy-uname. + endselect. + + data: comma_elim(4) type c. + data: help6 type i. + field-symbols <g> 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 = wa_usr-datfm. + 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 = '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 <f_excel_tab> assigning <line>. + assign component semaitem-col_no of structure <line> to <item>. + describe field <item> 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 <line> type typ components count. + mit = 1. + do count times. + if mit = semaitem-col_src. + assign component sy-index of structure <line> to <item>. + describe field <item> 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: conv_exit(10) type c. + 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 <f_excel_tab> assigning <line>. + +* 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 <line> to <item>. + else. + assign component sy-index + of structure <line> to <item>. + 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 <item> is initial and not <item> co ' ' and not + <item> co '0'. +* change for date in char format & sema_type = X starts + if sema_type = 'X'. + describe field <item> type typ. + if typ = 'C'. + temp_date = <item>. + number_of_days = temp_date - genesis. + else. + number_of_days = <item> - genesis. + endif. + else. + number_of_days = <item> - 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 <item> 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 <item> type typ. + + if semaitem-col_cur is initial. + if typ ne 'F'. + write <item> to contentsitem-value no-grouping + no-sign decimals 14. + else. + write <item> 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 <item> to contentsitem-value no-grouping + currency wa_tcurx-currkey no-sign decimals 14. + else. + write <item> to contentsitem-value no-grouping + currency wa_tcurx-currkey no-sign. + endif. + endif. + else. + assign component semaitem-col_cur + of structure <line> to <g>. +* 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 <f_fieldcat_line> + with key tabname = l_tabname + tech = space + no_out = space + col_pos = semaitem-col_no. + IF sy-subrc = 0. + IF <f_fieldcat_line>-cfieldname is not initial. + l_def = 'C'. + else."if <f_fieldcat_line>-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 = <g>. +* 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 <item> to contentsitem-value + currency <g> + no-sign no-grouping. + else. + write <item> to contentsitem-value + decimals 14 currency <g> + 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 = <g>. +* 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 <item> to contentsitem-value + unit <g> + 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 <f_fieldcat_line> + where tabname = l_tabname + and tech ne 'X' + and no_out ne 'X'. + if <f_fieldcat_line>-col_pos = semaitem-col_no. + if <f_fieldcat_line>-no_zero = 'X'. + if <item> = '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. + if <item> = '0'. + clear: contentsitem-value. + endif. + ENDIF. + endif. + endif. + endloop. + unassign: <f_fieldcat_line>. + + if <item> lt 0. + search contentsitem-value for 'E'. + if sy-fdpos eq 0. + +* bring negative sign to front of amount + + 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 <item> 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: <f_fieldcat_line>. + +* 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: item type colxxl_t. + 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: <f_source> type any. + field-symbols: <f_des> 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 <f_source>. + if <f_source> is not initial. + assign component sy-index of structure wa_format to <f_des>. + <f_des> = <f_source>. + unassign: <f_des>. + endif. + unassign: <f_source>. + 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. + if 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. + 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. + if 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. + 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 <f_source>. + if <f_source> is not initial. + assign component sy-index of structure wa_format to <f_des>. + <f_des> = <f_source>. + unassign: <f_des>. + endif. + unassign: <f_source>. + 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, + <f_excel_tab>. + + clear: + lo_error_w. + + unassign: + <line>, + <item>, + <f_excel_tab>. + +*--------------------------------------------------------------------* +* 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 i499(sy) with 'Document is Exported to ' p_path. + message i499(sy) with 'Data has been exported successfully'. + + clear: + ls_path, + li_document_size. + + close_document. + endmethod. + + + + + + + + method BIND_TABLE. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (wi p) 2012-12-01 +* - ... +* aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue #237 - Check if overlapping areas exist +* - Alessandro Iannacci 2012-12-01 +* changes: - Added raise if overlaps are detected +*--------------------------------------------------------------------* + + CONSTANTS: + lc_top_left_column TYPE zexcel_cell_column_alpha VALUE 'B', + lc_top_left_row TYPE zexcel_cell_row VALUE '3'. + + DATA: + lv_row_int TYPE zexcel_cell_row, + lv_first_row TYPE zexcel_cell_row, + lv_last_row TYPE zexcel_cell_row, + lv_column_int TYPE zexcel_cell_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lt_field_catalog TYPE zexcel_t_fieldcatalog, + lv_id TYPE i, + lv_rows TYPE i, + lv_formula TYPE string, + ls_settings TYPE zexcel_s_table_settings, + lo_table TYPE REF TO zcl_excel_table, + lt_column_name_buffer TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line, + lv_value TYPE string, + lv_syindex TYPE char3, + lv_errormessage TYPE string, "ins issue #237 + + lv_columns TYPE i, + lt_columns TYPE zexcel_t_fieldcatalog, + lv_maxcol TYPE i, + lv_maxrow TYPE i, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_curtable TYPE REF TO zcl_excel_table. + + FIELD-SYMBOLS: + <ls_field_catalog> TYPE zexcel_s_fieldcatalog, + <ls_field_catalog_custom> TYPE zexcel_s_fieldcatalog, + <fs_table_line> TYPE ANY, + <fs_fldval> TYPE ANY. + + ls_settings = is_table_settings. + + IF ls_settings-top_left_column IS INITIAL. + ls_settings-top_left_column = lc_top_left_column. + ENDIF. + + IF ls_settings-table_style IS INITIAL. + ls_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ENDIF. + + IF ls_settings-top_left_row IS INITIAL. + ls_settings-top_left_row = lc_top_left_row. + ENDIF. + + IF it_field_catalog IS NOT SUPPLIED. + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = ip_table ). + ELSE. + lt_field_catalog = it_field_catalog. + ENDIF. + + SORT lt_field_catalog BY position. + +*--------------------------------------------------------------------* +* issue #237 Check if overlapping areas exist Start +*--------------------------------------------------------------------* + "Get the number of columns for the current table + lt_columns = lt_field_catalog. + DELETE lt_columns WHERE dynpfld NE abap_true. + DESCRIBE TABLE lt_columns LINES lv_columns. + + "Calculate the top left row of the current table + lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). + lv_row_int = ls_settings-top_left_row. + + "Get number of row for the current table + DESCRIBE TABLE ip_table LINES lv_rows. + + "Calculate the bottom right row for the current table + lv_maxcol = lv_column_int + lv_columns - 1. + lv_maxrow = lv_row_int + lv_rows - 1. + ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( lv_maxcol ). + ls_settings-bottom_right_row = lv_maxrow. + + lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). + + lo_iterator = me->tables->if_object_collection~get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + + lo_curtable ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF ( ( ls_settings-top_left_row GE lo_curtable->settings-top_left_row AND ls_settings-top_left_row LE lo_curtable->settings-bottom_right_row ) + OR + ( ls_settings-bottom_right_row GE lo_curtable->settings-top_left_row AND ls_settings-bottom_right_row LE lo_curtable->settings-bottom_right_row ) + ) + AND + ( ( lv_column_int GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_column_int LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) + OR + ( lv_maxcol GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_maxcol LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) + ). + lv_errormessage = 'Table overlaps with previously bound table and will not be added to worksheet.'(400). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDWHILE. +*--------------------------------------------------------------------* +* issue #237 Check if overlapping areas exist End +*--------------------------------------------------------------------* + + CREATE OBJECT lo_table. + lo_table->settings = ls_settings. + lo_table->set_data( ir_data = ip_table ). + lv_id = me->excel->get_next_table_id( ). + lo_table->set_id( iv_id = lv_id ). +* lo_table->fieldcat = lt_field_catalog[]. + + me->tables->add( lo_table ). + +* It is better to loop column by column (only visible column) + LOOP AT lt_field_catalog ASSIGNING <ls_field_catalog> WHERE dynpfld EQ abap_true. + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + + " Due restrinction of new table object we cannot have two column with the same name + " Check if a column with the same name exists, if exists add a counter + " If no medium description is provided we try to use small or long +* lv_value = <ls_field_catalog>-scrtext_m. + IF <ls_field_catalog>-scrtext_m IS NOT INITIAL. + lv_value = <ls_field_catalog>-scrtext_m. + <ls_field_catalog>-scrtext_l = lv_value. + ELSEIF <ls_field_catalog>-scrtext_s IS NOT INITIAL. + lv_value = <ls_field_catalog>-scrtext_s. + <ls_field_catalog>-scrtext_l = lv_value. + ELSEIF <ls_field_catalog>-scrtext_l IS NOT INITIAL. + lv_value = <ls_field_catalog>-scrtext_l. + ELSE. + lv_value = 'Column'. " default value as Excel does + <ls_field_catalog>-scrtext_l = lv_value. + ENDIF. + WHILE 1 = 1. + + READ TABLE lt_column_name_buffer TRANSPORTING NO FIELDS WITH KEY table_line = lv_value BINARY SEARCH. + IF sy-subrc <> 0. + <ls_field_catalog>-scrtext_l = lv_value. + INSERT lv_value INTO TABLE lt_column_name_buffer. + EXIT. + ELSE. + lv_syindex = sy-index. + CONCATENATE <ls_field_catalog>-scrtext_l lv_syindex INTO lv_value. + ENDIF. + + ENDWHILE. + " First of all write column header + IF <ls_field_catalog>-style_header IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_value + ip_style = <ls_field_catalog>-style_header ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_value ). + ENDIF. + + ADD 1 TO lv_row_int. + LOOP AT ip_table ASSIGNING <fs_table_line>. + + ASSIGN COMPONENT <ls_field_catalog>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. + " issue #290 Add formula support in table + IF <ls_field_catalog>-formula EQ abap_true. + IF <ls_field_catalog>-style IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> ). + ENDIF. + ELSE. + IF <ls_field_catalog>-style IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> ). + ENDIF. + ENDIF. + ADD 1 TO lv_row_int. + + ENDLOOP. + IF sy-subrc <> 0. "create empty row if table has no data + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = space ). + ADD 1 TO lv_row_int. + ENDIF. + +*--------------------------------------------------------------------* + " totals +*--------------------------------------------------------------------* + IF <ls_field_catalog>-totals_function IS NOT INITIAL. + lv_formula = lo_table->get_totals_formula( ip_column = <ls_field_catalog>-scrtext_l ip_function = <ls_field_catalog>-totals_function ). + IF <ls_field_catalog>-style_total IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = lv_formula + ip_style = <ls_field_catalog>-style_total ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = lv_formula ). + ENDIF. + ENDIF. + + lv_row_int = ls_settings-top_left_row. + ADD 1 TO lv_column_int. + +*--------------------------------------------------------------------* + " conditional formatting +*--------------------------------------------------------------------* + IF <ls_field_catalog>-cond_style IS NOT INITIAL. + lv_first_row = ls_settings-top_left_row + 1. " +1 to exclude header + lv_last_row = ls_settings-top_left_row + lv_rows. + <ls_field_catalog>-cond_style->set_range( ip_start_column = lv_column_alpha + ip_start_row = lv_first_row + ip_stop_column = lv_column_alpha + ip_stop_row = lv_last_row ). + ENDIF. + + ENDLOOP. + +*--------------------------------------------------------------------* + " Set field catalog +*--------------------------------------------------------------------* + lo_table->fieldcat = lt_field_catalog[]. + + es_table_settings = ls_settings. + es_table_settings-bottom_right_column = lv_column_alpha. + " >> Issue #291 + IF ip_table IS INITIAL. + es_table_settings-bottom_right_row = ls_settings-top_left_row + 2. "Last rows + ELSE. + es_table_settings-bottom_right_row = ls_settings-top_left_row + lv_rows + 1. "Last rows + ENDIF. + " << Issue #291 + + endmethod. + + + + + + + method CALCULATE_CELL_WIDTH. + DATA: cell_value TYPE zexcel_cell_value, + guid TYPE zexcel_cell_style, + stylemapping TYPE zexcel_s_stylemapping. + + me->get_cell( EXPORTING ip_column = ip_column " Cell Column + ip_row = ip_row " Cell Row + IMPORTING ep_value = cell_value + ep_guid = guid )." Cell Value ). + + + ep_width = STRLEN( cell_value ). + TRY. + stylemapping = me->excel->get_style_to_guid( guid ). + CATCH zcx_excel. + EXIT. " Do nothing if no style was found + ENDTRY. + + IF stylemapping-complete_stylex-font-size = 'X'. + ep_width = ep_width * stylemapping-complete_style-font-size / 11. + ENDIF. + + endmethod. + + + + method CALCULATE_COLUMN_WIDTHS. + TYPES: + BEGIN OF t_auto_size, + col_index TYPE int4, + width TYPE float, + END OF t_auto_size. + TYPES: tt_auto_size TYPE TABLE OF t_auto_size. + + DATA: column_dimensions TYPE zexcel_t_worksheet_columndime. + DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + DATA: auto_size TYPE flag. + DATA: auto_sizes TYPE tt_auto_size. +* DATA: col_alpha TYPE zexcel_cell_column_alpha." issue #155 - less restrictive typing for ip_column + DATA: cell_value TYPE zexcel_cell_value. + DATA: cell_style TYPE REF TO zcl_excel_style. + DATA: count TYPE int4. + DATA: highest_row TYPE int4. + DATA: width TYPE i. + + FIELD-SYMBOLS: <column_dimension> LIKE LINE OF column_dimensions. + FIELD-SYMBOLS: <auto_size> LIKE LINE OF auto_sizes. + + column_dimensions[] = me->get_column_dimensions( ). + LOOP AT column_dimensions ASSIGNING <column_dimension>. + auto_size = <column_dimension>-column_dimension->get_auto_size( ). + IF auto_size = abap_true. + APPEND INITIAL LINE TO auto_sizes ASSIGNING <auto_size>. + <auto_size>-col_index = <column_dimension>-column_dimension->get_column_index( ). + <auto_size>-width = -1. + ENDIF. + ENDLOOP. + + " There is only something to do if there are some auto-size columns + IF NOT auto_sizes IS INITIAL. + highest_row = me->get_highest_row( ). + LOOP AT auto_sizes ASSIGNING <auto_size>. +* col_alpha = zcl_excel_common=>convert_column2alpha( <auto_size>-col_index )." issue #155 - less restrictive typing for ip_column + count = 1. + WHILE count <= highest_row. +* Start of change # issue 139 - Dateretention of cellstyles +* IF cell_style IS BOUND. +* CREATE OBJECT cell_style. +* ENDIF. +* me->get_cell( +* EXPORTING +* ip_column = col_alpha " Cell Column +* ip_row = count " Cell Row +* IMPORTING +* ep_value = cell_value " Cell Value +* ep_style = cell_style " Request Cell Style as well +* ). +* " For an easy start we just take the number of characters as the width +* width = strlen( cell_value ). +* " Addition to solve issue #120, contribution by Stefan Schm#ƒÂ#cker +* " Calculate width using Font Size and Font Type +* IF cell_style IS BOUND +* AND cell_style->font IS BOUND. +* width = cell_style->font->calculate_text_width( cell_value ). +* ENDIF. +* width = calculate_cell_width( ip_column = col_alpha " issue #155 - less restrictive typing for ip_column + width = calculate_cell_width( ip_column = <auto_size>-col_index " issue #155 - less restrictive typing for ip_column + ip_row = count ). +* End of change # issue 139 - Dateretention of cellstyles + IF width > <auto_size>-width. + <auto_size>-width = width. + ENDIF. + count = count + 1. + ENDWHILE. +* column_dimension = me->get_column_dimension( col_alpha ). " issue #155 - less restrictive typing for ip_column + column_dimension = me->get_column_dimension( <auto_size>-col_index ). " issue #155 - less restrictive typing for ip_column + column_dimension->set_width( <auto_size>-width ). + ENDLOOP. + ENDIF. + + endmethod. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CHANGE_CELL_STYLE. + " issue # 139 + DATA: stylemapping TYPE zexcel_s_stylemapping, + + complete_style TYPE zexcel_s_cstyle_complete, + complete_stylex TYPE zexcel_s_cstylex_complete, + + borderx TYPE zexcel_s_cstylex_border, + l_guid TYPE zexcel_cell_style. "issue # 177 + +* We have a lot of parameters. Use some macros to make the coding more structured + + DEFINE clear_initial_colorxfields. + if &1-rgb is initial. + clear &2-rgb. + endif. + if &1-indexed is initial. + clear &2-indexed. + endif. + if &1-theme is initial. + clear &2-theme. + endif. + if &1-tint is initial. + clear &2-tint. + endif. + END-OF-DEFINITION. + + DEFINE move_supplied_borders. + if ip_&1 is supplied. " only act if parameter was supplied + if ip_x&1 is supplied. " + borderx = ip_x&1. " use supplied x-parameter + else. + clear borderx with 'X'. +* clear in a way that would be expected to work easily + if ip_&1-border_style is initial. + clear borderx-border_style. + endif. + clear_initial_colorxfields ip_&1-border_color borderx-border_color. + endif. + move-corresponding ip_&1 to complete_style-&2. + move-corresponding borderx to complete_stylex-&2. + endif. + END-OF-DEFINITION. + +* First get current stylsettings + TRY. + me->get_cell( EXPORTING ip_column = ip_column " Cell Column + ip_row = ip_row " Cell Row + IMPORTING ep_guid = l_guid )." Cell Value ). "issue # 177 + + + stylemapping = me->excel->get_style_to_guid( l_guid ). "issue # 177 + complete_style = stylemapping-complete_style. + complete_stylex = stylemapping-complete_stylex. + CATCH zcx_excel. +* Error --> use submitted style + ENDTRY. + +* move_supplied_multistyles: complete. + IF ip_complete IS SUPPLIED. + IF ip_xcomplete IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Complete styleinfo has to be supplied with corresponding X-field'. + ENDIF. + MOVE-CORRESPONDING ip_complete TO complete_style. + MOVE-CORRESPONDING ip_xcomplete TO complete_stylex. + ENDIF. + + + + IF ip_font IS SUPPLIED. + DATA: fontx LIKE ip_xfont. + IF ip_xfont IS SUPPLIED. + fontx = ip_xfont. + ELSE. +* Only supplied values should be used - exception: Flags bold and italic strikethrough underline + MOVE 'X' TO: fontx-bold, + fontx-italic, + fontx-strikethrough, + fontx-underline_mode. + CLEAR fontx-color WITH 'X'. + clear_initial_colorxfields ip_font-color fontx-color. + IF ip_font-family IS NOT INITIAL. + fontx-family = 'X'. + ENDIF. + IF ip_font-name IS NOT INITIAL. + fontx-name = 'X'. + ENDIF. + IF ip_font-scheme IS NOT INITIAL. + fontx-scheme = 'X'. + ENDIF. + IF ip_font-size IS NOT INITIAL. + fontx-size = 'X'. + ENDIF. + IF ip_font-underline_mode IS NOT INITIAL. + fontx-underline_mode = 'X'. + ENDIF. + ENDIF. + MOVE-CORRESPONDING ip_font TO complete_style-font. + MOVE-CORRESPONDING fontx TO complete_stylex-font. +* Correction for undeline mode + ENDIF. + + IF ip_fill IS SUPPLIED. + DATA: fillx LIKE ip_xfill. + IF ip_xfill IS SUPPLIED. + fillx = ip_xfill. + ELSE. + CLEAR fillx WITH 'X'. + IF ip_fill-filltype IS INITIAL. + CLEAR fillx-filltype. + ENDIF. + clear_initial_colorxfields ip_fill-fgcolor fillx-fgcolor. + clear_initial_colorxfields ip_fill-bgcolor fillx-bgcolor. + + ENDIF. + MOVE-CORRESPONDING ip_fill TO complete_style-fill. + MOVE-CORRESPONDING fillx TO complete_stylex-fill. + ENDIF. + + + IF ip_borders IS SUPPLIED. + DATA: bordersx LIKE ip_xborders. + IF ip_xborders IS SUPPLIED. + bordersx = ip_xborders. + ELSE. + CLEAR bordersx WITH 'X'. + IF ip_borders-allborders-border_style IS INITIAL. + CLEAR bordersx-allborders-border_style. + ENDIF. + IF ip_borders-diagonal-border_style IS INITIAL. + CLEAR bordersx-diagonal-border_style. + ENDIF. + IF ip_borders-down-border_style IS INITIAL. + CLEAR bordersx-down-border_style. + ENDIF. + IF ip_borders-left-border_style IS INITIAL. + CLEAR bordersx-left-border_style. + ENDIF. + IF ip_borders-right-border_style IS INITIAL. + CLEAR bordersx-right-border_style. + ENDIF. + IF ip_borders-top-border_style IS INITIAL. + CLEAR bordersx-top-border_style. + ENDIF. + clear_initial_colorxfields ip_borders-allborders-border_color bordersx-allborders-border_color. + clear_initial_colorxfields ip_borders-diagonal-border_color bordersx-diagonal-border_color. + clear_initial_colorxfields ip_borders-down-border_color bordersx-down-border_color. + clear_initial_colorxfields ip_borders-left-border_color bordersx-left-border_color. + clear_initial_colorxfields ip_borders-right-border_color bordersx-right-border_color. + clear_initial_colorxfields ip_borders-top-border_color bordersx-top-border_color. + + ENDIF. + MOVE-CORRESPONDING ip_borders TO complete_style-borders. + MOVE-CORRESPONDING bordersx TO complete_stylex-borders. + ENDIF. + + IF ip_alignment IS SUPPLIED. + DATA: alignmentx LIKE ip_xalignment. + IF ip_xalignment IS SUPPLIED. + alignmentx = ip_xalignment. + ELSE. + CLEAR alignmentx WITH 'X'. + IF ip_alignment-horizontal IS INITIAL. + CLEAR alignmentx-horizontal. + ENDIF. + IF ip_alignment-vertical IS INITIAL. + CLEAR alignmentx-vertical. + ENDIF. + ENDIF. + MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. + MOVE-CORRESPONDING alignmentx TO complete_stylex-alignment. + ENDIF. + + IF ip_protection IS SUPPLIED. + MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. + IF ip_xprotection IS SUPPLIED. + MOVE-CORRESPONDING ip_xprotection TO complete_stylex-protection. + ELSE. + IF ip_protection-hidden IS NOT INITIAL. + complete_style-protection-hidden = 'X'. + ENDIF. + IF ip_protection-locked IS NOT INITIAL. + complete_style-protection-locked = 'X'. + ENDIF. + ENDIF. + ENDIF. + + + move_supplied_borders : borders_allborders borders-allborders, + borders_diagonal borders-diagonal , + borders_down borders-down , + borders_left borders-left , + borders_right borders-right , + borders_top borders-top . + + DEFINE move_supplied_singlestyles. + if ip_&1 is supplied. + complete_style-&2 = ip_&1. + complete_stylex-&2 = 'X'. + endif. + END-OF-DEFINITION. + + move_supplied_singlestyles: number_format_format_code number_format-format_code, + font_bold font-bold, + font_color font-color, + font_color_rgb font-color-rgb, + font_color_indexed font-color-indexed, + font_color_theme font-color-theme, + font_color_tint font-color-tint, + + font_family font-family, + font_italic font-italic, + font_name font-name, + font_scheme font-scheme, + font_size font-size, + font_strikethrough font-strikethrough, + font_underline font-underline, + font_underline_mode font-underline_mode, + fill_filltype fill-filltype, + fill_rotation fill-rotation, + fill_fgcolor fill-fgcolor, + fill_fgcolor_rgb fill-fgcolor-rgb, + fill_fgcolor_indexed fill-fgcolor-indexed, + fill_fgcolor_theme fill-fgcolor-theme, + fill_fgcolor_tint fill-fgcolor-tint, + + fill_bgcolor fill-bgcolor, + fill_bgcolor_rgb fill-bgcolor-rgb, + fill_bgcolor_indexed fill-bgcolor-indexed, + fill_bgcolor_theme fill-bgcolor-theme, + fill_bgcolor_tint fill-bgcolor-tint, + + borders_diagonal_mode borders-diagonal_mode, + alignment_horizontal alignment-horizontal, + alignment_vertical alignment-vertical, + alignment_textrotation alignment-textrotation, + alignment_wraptext alignment-wraptext, + alignment_shrinktofit alignment-shrinktofit, + alignment_indent alignment-indent, + protection_hidden protection-hidden, + protection_locked protection-locked, + + borders_allborders_style borders-allborders-border_style, + borders_allborders_color borders-allborders-border_color, + borders_allbo_color_rgb borders-allborders-border_color-rgb, + borders_allbo_color_indexed borders-allborders-border_color-indexed, + borders_allbo_color_theme borders-allborders-border_color-theme, + borders_allbo_color_tint borders-allborders-border_color-tint, + + borders_diagonal_style borders-diagonal-border_style, + borders_diagonal_color borders-diagonal-border_color, + borders_diagonal_color_rgb borders-diagonal-border_color-rgb, + borders_diagonal_color_inde borders-diagonal-border_color-indexed, + borders_diagonal_color_them borders-diagonal-border_color-theme, + borders_diagonal_color_tint borders-diagonal-border_color-tint, + + borders_down_style borders-down-border_style, + borders_down_color borders-down-border_color, + borders_down_color_rgb borders-down-border_color-rgb, + borders_down_color_indexed borders-down-border_color-indexed, + borders_down_color_theme borders-down-border_color-theme, + borders_down_color_tint borders-down-border_color-tint, + + borders_left_style borders-left-border_style, + borders_left_color borders-left-border_color, + borders_left_color_rgb borders-left-border_color-rgb, + borders_left_color_indexed borders-left-border_color-indexed, + borders_left_color_theme borders-left-border_color-theme, + borders_left_color_tint borders-left-border_color-tint, + + borders_right_style borders-right-border_style, + borders_right_color borders-right-border_color, + borders_right_color_rgb borders-right-border_color-rgb, + borders_right_color_indexed borders-right-border_color-indexed, + borders_right_color_theme borders-right-border_color-theme, + borders_right_color_tint borders-right-border_color-tint, + + borders_top_style borders-top-border_style, + borders_top_color borders-top-border_color, + borders_top_color_rgb borders-top-border_color-rgb, + borders_top_color_indexed borders-top-border_color-indexed, + borders_top_color_theme borders-top-border_color-theme, + borders_top_color_tint borders-top-border_color-tint. + + +* Now we have a completly filled styles. +* This can be used to get the guid +* Return guid if requested. Might be used if copy&paste of styles is requested + ep_guid = me->excel->get_static_cellstyle_guid( ip_cstyle_complete = complete_style + ip_cstylex_complete = complete_stylex ). + me->set_cell_style( ip_column = ip_column + ip_row = ip_row + ip_style = ep_guid ). + + endmethod. + + + + + + method CONSTRUCTOR. + DATA: lv_title TYPE zexcel_sheet_title. + + me->excel = ip_excel. + + CALL FUNCTION 'GUID_CREATE' + IMPORTING + ev_guid_16 = me->guid. + + IF ip_title IS NOT INITIAL. + lv_title = ip_title. + ELSE. +* lv_title = me->guid. " del issue #154 - Names of worksheets + lv_title = me->generate_title( ). " ins issue #154 - Names of worksheets + ENDIF. + + me->set_title( ip_title = lv_title ). + + CREATE OBJECT sheet_setup. + CREATE OBJECT conditional_styles. + CREATE OBJECT data_validations. + CREATE OBJECT tables. + CREATE OBJECT ranges. " issue #163 + CREATE OBJECT drawings + EXPORTING + ip_type = zcl_excel_drawing=>type_image. + CREATE OBJECT charts + EXPORTING + ip_type = zcl_excel_drawing=>type_chart. + me->zif_excel_sheet_protection~initialize( ). + me->zif_excel_sheet_properties~initialize( ). + CREATE OBJECT hyperlinks. + +* initialize active cell coordinates + active_cell-cell_row = 1. + active_cell-cell_column = 1. + +* inizialize dimension range + lower_cell-cell_row = 1. + lower_cell-cell_column = 1. + upper_cell-cell_row = 1. + upper_cell-cell_column = 1. + + endmethod. + + + method DELETE_MERGE. + + DELETE sheet_content_merge INDEX 1. + DELETE sheet_content_merge INDEX 1. + + endmethod. + + + + + + method FREEZE_PANES. + data: lv_xsplit type i, + lv_ysplit type i. + + IF ip_num_columns IS NOT SUPPLIED AND ip_num_rows IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Pleas provide number of rows and/or columns to freeze'. + ENDIF. + + IF ip_num_columns IS SUPPLIED AND ip_num_columns <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Number of columns to freeze should be positive'. + ENDIF. + + IF ip_num_rows IS SUPPLIED AND ip_num_rows <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Number of rows to freeze should be positive'. + ENDIF. + + freeze_pane_cell_column = ip_num_columns + 1. + freeze_pane_cell_row = ip_num_rows + 1. + endmethod. + + + + method GENERATE_TITLE. + DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + errormessage TYPE string. + + DATA: t_titles TYPE HASHED TABLE OF zexcel_sheet_title WITH UNIQUE KEY table_line, + title TYPE zexcel_sheet_title, + sheetnumber TYPE i. + +* Get list of currently used titles + lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_worksheets_iterator->has_next( ) = abap_true. + lo_worksheet ?= lo_worksheets_iterator->get_next( ). + title = lo_worksheet->get_title( ). + INSERT title INTO TABLE t_titles. + ADD 1 TO sheetnumber. + ENDWHILE. + +* Now build sheetnumber. Increase counter until we hit a number that is not used so far + ADD 1 TO sheetnumber. " Start counting with next number + DO. + title = sheetnumber. + SHIFT title LEFT DELETING LEADING space. + CONCATENATE 'Sheet'(001) title INTO ep_title. + INSERT ep_title INTO TABLE t_titles. + IF sy-subrc = 0. " Title not used so far --> take it + EXIT. + ENDIF. + + ADD 1 TO sheetnumber. + ENDDO. + endmethod. + + + + + method GET_ACTIVE_CELL. + + DATA: lv_active_column TYPE zexcel_cell_column_alpha, + lv_active_row TYPE string. + + lv_active_column = zcl_excel_common=>convert_column2alpha( active_cell-cell_column ). + lv_active_row = active_cell-cell_row. + SHIFT lv_active_row RIGHT DELETING TRAILING space. + SHIFT lv_active_row LEFT DELETING LEADING space. + CONCATENATE lv_active_column lv_active_row INTO ep_active_cell. + + endmethod. + + + + + + + + + + method GET_CELL. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + READ TABLE sheet_content INTO ls_sheet_content WITH TABLE KEY cell_row = ip_row + cell_column = lv_column. + + ep_rc = sy-subrc. + ep_value = ls_sheet_content-cell_value. + ep_guid = ls_sheet_content-cell_style. " issue 139 - added this to be used for columnwidth calculation + + " Addition to solve issue #120, contribution by Stefan Schm#ƒÂ#cker + DATA: style_iterator TYPE REF TO cl_object_collection_iterator, + style TYPE REF TO zcl_excel_style. + IF ep_style IS REQUESTED. + style_iterator = me->excel->get_styles_iterator( ). + WHILE style_iterator->has_next( ) = 'X'. + style ?= style_iterator->get_next( ). + IF style->get_guid( ) = ls_sheet_content-cell_style. + ep_style = style. + EXIT. + ENDIF. + ENDWHILE. + ENDIF. + endmethod. + + + + + + method GET_COLUMN_DIMENSION. + FIELD-SYMBOLS: <fs_column_dimension> LIKE LINE OF column_dimensions. + DATA: lv_column_alpha TYPE zexcel_cell_column_alpha. " issue #155 - less restrictive typing for ip_column + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column )." issue #155 - less restrictive typing for ip_column + READ TABLE me->column_dimensions ASSIGNING <fs_column_dimension> + WITH KEY column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column + + IF NOT <fs_column_dimension> IS ASSIGNED. + CREATE OBJECT r_column_dimension + EXPORTING + ip_index = lv_column_alpha " issue #155 - less restrictive typing for ip_column + ip_excel = me->excel " issue #157 - Allow style for columns + ip_worksheet = me. " issue #157 - Allow style for columns + APPEND INITIAL LINE TO me->column_dimensions ASSIGNING <fs_column_dimension>. + <fs_column_dimension>-column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column + <fs_column_dimension>-column_dimension = r_column_dimension. + ELSE. + r_column_dimension = <fs_column_dimension>-column_dimension. + ENDIF. + + endmethod. + + + + method GET_COLUMN_DIMENSIONS. + r_column_dimension[] = me->column_dimensions[]. + endmethod. + + + + method GET_COND_STYLES_ITERATOR. + + eo_iterator = me->conditional_styles->get_iterator( ). + endmethod. + + + + method GET_DATA_VALIDATIONS_ITERATOR. + + eo_iterator = me->data_validations->get_iterator( ). + endmethod. + + + + method GET_DATA_VALIDATIONS_SIZE. + ep_size = me->data_validations->size( ). + endmethod. + + + + method GET_DEFAULT_COLUMN_DIMENSION. + IF me->default_column_dimension IS NOT BOUND. + CREATE OBJECT me->default_column_dimension + EXPORTING + ip_index = 'A' " ???? + ip_worksheet = me + ip_excel = me->excel. + ENDIF. + + r_column_dimension = me->default_column_dimension. + endmethod. + + + + method GET_DEFAULT_EXCEL_DATE_FORMAT. + CONSTANTS: c_lang_e TYPE lang VALUE 'E'. + + IF default_excel_date_format IS NOT INITIAL. + ep_default_excel_date_format = default_excel_date_format. + RETURN. + ENDIF. + + "try to get defaults + TRY. + cl_abap_datfm=>get_date_format_des( EXPORTING im_langu = c_lang_e + IMPORTING ex_dateformat = default_excel_date_format ). + CATCH cx_abap_datfm_format_unknown. + + ENDTRY. + + " and fallback to fixed format + IF default_excel_date_format IS INITIAL. + default_excel_date_format = zcl_excel_style_number_format=>c_format_date_ddmmyyyydot. + ENDIF. + + ep_default_excel_date_format = default_excel_date_format. + endmethod. + + + + method GET_DEFAULT_EXCEL_TIME_FORMAT. + DATA: l_timefm TYPE xutimefm. + + IF default_excel_time_format IS NOT INITIAL. + ep_default_excel_time_format = default_excel_time_format. + RETURN. + ENDIF. + +* Let's get default + l_timefm = cl_abap_timefm=>get_environment_timefm( ). + CASE l_timefm. + WHEN 0. +*0 24 Hour Format (Example: 12:05:10) + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. + WHEN 1. +*1 12 Hour Format (Example: 12:05:10 PM) + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 2. +*2 12 Hour Format (Example: 12:05:10 pm) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 3. +*3 Hours from 0 to 11 (Example: 00:05:10 PM) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 4. +*4 Hours from 0 to 11 (Example: 00:05:10 pm) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN OTHERS. + " and fallback to fixed format + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. + ENDCASE. + + ep_default_excel_time_format = default_excel_time_format. + endmethod. + + + + method GET_DEFAULT_ROW_DIMENSION. + IF me->default_row_dimension IS NOT BOUND. + CREATE OBJECT me->default_row_dimension. + ENDIF. + + r_row_dimension = me->default_row_dimension. + endmethod. + + + + + method GET_DIMENSION_RANGE. + + me->update_dimension_range( ). + IF upper_cell EQ lower_cell. "only one cell + " Worksheet not filled +* IF upper_cell-cell_coords = '0'. + IF upper_cell-cell_coords IS INITIAL. + ep_dimension_range = 'A1'. + ELSE. + ep_dimension_range = upper_cell-cell_coords. + ENDIF. + ELSE. + CONCATENATE upper_cell-cell_coords ':' lower_cell-cell_coords INTO ep_dimension_range. + ENDIF. + + endmethod. + + + + + method GET_DRAWINGS. + + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + lo_iterator TYPE REF TO cl_object_collection_iterator. + + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + r_drawings = drawings. + WHEN zcl_excel_drawing=>type_chart. + r_drawings = charts. + WHEN space. + CREATE OBJECT r_drawings + EXPORTING + ip_type = ''. + + lo_iterator = drawings->get_iterator( ). + WHILE lo_iterator->has_next( ) = abap_true. + lo_drawing ?= lo_iterator->get_next( ). + r_drawings->include( lo_drawing ). + ENDWHILE. + lo_iterator = charts->get_iterator( ). + WHILE lo_iterator->has_next( ) = abap_true. + lo_drawing ?= lo_iterator->get_next( ). + r_drawings->include( lo_drawing ). + ENDWHILE. + WHEN OTHERS. + ENDCASE. + endmethod. + + + + + method GET_DRAWINGS_ITERATOR. + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + eo_iterator = drawings->get_iterator( ). + WHEN zcl_excel_drawing=>type_chart. + eo_iterator = charts->get_iterator( ). + ENDCASE. + endmethod. + + + + + method GET_FREEZE_CELL. + ep_row = me->freeze_pane_cell_row. + ep_column = me->freeze_pane_cell_column. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + + method GET_HIGHEST_COLUMN. + me->update_dimension_range( ). + r_highest_column = me->lower_cell-cell_column. + endmethod. + + + + + method GET_HIGHEST_ROW. + me->update_dimension_range( ). + r_highest_row = me->lower_cell-cell_row. + endmethod. + + + + method GET_HYPERLINKS_ITERATOR. + eo_iterator = hyperlinks->get_iterator( ). + endmethod. + + + + method GET_HYPERLINKS_SIZE. + ep_size = hyperlinks->size( ). + endmethod. + + + + + method GET_MERGE. + + DATA: lv_column_start TYPE string, + lv_column_end TYPE string, + lv_row TYPE string, + lv_index TYPE sy-tabix, + ls_sheet_content TYPE zexcel_s_cell_data, + range_from TYPE string, + range_to TYPE string, + lv_merge_range TYPE string, + lv_count TYPE string. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + DESCRIBE TABLE sheet_content_merge LINES lv_count. + + WHILE lv_count GT lv_index. +* LOOP AT sheet_content_merge ASSIGNING <fs_sheet_content>. + lv_index = lv_index + 1. + READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX lv_index. + lv_column_start = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). + lv_row = <fs_sheet_content>-cell_row. + SHIFT lv_column_start RIGHT DELETING TRAILING space. + SHIFT lv_column_start LEFT DELETING LEADING space. + SHIFT lv_row RIGHT DELETING TRAILING space. + SHIFT lv_row LEFT DELETING LEADING space. + CONCATENATE lv_column_start lv_row + INTO range_from. + + lv_index = lv_index + 1. + READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX lv_index. + lv_column_end = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). + lv_row = <fs_sheet_content>-cell_row. + SHIFT lv_column_end RIGHT DELETING TRAILING space. + SHIFT lv_column_end LEFT DELETING LEADING space. + SHIFT lv_row RIGHT DELETING TRAILING space. + SHIFT lv_row LEFT DELETING LEADING space. + CONCATENATE lv_column_end lv_row + INTO range_to. + + CONCATENATE range_from range_to INTO lv_merge_range + SEPARATED BY ':'. + APPEND lv_merge_range TO merge_range. + ENDWHILE. +* ENDLOOP. + +* READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX 1. +* IF sy-subrc EQ 0 AND <fs_sheet_content> IS ASSIGNED. +* lv_column_start = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). +* lv_row = <fs_sheet_content>-cell_row. +* SHIFT lv_column_start RIGHT DELETING TRAILING space. +* SHIFT lv_column_start LEFT DELETING LEADING space. +* SHIFT lv_row RIGHT DELETING TRAILING space. +* SHIFT lv_row LEFT DELETING LEADING space. +* CONCATENATE lv_column_start lv_row +* INTO range_from. +* ENDIF. +* READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX 2. +* IF sy-subrc EQ 0 AND <fs_sheet_content> IS ASSIGNED. +* lv_column_end = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). +* SHIFT lv_column_end RIGHT DELETING TRAILING space. +* SHIFT lv_column_end LEFT DELETING LEADING space. +* CONCATENATE lv_column_end lv_row +* INTO range_to. +* ENDIF. + +* IF range_from NE space AND range_to NE space. +* CONCATENATE range_from range_to INTO ep_merge_range +* SEPARATED BY ':'. +* ENDIF. + + endmethod. + + + + method GET_RANGES_ITERATOR. + + eo_iterator = me->ranges->get_iterator( ). + + endmethod. + + + + + method GET_ROW_DIMENSION. + FIELD-SYMBOLS: <fs_row_dimension> LIKE LINE OF row_dimensions. + + READ TABLE me->row_dimensions ASSIGNING <fs_row_dimension> + WITH KEY row = ip_row. + + IF NOT <fs_row_dimension> IS ASSIGNED. + CREATE OBJECT r_row_dimension + EXPORTING + ip_index = ip_row. + APPEND INITIAL LINE TO me->row_dimensions ASSIGNING <fs_row_dimension>. + <fs_row_dimension>-row = ip_row. + <fs_row_dimension>-row_dimension = r_row_dimension. + ELSE. + r_row_dimension = <fs_row_dimension>-row_dimension. + ENDIF. + + endmethod. + + + + method GET_ROW_DIMENSIONS. + r_row_dimension[] = me->row_dimensions[]. + endmethod. + + + + method GET_TABCOLOR. + ev_tabcolor = me->tabcolor. + endmethod. + + + + method GET_TABLES_ITERATOR. + eo_iterator = tables->if_object_collection~get_iterator( ). + endmethod. + + + + method GET_TABLES_SIZE. + ep_size = tables->if_object_collection~size( ). + endmethod. + + + + + method GET_TITLE. + DATA lv_value TYPE string. + IF ip_escaped EQ abap_true. + lv_value = me->title. + ep_title = zcl_excel_common=>escape_string( lv_value ). + ELSE. + ep_title = me->title. + ENDIF. + endmethod. + + + + + + method GET_VALUE_TYPE. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + ls_dfies TYPE dfies, + l_function TYPE funcname, + l_value(50) TYPE c. + + ep_value = ip_value. + ep_value_type = cl_abap_typedescr=>typekind_string. " Thats our default if something goes wrong. + + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ip_value ). + CATCH cx_sy_move_cast_error. + CLEAR lo_addit. + ENDTRY. + IF lo_addit IS BOUND. + lo_addit->get_ddic_field( RECEIVING p_flddescr = ls_dfies + EXCEPTIONS not_found = 1 + no_ddic_type = 2 + OTHERS = 3 ) . + IF sy-subrc = 0. + ep_value_type = ls_dfies-inttype. + + IF ls_dfies-convexit IS NOT INITIAL. +* We need to convert with output conversion function + CONCATENATE 'CONVERSION_EXIT_' ls_dfies-convexit '_OUTPUT' INTO l_function. + SELECT SINGLE funcname INTO l_function + FROM tfdir + WHERE funcname = l_function. + IF sy-subrc = 0. + CALL FUNCTION l_function + EXPORTING + input = ip_value + IMPORTING +* LONG_TEXT = + output = l_value +* SHORT_TEXT = + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ELSE. + ep_value = l_value. + ENDIF. + ENDIF. + ENDIF. + ELSE. + ep_value_type = lo_addit->get_data_type_kind( ip_value ). + ENDIF. + ENDIF. + + endmethod. + + + method PRINT_TITLE_SET_RANGE. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range, + lv_repeat_range_sheetname TYPE string, + lv_repeat_range_col TYPE string, + lv_row_char_from TYPE char10, + lv_row_char_to TYPE char10, + lv_repeat_range_row TYPE string, + lv_repeat_range TYPE string. + + +*--------------------------------------------------------------------* +* Get range that represents printarea +* if non-existant, create it +*--------------------------------------------------------------------* + lo_range_iterator = me->get_ranges_iterator( ). + WHILE lo_range_iterator->has_next( ) = abap_true. + + lo_range ?= lo_range_iterator->get_next( ). + IF lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. + EXIT. " Found it + ENDIF. + CLEAR lo_range. + + ENDWHILE. + + + IF me->print_title_col_from IS INITIAL AND + me->print_title_row_from IS INITIAL. +*--------------------------------------------------------------------* +* No print titles are present, +*--------------------------------------------------------------------* + IF lo_range IS BOUND. + me->ranges->remove( lo_range ). + ENDIF. + ELSE. +*--------------------------------------------------------------------* +* Print titles are present, +*--------------------------------------------------------------------* + IF lo_range IS NOT BOUND. + lo_range = me->add_new_range( ). + lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. + ENDIF. + + lv_repeat_range_sheetname = me->get_title( ). + lv_repeat_range_sheetname = zcl_excel_common=>escape_string( lv_repeat_range_sheetname ). + +*--------------------------------------------------------------------* +* Repeat-columns +*--------------------------------------------------------------------* + IF me->print_title_col_from IS NOT INITIAL. + CONCATENATE lv_repeat_range_sheetname + '!$' me->print_title_col_from + ':$' me->print_title_col_to + INTO lv_repeat_range_col. + ENDIF. + +*--------------------------------------------------------------------* +* Repeat-rows +*--------------------------------------------------------------------* + IF me->print_title_row_from IS NOT INITIAL. + lv_row_char_from = me->print_title_row_from. + lv_row_char_to = me->print_title_row_to. + CONCATENATE '!$' lv_row_char_from + ':$' lv_row_char_to + INTO lv_repeat_range_row. + CONDENSE lv_repeat_range_row NO-GAPS. + CONCATENATE lv_repeat_range_sheetname + lv_repeat_range_row + INTO lv_repeat_range_row. + ENDIF. + +*--------------------------------------------------------------------* +* Concatenate repeat-rows and columns +*--------------------------------------------------------------------* + IF lv_repeat_range_col IS INITIAL. + lv_repeat_range = lv_repeat_range_row. + ELSEIF lv_repeat_range_row IS INITIAL. + lv_repeat_range = lv_repeat_range_col. + ELSE. + CONCATENATE lv_repeat_range_col lv_repeat_range_row + INTO lv_repeat_range SEPARATED BY ','. + ENDIF. + + + lo_range->set_range_value( lv_repeat_range ). + ENDIF. + + + + endmethod. + + + + + + + + + + + + method SET_CELL. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string, + lv_col_alpha TYPE zexcel_cell_column_alpha, + lv_value TYPE zexcel_cell_value, + lv_data_type TYPE zexcel_cell_data_type, + lv_value_type TYPE abap_typekind, + lo_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style, + lo_addit TYPE REF TO cl_abap_elemdescr, + lo_value TYPE REF TO data, + lo_value_new TYPE REF TO data. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data, + <fs_numeric> TYPE numeric, + <fs_date> TYPE d, + <fs_time> TYPE t, + <fs_value> TYPE simple. + + IF ip_value IS NOT SUPPLIED AND ip_formula IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please provide the value or formula'. + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* lv_style_guid = ip_style. + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH TABLE KEY cell_row = ip_row " Changed to access via table key , Stefan Schmöcker, 2013-08-03 + cell_column = lv_column. + IF sy-subrc = 0. + IF ip_style IS INITIAL. + " If no style is provided as method-parameter and cell is found use cell's current style + lv_style_guid = <fs_sheet_content>-cell_style. + ELSE. + " Style provided as method-parameter --> use this + lv_style_guid = ip_style. + ENDIF. + ELSE. + " No cell found --> use supplied style even if empty + lv_style_guid = ip_style. + ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + IF ip_value IS SUPPLIED. + "if data type is passed just write the value. Otherwise map abap type to excel and perform conversion + "IP_DATA_TYPE is passed by excel reader so source types are preserved +*First we get reference into local var. + CREATE DATA lo_value LIKE ip_value. + ASSIGN lo_value->* TO <fs_value>. + <fs_value> = ip_value. + IF ip_data_type IS SUPPLIED. + IF ip_abap_type IS NOT SUPPLIED. + get_value_type( EXPORTING ip_value = ip_value + IMPORTING ep_value = <fs_value> ) . + ENDIF. + lv_value = <fs_value>. + lv_data_type = ip_data_type. + ELSE. + IF ip_abap_type IS SUPPLIED. + lv_value_type = ip_abap_type. + ELSE. + get_value_type( EXPORTING ip_value = ip_value + IMPORTING ep_value = <fs_value> + ep_value_type = lv_value_type ). + ENDIF. + CASE lv_value_type. + WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. + lo_addit = cl_abap_elemdescr=>get_i( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_numeric>. + IF sy-subrc = 0. + <fs_numeric> = <fs_value>. + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). + ENDIF. + + WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. + lo_addit = cl_abap_elemdescr=>get_f( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_numeric>. + IF sy-subrc = 0. + <fs_numeric> = <fs_value>. + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). + ENDIF. + + WHEN cl_abap_typedescr=>typekind_char OR cl_abap_typedescr=>typekind_string OR cl_abap_typedescr=>typekind_num OR + cl_abap_typedescr=>typekind_hex. + lv_value = <fs_value>. + lv_data_type = 's'. + + WHEN cl_abap_typedescr=>typekind_date. + lo_addit = cl_abap_elemdescr=>get_d( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_date>. + IF sy-subrc = 0. + <fs_date> = <fs_value>. + lv_value = zcl_excel_common=>date_to_excel_string( ip_value = <fs_date> ) . + ENDIF. +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Moved to end of routine - apply date-format even if other styleinformation is passed +* IF ip_style IS NOT SUPPLIED. "get default date format in case parameter is initial +* lo_style = excel->add_new_style( ). +* lo_style->number_format->format_code = get_default_excel_date_format( ). +* lv_style_guid = lo_style->get_guid( ). +* ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + WHEN cl_abap_typedescr=>typekind_time. + lo_addit = cl_abap_elemdescr=>get_t( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_time>. + IF sy-subrc = 0. + <fs_time> = <fs_value>. + lv_value = zcl_excel_common=>time_to_excel_string( ip_value = <fs_time> ). + ENDIF. +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Moved to end of routine - apply time-format even if other styleinformation is passed +* IF ip_style IS NOT SUPPLIED. "get default time format for user in case parameter is initial +* lo_style = excel->add_new_style( ). +* lo_style->number_format->format_code = zcl_excel_style_number_format=>c_format_date_time6. +* lv_style_guid = lo_style->get_guid( ). +* ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid data type of input value'. + ENDCASE. + ENDIF. + + ENDIF. + + IF ip_hyperlink IS BOUND. + ip_hyperlink->set_cell_reference( ip_column = ip_column + ip_row = ip_row ). + me->hyperlinks->add( ip_hyperlink ). + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Read table moved up, so that current style may be evaluated +* lv_column = zcl_excel_common=>convert_column2int( ip_column ). + +* READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row +* cell_column = lv_column. +* +* IF sy-subrc EQ 0. + IF <fs_sheet_content> IS ASSIGNED. +* End of change issue #152 - don't touch exisiting style if only value is passed + <fs_sheet_content>-cell_value = lv_value. + <fs_sheet_content>-cell_formula = ip_formula. + <fs_sheet_content>-cell_style = lv_style_guid. + <fs_sheet_content>-data_type = lv_data_type. + ELSE. + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column. + ls_sheet_content-cell_value = lv_value. + ls_sheet_content-cell_formula = ip_formula. + ls_sheet_content-cell_style = lv_style_guid. + ls_sheet_content-data_type = lv_data_type. + lv_row_alpha = ip_row. +* SHIFT lv_row_alpha RIGHT DELETING TRAILING space."del #152 - replaced with condense - should be faster +* SHIFT lv_row_alpha LEFT DELETING LEADING space. "del #152 - replaced with condense - should be faster + CONDENSE lv_row_alpha NO-GAPS. "ins #152 - replaced 2 shifts - should be faster + lv_col_alpha = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column + CONCATENATE lv_col_alpha lv_row_alpha INTO ls_sheet_content-cell_coords. " issue #155 - less restrictive typing for ip_column + INSERT ls_sheet_content INTO TABLE sheet_content ASSIGNING <fs_sheet_content>. "ins #152 - Now <fs_sheet_content> always holds the data +* APPEND ls_sheet_content TO sheet_content. +* SORT sheet_content BY cell_row cell_column. + " me->update_dimension_range( ). + + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* For Date- or Timefields change the formatcode if nothing is set yet +* Enhancement option: Check if existing formatcode is a date/ or timeformat +* If not, use default + DATA: lo_format_code_datetime TYPE zexcel_number_format. + DATA: stylemapping TYPE zexcel_s_stylemapping. + CASE lv_value_type. + WHEN cl_abap_typedescr=>typekind_date. + TRY. + stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). + CATCH zcx_excel . + ENDTRY. + IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR + stylemapping-complete_style-number_format-format_code IS INITIAL. + lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_std. + ELSE. + lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. + ENDIF. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_number_format_format_code = lo_format_code_datetime ). + + WHEN cl_abap_typedescr=>typekind_time. + TRY. + stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). + CATCH zcx_excel . + ENDTRY. + IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR + stylemapping-complete_style-number_format-format_code IS INITIAL. + lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_time6. + ELSE. + lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. + ENDIF. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_number_format_format_code = lo_format_code_datetime ). + + ENDCASE. +* End of change issue #152 - don't touch exisiting style if only value is passed + +* Fix issue #162 + lv_value = ip_value. + IF lv_value CS cl_abap_char_utilities=>cr_lf. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_alignment_wraptext = abap_true ). + ENDIF. +* End of Fix issue #162 + + endmethod. + + + + + + + method SET_CELL_FORMULA. + DATA: + lv_column TYPE zexcel_cell_column, + ls_sheet_content LIKE LINE OF me->sheet_content. + + FIELD-SYMBOLS: + <sheet_content> LIKE LINE OF me->sheet_content. + +*--------------------------------------------------------------------* +* Get cell to set formula into +*--------------------------------------------------------------------* + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + READ TABLE me->sheet_content ASSIGNING <sheet_content> WITH TABLE KEY cell_row = ip_row + cell_column = lv_column. + IF sy-subrc <> 0. " Create new entry in sheet_content if necessary + CHECK ip_formula IS INITIAL. " no need to create new entry in sheet_content when no formula is passed + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column. + INSERT ls_sheet_content INTO TABLE me->sheet_content ASSIGNING <sheet_content>. + ENDIF. + +*--------------------------------------------------------------------* +* Fieldsymbol now holds the relevant cell +*--------------------------------------------------------------------* + <sheet_content>-cell_formula = ip_formula. + + + endmethod. + + + + + + + method SET_CELL_STYLE. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string, + lo_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_style_guid = ip_style. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row + cell_column = lv_column. + + IF sy-subrc EQ 0. + <fs_sheet_content>-cell_style = lv_style_guid. + ELSE. + set_cell( ip_column = ip_column ip_row = ip_row ip_value = '' ip_style = ip_style ). + ENDIF. + + endmethod. + + + + + + + method SET_COLUMN_WIDTH. + DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + DATA: width TYPE float. + + column_dimension = me->get_column_dimension( ip_column ). + +* if a fix size is supplied use this + IF ip_width_fix IS SUPPLIED. + TRY. + width = ip_width_fix. + IF width <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please supply a positive number as column-width'. + ENDIF. + column_dimension->set_width( width ). + EXIT. + CATCH cx_sy_conversion_no_number. +* Strange stuff passed --> raise error + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret supplied input as number'. + ENDTRY. + ENDIF. + +* If we get down to here, we have to use whatever is found in autosize. + column_dimension->set_auto_size( ip_width_autosize ). + + + endmethod. + + + + + method SET_DEFAULT_EXCEL_DATE_FORMAT. + + IF ip_default_excel_date_format IS INITIAL. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Default date format cannot be blank'. + ENDIF. + + default_excel_date_format = ip_default_excel_date_format. + endmethod. + + + + + + + + method SET_MERGE. + + DATA: lv_column_start TYPE zexcel_cell_column, + lv_column_end TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_column_start = zcl_excel_common=>convert_column2int( ip_column_start ). + lv_column_end = zcl_excel_common=>convert_column2int( ip_column_end ). + + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column_start. + lv_row_alpha = ip_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_column_start lv_row_alpha INTO ls_sheet_content-cell_coords. + INSERT ls_sheet_content INTO TABLE sheet_content_merge. + + ls_sheet_content-cell_column = lv_column_end. + IF ip_row_to IS SUPPLIED. + ls_sheet_content-cell_row = ip_row_to. + lv_row_alpha = ip_row_to. + ELSE. + lv_row_alpha = ip_row. + ls_sheet_content-cell_row = ip_row. + ENDIF. + + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_column_end lv_row_alpha INTO ls_sheet_content-cell_coords. + INSERT ls_sheet_content INTO TABLE sheet_content_merge. + + endmethod. + + + + method SET_PRINT_GRIDLINES. + me->print_gridlines = i_print_gridlines. + endmethod. + + + + + + method SET_ROW_HEIGHT. + DATA: row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + DATA: height TYPE float. + + row_dimension = me->get_row_dimension( ip_row ). + +* if a fix size is supplied use this + TRY. + height = ip_height_fix. + IF height <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please supply a positive number as row-height'. + ENDIF. + row_dimension->set_row_height( height ). + EXIT. + CATCH cx_sy_conversion_no_number. +* Strange stuff passed --> raise error + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret supplied input as number'. + ENDTRY. + + + + endmethod. + + + + method SET_SHOW_GRIDLINES. + me->show_gridlines = i_show_gridlines. + endmethod. + + + + method SET_SHOW_ROWCOLHEADERS. + me->show_rowcolheaders = i_show_rowcolheaders. + endmethod. + + + + method SET_TABCOLOR. + me->tabcolor = iv_tabcolor. + endmethod. + + + + + + + + + + + + method SET_TABLE. + + DATA: lo_tabdescr TYPE REF TO cl_abap_structdescr, + lr_data TYPE REF TO data, + ls_newline TYPE REF TO data, + ls_header TYPE x030l, + lt_dfies TYPE ddfields, + lv_row_header TYPE zexcel_cell_row VALUE '2', + lv_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + lv_row_int TYPE zexcel_cell_row, + lv_column_int TYPE zexcel_cell_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lv_cell_value TYPE zexcel_cell_value. + + + FIELD-SYMBOLS: <fs_table_line> TYPE ANY, + <fs_fldval> TYPE ANY, + <fs_dfies> TYPE dfies, + <fs_cell_value> TYPE zexcel_cell_value. + + lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). + lv_row_int = ip_top_left_row. + + CREATE DATA lr_data LIKE LINE OF ip_table. + + lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + ls_header = lo_tabdescr->get_ddic_header( ). + + lt_dfies = lo_tabdescr->get_ddic_field_list( ). + +* It is better to loop column by column + LOOP AT lt_dfies ASSIGNING <fs_dfies>. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + + IF ip_no_header = abap_false. + " First of all write column header + lv_cell_value = <fs_dfies>-scrtext_m. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_cell_value + ip_style = ip_hdr_style ). + IF ip_transpose = abap_true. + ADD 1 TO lv_column_int. + ELSE. + ADD 1 TO lv_row_int. + ENDIF. + ENDIF. + + LOOP AT ip_table ASSIGNING <fs_table_line>. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + ASSIGN COMPONENT <fs_dfies>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. + MOVE <fs_fldval> TO lv_cell_value. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> "lv_cell_value + ip_style = ip_body_style ). + IF ip_transpose = abap_true. + ADD 1 TO lv_column_int. + ELSE. + ADD 1 TO lv_row_int. + ENDIF. + ENDLOOP. + IF ip_transpose = abap_true. + lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). + ADD 1 TO lv_row_int. + ELSE. + lv_row_int = ip_top_left_row. + ADD 1 TO lv_column_int. + ENDIF. + ENDLOOP. + + endmethod. + + + + + method SET_TITLE. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 The current coding for replacing a named ranges name +* after renaming a sheet should be checked if it is +* really working if sheetname should be escaped +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (wip ) 2012-12-08 +* - ... +* changes: aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue#243 - ' is not allowed as first character in sheet title +* - Stefan Schmöcker, 2012-12-02 +* changes: added additional check for ' as first character +*--------------------------------------------------------------------* + DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + errormessage TYPE string, + lv_rangesheetname_old TYPE string, + lv_rangesheetname_new TYPE string, + lo_ranges_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range, + lv_range_value TYPE zexcel_range_value, + lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + + +*--------------------------------------------------------------------* +* Check whether title consists only of allowed characters +* Illegal characters are: / \ [ ] * ? : --> http://msdn.microsoft.com/en-us/library/ff837411.aspx +* Illegal characters not in documentation: ' as first character +*--------------------------------------------------------------------* + IF ip_title CA '/\[]*?:'. + lv_errormessage = 'Found illegal character in sheetname. List of forbidden characters: /\[]*?:'(402). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF ip_title IS NOT INITIAL AND ip_title(1) = `'`. + lv_errormessage = 'Sheetname may not start with &'(403). " & used instead of ' to allow fallbacklanguage + REPLACE '&' IN lv_errormessage WITH `'`. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + +*--------------------------------------------------------------------* +* Check whether title is unique in workbook +*--------------------------------------------------------------------* + lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_worksheets_iterator->has_next( ) = 'X'. + + lo_worksheet ?= lo_worksheets_iterator->get_next( ). + CHECK me->guid <> lo_worksheet->get_guid( ). " Don't check against itself + IF ip_title = lo_worksheet->get_title( ). " Not unique --> raise exception + errormessage = 'Duplicate sheetname &'. + REPLACE '&' IN errormessage WITH ip_title. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = errormessage. + ENDIF. + + ENDWHILE. + +*--------------------------------------------------------------------* +* Remember old sheetname and rename sheet to desired name +*--------------------------------------------------------------------* + CONCATENATE me->title '!' INTO lv_rangesheetname_old. + me->title = ip_title. + +*--------------------------------------------------------------------* +* After changing this worksheet's title we have to adjust +* all ranges that are referring to this worksheet. +*--------------------------------------------------------------------* +* 2do§1 - Check if the following quickfix is solid +* I fear it isn't - but this implementation is better then +* nothing at all since it handles a supposed majority of cases +*--------------------------------------------------------------------* + CONCATENATE me->title '!' INTO lv_rangesheetname_new. + + lo_ranges_iterator = me->excel->get_ranges_iterator( ). + WHILE lo_ranges_iterator->has_next( ) = 'X'. + + lo_range ?= lo_ranges_iterator->get_next( ). + lv_range_value = lo_range->get_value( ). + REPLACE ALL OCCURRENCES OF lv_rangesheetname_old IN lv_range_value WITH lv_rangesheetname_new. + IF sy-subrc = 0. + lo_range->set_range_value( lv_range_value ). + ENDIF. + + ENDWHILE. + + + endmethod. + + + + method UPDATE_DIMENSION_RANGE. + + DATA: ls_sheet_content TYPE zexcel_s_cell_data, + lt_sheet_content TYPE zexcel_t_cell_data_unsorted, + lv_row_alpha TYPE string, + lv_column_alpha TYPE zexcel_cell_column_alpha. + + CHECK sheet_content IS NOT INITIAL. + +* update dimension range + lt_sheet_content = sheet_content. + "upper left corner + SORT lt_sheet_content BY cell_row. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + upper_cell-cell_row = ls_sheet_content-cell_row. + SORT lt_sheet_content BY cell_column. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + upper_cell-cell_column = ls_sheet_content-cell_column. + + lv_row_alpha = upper_cell-cell_row. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( upper_cell-cell_column ). + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_column_alpha lv_row_alpha INTO upper_cell-cell_coords. + + "bottom right corner + SORT lt_sheet_content BY cell_row DESCENDING. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + lower_cell-cell_row = ls_sheet_content-cell_row. + SORT lt_sheet_content BY cell_column DESCENDING. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + lower_cell-cell_column = ls_sheet_content-cell_column. + + lv_row_alpha = lower_cell-cell_row. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lower_cell-cell_column ). + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_column_alpha lv_row_alpha INTO lower_cell-cell_coords. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method ADD. + + worksheets->add( ip_worksheet ). + + endmethod. + + + method CLEAR. + + worksheets->clear( ). + + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT worksheets. + + endmethod. + + + + + method GET. + + DATA lv_index TYPE i. + lv_index = ip_index. + eo_worksheet ?= worksheets->if_object_collection~get( lv_index ). + + endmethod. + + + + method GET_ITERATOR. + + eo_iterator ?= worksheets->if_object_collection~get_iterator( ). + + endmethod. + + + + method IS_EMPTY. + + is_empty = worksheets->if_object_collection~is_empty( ). + + endmethod. + + + + method REMOVE. + + worksheets->remove( ip_worksheet ). + + endmethod. + + + + method SIZE. + + ep_size = worksheets->if_object_collection~size( ). + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + method CONSTRUCTOR. + me->column_index = zcl_excel_common=>convert_column2int( ip_index ). + me->width = -1. + me->auto_size = abap_false. + me->visible = abap_true. + me->outline_level = 0. + me->collapsed = abap_false. + me->excel = ip_excel. "ins issue #157 - Allow Style for columns + me->worksheet = ip_worksheet. "ins issue #157 - Allow Style for columns + + " set default index to cellXf + me->xf_index = 0. + + endmethod. + + + + method GET_AUTO_SIZE. + r_auto_size = me->auto_size. + endmethod. + + + + method GET_COLLAPSED. + r_Collapsed = me->Collapsed. + endmethod. + + + + method GET_COLUMN_INDEX. + r_column_index = me->column_index. + endmethod. + + + + + method GET_COLUMN_STYLE_GUID. + IF me->style_guid IS NOT INITIAL. + ep_style_guid = me->style_guid. + ELSE. + ep_style_guid = me->worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. + endmethod. + + + + method GET_OUTLINE_LEVEL. + r_outline_level = me->outline_level. + endmethod. + + + + method GET_VISIBLE. + r_Visible = me->Visible. + endmethod. + + + + method GET_WIDTH. + r_WIDTH = me->WIDTH. + endmethod. + + + + method GET_XF_INDEX. + r_xf_index = me->xf_index. + endmethod. + + + + + method SET_AUTO_SIZE. + me->auto_size = ip_auto_size. + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLLAPSED. + me->Collapsed = ip_Collapsed. + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLUMN_INDEX. + me->column_index = zcl_excel_common=>convert_column2int( ip_index ). + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLUMN_STYLE_BY_GUID. + DATA: stylemapping TYPE zexcel_s_stylemapping. + + IF me->excel IS NOT BOUND. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Internal error - reference to ZCL_EXCEL not bound'. + ENDIF. + TRY. + stylemapping = me->excel->get_style_to_guid( ip_style_guid ). + me->style_guid = stylemapping-guid. + + CATCH zcx_excel . + EXIT. " leave as is in case of error + ENDTRY. + + endmethod. + + + + method SET_OUTLINE_LEVEL. + me->outline_level = ip_outline_level. + endmethod. + + + + + method SET_VISIBLE. + me->Visible = ip_Visible. + r_worksheet_columndime = me. + endmethod. + + + + + + method SET_WIDTH. + TRY. + me->width = ip_width. + r_worksheet_columndime = me. + CATCH cx_sy_conversion_no_number. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret width as number'. + ENDTRY. + endmethod. + + + + + method SET_XF_INDEX. + me->XF_INDEX = ip_XF_INDEX. + r_worksheet_columndime = me. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + method CONSTRUCTOR. + " Initialise values + me->row_index = ip_index. + me->row_height = -1. + me->visible = abap_true. + me->outline_level = 0. + me->collapsed = abap_false. + + " set row dimension as unformatted by default + me->xf_index = 0. + endmethod. + + + + method GET_COLLAPSED. + r_collapsed = me->collapsed. + endmethod. + + + + method GET_OUTLINE_LEVEL. + r_outline_level = me->outline_level. + endmethod. + + + + method GET_ROW_HEIGHT. + r_row_height = me->row_height. + endmethod. + + + + method GET_ROW_INDEX. + r_row_index = me->row_index. + endmethod. + + + + method GET_VISIBLE. + r_visible = me->visible. + endmethod. + + + + method GET_XF_INDEX. + r_xf_index = me->xf_index. + endmethod. + + + + method SET_COLLAPSED. + me->collapsed = ip_collapsed. + endmethod. + + + + + method SET_OUTLINE_LEVEL. + IF ip_outline_level < 0 + OR ip_outline_level > 7. + + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Outline level must range between 0 and 7.'. + + ENDIF. + me->outline_level = ip_outline_level. + endmethod. + + + + + method SET_ROW_HEIGHT. + TRY. + me->row_height = ip_row_height. + CATCH cx_sy_conversion_no_number. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret ip_row_height as number'. + ENDTRY. + endmethod. + + + + method SET_ROW_INDEX. + me->row_index = ip_index. + endmethod. + + + + method SET_VISIBLE. + me->visible = ip_visible. + endmethod. + + + + method SET_XF_INDEX. + me->XF_INDEX = ip_XF_INDEX. + endmethod. + + - + *"* local class implementation for public class *"* use this source file for the implementation part of *"* local helper classes @@ -36,7 +12611,7 @@ me->excel = io_excel. ep_file = me->create( ). -endmethod. + endmethod. @@ -233,7 +12808,7 @@ endmethod. * STEP 12: Create the final zip ep_excel = lo_zip->save( ). -endmethod. + endmethod. @@ -508,7 +13083,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -731,7 +13306,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -856,7 +13431,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -955,12 +13530,12 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. - METHOD create_xl_charts. + method CREATE_XL_CHARTS. ** Constant node name @@ -1860,7 +14435,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -ENDMETHOD. + endmethod. @@ -1940,7 +14515,7 @@ ENDMETHOD. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -2039,7 +14614,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -2353,7 +14928,7 @@ endmethod. parent = io_document ). ep_anchor->append_child( new_child = lo_element_clientdata ). -endmethod. + endmethod. @@ -2501,7 +15076,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -2618,17 +15193,17 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. - METHOD create_xl_sheet. + method CREATE_XL_SHEET. *--------------------------------------------------------------------* * issue #237 - Error writing column-style -* - Stefan Schmöcker, 2012-11-01 +* - Stefan Schmöcker, 2012-11-01 *--------------------------------------------------------------------* TYPES: BEGIN OF cfvo, @@ -4276,7 +16851,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -ENDMETHOD. + endmethod. @@ -4446,7 +17021,7 @@ ENDMETHOD. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -4454,919 +17029,957 @@ endmethod. ** Constant node name - CONSTANTS: lc_xml_node_stylesheet TYPE string VALUE 'styleSheet', - " font - lc_xml_node_fonts TYPE string VALUE 'fonts', - lc_xml_node_font TYPE string VALUE 'font', - lc_xml_node_b TYPE string VALUE 'b', "bold - lc_xml_node_i TYPE string VALUE 'i', "italic - lc_xml_node_u TYPE string VALUE 'u', "underline - lc_xml_node_strike TYPE string VALUE 'strike', "strikethrough - lc_xml_node_sz TYPE string VALUE 'sz', - lc_xml_node_color TYPE string VALUE 'color', - lc_xml_node_name TYPE string VALUE 'name', - lc_xml_node_family TYPE string VALUE 'family', - lc_xml_node_scheme TYPE string VALUE 'scheme', - " fill - lc_xml_node_fills TYPE string VALUE 'fills', - lc_xml_node_fill TYPE string VALUE 'fill', - lc_xml_node_patternfill TYPE string VALUE 'patternFill', - lc_xml_node_fgcolor TYPE string VALUE 'fgColor', - lc_xml_node_bgcolor TYPE string VALUE 'bgColor', - lc_xml_node_gradientfill TYPE string VALUE 'gradientFill', - lc_xml_node_stop TYPE string VALUE 'stop', - " borders - lc_xml_node_borders TYPE string VALUE 'borders', - lc_xml_node_border TYPE string VALUE 'border', - lc_xml_node_left TYPE string VALUE 'left', - lc_xml_node_right TYPE string VALUE 'right', - lc_xml_node_top TYPE string VALUE 'top', - lc_xml_node_bottom TYPE string VALUE 'bottom', - lc_xml_node_diagonal TYPE string VALUE 'diagonal', - " numfmt - lc_xml_node_numfmts TYPE string VALUE 'numFmts', - lc_xml_node_numfmt TYPE string VALUE 'numFmt', - " Styles - lc_xml_node_cellstylexfs TYPE string VALUE 'cellStyleXfs', - lc_xml_node_xf TYPE string VALUE 'xf', - lc_xml_node_cellxfs TYPE string VALUE 'cellXfs', - lc_xml_node_cellstyles TYPE string VALUE 'cellStyles', - lc_xml_node_cellstyle TYPE string VALUE 'cellStyle', - lc_xml_node_dxfs TYPE string VALUE 'dxfs', - lc_xml_node_dxf TYPE string VALUE 'dxf', - lc_xml_node_tablestyles TYPE string VALUE 'tableStyles', - " Colors - lc_xml_node_colors TYPE string VALUE 'colors', - lc_xml_node_indexedcolors TYPE string VALUE 'indexedColors', - lc_xml_node_rgbcolor TYPE string VALUE 'rgbColor', - lc_xml_node_mrucolors TYPE string VALUE 'mruColors', - " Alignment - lc_xml_node_alignment TYPE string VALUE 'alignment', - " Protection - lc_xml_node_protection TYPE string VALUE 'protection', - " Node attributes - lc_xml_attr_count TYPE string VALUE 'count', - lc_xml_attr_val TYPE string VALUE 'val', - lc_xml_attr_theme TYPE string VALUE 'theme', - lc_xml_attr_rgb TYPE string VALUE 'rgb', - lc_xml_attr_indexed TYPE string VALUE 'indexed', - lc_xml_attr_tint TYPE string VALUE 'tint', - lc_xml_attr_style TYPE string VALUE 'style', - lc_xml_attr_position TYPE string VALUE 'position', - lc_xml_attr_degree TYPE string VALUE 'degree', - lc_xml_attr_patterntype TYPE string VALUE 'patternType', - lc_xml_attr_numfmtid TYPE string VALUE 'numFmtId', - lc_xml_attr_fontid TYPE string VALUE 'fontId', - lc_xml_attr_fillid TYPE string VALUE 'fillId', - lc_xml_attr_borderid TYPE string VALUE 'borderId', - lc_xml_attr_xfid TYPE string VALUE 'xfId', - lc_xml_attr_applynumberformat TYPE string VALUE 'applyNumberFormat', - lc_xml_attr_applyprotection TYPE string VALUE 'applyProtection', - lc_xml_attr_applyfont TYPE string VALUE 'applyFont', - lc_xml_attr_applyfill TYPE string VALUE 'applyFill', - lc_xml_attr_applyborder TYPE string VALUE 'applyBorder', - lc_xml_attr_name TYPE string VALUE 'name', - lc_xml_attr_builtinid TYPE string VALUE 'builtinId', - lc_xml_attr_defaulttablestyle TYPE string VALUE 'defaultTableStyle', - lc_xml_attr_defaultpivotstyle TYPE string VALUE 'defaultPivotStyle', - lc_xml_attr_applyalignment TYPE string VALUE 'applyAlignment', - lc_xml_attr_horizontal TYPE string VALUE 'horizontal', - lc_xml_attr_formatcode TYPE string VALUE 'formatCode', - lc_xml_attr_vertical TYPE string VALUE 'vertical', - lc_xml_attr_wraptext TYPE string VALUE 'wrapText', - lc_xml_attr_textrotation TYPE string VALUE 'textRotation', - lc_xml_attr_shrinktofit TYPE string VALUE 'shrinkToFit', - lc_xml_attr_indent TYPE string VALUE 'indent', - lc_xml_attr_locked TYPE string VALUE 'locked', - lc_xml_attr_hidden TYPE string VALUE 'hidden', - lc_xml_attr_diagonalup TYPE string VALUE 'diagonalUp', - lc_xml_attr_diagonaldown TYPE string VALUE 'diagonalDown', - " Node namespace - lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'. + CONSTANTS: lc_xml_node_stylesheet TYPE string VALUE 'styleSheet', + " font + lc_xml_node_fonts TYPE string VALUE 'fonts', + lc_xml_node_font TYPE string VALUE 'font', + lc_xml_node_b TYPE string VALUE 'b', "bold + lc_xml_node_i TYPE string VALUE 'i', "italic + lc_xml_node_u TYPE string VALUE 'u', "underline + lc_xml_node_strike TYPE string VALUE 'strike', "strikethrough + lc_xml_node_sz TYPE string VALUE 'sz', + lc_xml_node_color TYPE string VALUE 'color', + lc_xml_node_name TYPE string VALUE 'name', + lc_xml_node_family TYPE string VALUE 'family', + lc_xml_node_scheme TYPE string VALUE 'scheme', + " fill + lc_xml_node_fills TYPE string VALUE 'fills', + lc_xml_node_fill TYPE string VALUE 'fill', + lc_xml_node_patternfill TYPE string VALUE 'patternFill', + lc_xml_node_fgcolor TYPE string VALUE 'fgColor', + lc_xml_node_bgcolor TYPE string VALUE 'bgColor', + lc_xml_node_gradientfill TYPE string VALUE 'gradientFill', + lc_xml_node_stop TYPE string VALUE 'stop', + " borders + lc_xml_node_borders TYPE string VALUE 'borders', + lc_xml_node_border TYPE string VALUE 'border', + lc_xml_node_left TYPE string VALUE 'left', + lc_xml_node_right TYPE string VALUE 'right', + lc_xml_node_top TYPE string VALUE 'top', + lc_xml_node_bottom TYPE string VALUE 'bottom', + lc_xml_node_diagonal TYPE string VALUE 'diagonal', + " numfmt + lc_xml_node_numfmts TYPE string VALUE 'numFmts', + lc_xml_node_numfmt TYPE string VALUE 'numFmt', + " Styles + lc_xml_node_cellstylexfs TYPE string VALUE 'cellStyleXfs', + lc_xml_node_xf TYPE string VALUE 'xf', + lc_xml_node_cellxfs TYPE string VALUE 'cellXfs', + lc_xml_node_cellstyles TYPE string VALUE 'cellStyles', + lc_xml_node_cellstyle TYPE string VALUE 'cellStyle', + lc_xml_node_dxfs TYPE string VALUE 'dxfs', + lc_xml_node_dxf TYPE string VALUE 'dxf', + lc_xml_node_tablestyles TYPE string VALUE 'tableStyles', + " Colors + lc_xml_node_colors TYPE string VALUE 'colors', + lc_xml_node_indexedcolors TYPE string VALUE 'indexedColors', + lc_xml_node_rgbcolor TYPE string VALUE 'rgbColor', + lc_xml_node_mrucolors TYPE string VALUE 'mruColors', + " Alignment + lc_xml_node_alignment TYPE string VALUE 'alignment', + " Protection + lc_xml_node_protection TYPE string VALUE 'protection', + " Node attributes + lc_xml_attr_count TYPE string VALUE 'count', + lc_xml_attr_val TYPE string VALUE 'val', + lc_xml_attr_theme TYPE string VALUE 'theme', + lc_xml_attr_rgb TYPE string VALUE 'rgb', + lc_xml_attr_indexed TYPE string VALUE 'indexed', + lc_xml_attr_tint TYPE string VALUE 'tint', + lc_xml_attr_style TYPE string VALUE 'style', + lc_xml_attr_position TYPE string VALUE 'position', + lc_xml_attr_degree TYPE string VALUE 'degree', + lc_xml_attr_patterntype TYPE string VALUE 'patternType', + lc_xml_attr_numfmtid TYPE string VALUE 'numFmtId', + lc_xml_attr_fontid TYPE string VALUE 'fontId', + lc_xml_attr_fillid TYPE string VALUE 'fillId', + lc_xml_attr_borderid TYPE string VALUE 'borderId', + lc_xml_attr_xfid TYPE string VALUE 'xfId', + lc_xml_attr_applynumberformat TYPE string VALUE 'applyNumberFormat', + lc_xml_attr_applyprotection TYPE string VALUE 'applyProtection', + lc_xml_attr_applyfont TYPE string VALUE 'applyFont', + lc_xml_attr_applyfill TYPE string VALUE 'applyFill', + lc_xml_attr_applyborder TYPE string VALUE 'applyBorder', + lc_xml_attr_name TYPE string VALUE 'name', + lc_xml_attr_builtinid TYPE string VALUE 'builtinId', + lc_xml_attr_defaulttablestyle TYPE string VALUE 'defaultTableStyle', + lc_xml_attr_defaultpivotstyle TYPE string VALUE 'defaultPivotStyle', + lc_xml_attr_applyalignment TYPE string VALUE 'applyAlignment', + lc_xml_attr_horizontal TYPE string VALUE 'horizontal', + lc_xml_attr_formatcode TYPE string VALUE 'formatCode', + lc_xml_attr_vertical TYPE string VALUE 'vertical', + lc_xml_attr_wraptext TYPE string VALUE 'wrapText', + lc_xml_attr_textrotation TYPE string VALUE 'textRotation', + lc_xml_attr_shrinktofit TYPE string VALUE 'shrinkToFit', + lc_xml_attr_indent TYPE string VALUE 'indent', + lc_xml_attr_locked TYPE string VALUE 'locked', + lc_xml_attr_hidden TYPE string VALUE 'hidden', + lc_xml_attr_diagonalup TYPE string VALUE 'diagonalUp', + lc_xml_attr_diagonaldown TYPE string VALUE 'diagonalDown', + " Node namespace + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'. - DATA: lo_ixml TYPE REF TO if_ixml, - lo_document TYPE REF TO if_ixml_document, - lo_element_root TYPE REF TO if_ixml_element, - lo_element_fonts TYPE REF TO if_ixml_element, - lo_element_font TYPE REF TO if_ixml_element, - lo_element_fills TYPE REF TO if_ixml_element, - lo_element_fill TYPE REF TO if_ixml_element, - lo_element_borders TYPE REF TO if_ixml_element, - lo_element_border TYPE REF TO if_ixml_element, - lo_element_numfmts TYPE REF TO if_ixml_element, - lo_element_numfmt TYPE REF TO if_ixml_element, - lo_element_cellxfs TYPE REF TO if_ixml_element, - lo_element TYPE REF TO if_ixml_element, - lo_sub_element TYPE REF TO if_ixml_element, - lo_sub_element_2 TYPE REF TO if_ixml_element, - lo_encoding TYPE REF TO if_ixml_encoding, - lo_streamfactory TYPE REF TO if_ixml_stream_factory, - lo_ostream TYPE REF TO if_ixml_ostream, - lo_renderer TYPE REF TO if_ixml_renderer, - lo_iterator TYPE REF TO cl_object_collection_iterator, - lo_iterator2 TYPE REF TO cl_object_collection_iterator, - lo_worksheet TYPE REF TO zcl_excel_worksheet, - lo_style_conditional TYPE REF TO zcl_excel_style_conditional, - lo_style TYPE REF TO zcl_excel_style. + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element_fonts TYPE REF TO if_ixml_element, + lo_element_font TYPE REF TO if_ixml_element, + lo_element_fills TYPE REF TO if_ixml_element, + lo_element_fill TYPE REF TO if_ixml_element, + lo_element_borders TYPE REF TO if_ixml_element, + lo_element_border TYPE REF TO if_ixml_element, + lo_element_numfmts TYPE REF TO if_ixml_element, + lo_element_numfmt TYPE REF TO if_ixml_element, + lo_element_cellxfs TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_sub_element TYPE REF TO if_ixml_element, + lo_sub_element_2 TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_iterator2 TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_style TYPE REF TO zcl_excel_style. - DATA: lt_fonts TYPE zexcel_t_style_font, - ls_font TYPE zexcel_s_style_font, - lt_fills TYPE zexcel_t_style_fill, - ls_fill TYPE zexcel_s_style_fill, - lt_borders TYPE zexcel_t_style_border, - ls_border TYPE zexcel_s_style_border, - lt_numfmts TYPE zexcel_t_style_numfmt, - ls_numfmt TYPE zexcel_s_style_numfmt, - lt_protections TYPE zexcel_t_style_protection, - ls_protection TYPE zexcel_s_style_protection, - lt_alignments TYPE zexcel_t_style_alignment, - ls_alignment TYPE zexcel_s_style_alignment, - lt_cellxfs TYPE zexcel_t_cellxfs, - ls_cellxfs TYPE zexcel_s_cellxfs, - ls_styles_mapping TYPE zexcel_s_styles_mapping, - ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, - ls_cellis TYPE zexcel_conditional_cellis, - ls_expression TYPE zexcel_conditional_expression, - lt_colors TYPE zexcel_t_style_color_argb, - ls_color LIKE LINE OF lt_colors. + DATA: lt_fonts TYPE zexcel_t_style_font, + ls_font TYPE zexcel_s_style_font, + lt_fills TYPE zexcel_t_style_fill, + ls_fill TYPE zexcel_s_style_fill, + lt_borders TYPE zexcel_t_style_border, + ls_border TYPE zexcel_s_style_border, + lt_numfmts TYPE zexcel_t_style_numfmt, + ls_numfmt TYPE zexcel_s_style_numfmt, + lt_protections TYPE zexcel_t_style_protection, + ls_protection TYPE zexcel_s_style_protection, + lt_alignments TYPE zexcel_t_style_alignment, + ls_alignment TYPE zexcel_s_style_alignment, + lt_cellxfs TYPE zexcel_t_cellxfs, + ls_cellxfs TYPE zexcel_s_cellxfs, + ls_styles_mapping TYPE zexcel_s_styles_mapping, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + ls_cellis TYPE zexcel_conditional_cellis, + ls_expression TYPE zexcel_conditional_expression, + lt_colors TYPE zexcel_t_style_color_argb, + ls_color LIKE LINE OF lt_colors. - DATA: lv_value TYPE string, - lv_dfx_count TYPE i, - lv_fonts_count TYPE i, - lv_fills_count TYPE i, - lv_borders_count TYPE i, - lv_cellxfs_count TYPE i, - lv_align_flag TYPE c. + DATA: lv_value TYPE string, + lv_dfx_count TYPE i, + lv_fonts_count TYPE i, + lv_fills_count TYPE i, + lv_borders_count TYPE i, + lv_cellxfs_count TYPE i, + lv_align_flag TYPE c. ********************************************************************** * STEP 1: Create [Content_Types].xml into the root of the ZIP - lo_ixml = cl_ixml=>create( ). + lo_ixml = cl_ixml=>create( ). ********************************************************************** * STEP 2: Set document attributes - lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian - character_set = 'utf-8' ). - lo_document = lo_ixml->create_document( ). - lo_document->set_encoding( lo_encoding ). - lo_document->set_standalone( abap_true ). + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). *********************************************************************** * STEP 3: Create main node relationships - lo_element_root = lo_document->create_simple_element( name = lc_xml_node_stylesheet - parent = lo_document ). - lo_element_root->set_attribute_ns( name = 'xmlns' - value = lc_xml_node_ns ). + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_stylesheet + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). ********************************************************************** * STEP 4: Create subnodes - lo_element_fonts = lo_document->create_simple_element( name = lc_xml_node_fonts - parent = lo_document ). - - lo_element_fills = lo_document->create_simple_element( name = lc_xml_node_fills - parent = lo_document ). - - lo_element_borders = lo_document->create_simple_element( name = lc_xml_node_borders + lo_element_fonts = lo_document->create_simple_element( name = lc_xml_node_fonts parent = lo_document ). - lo_element_cellxfs = lo_document->create_simple_element( name = lc_xml_node_cellxfs + lo_element_fills = lo_document->create_simple_element( name = lc_xml_node_fills parent = lo_document ). - lo_element_numfmts = lo_document->create_simple_element( name = lc_xml_node_numfmts - parent = lo_document ). + lo_element_borders = lo_document->create_simple_element( name = lc_xml_node_borders + parent = lo_document ). + + lo_element_cellxfs = lo_document->create_simple_element( name = lc_xml_node_cellxfs + parent = lo_document ). + + lo_element_numfmts = lo_document->create_simple_element( name = lc_xml_node_numfmts + parent = lo_document ). * Compress styles - lo_iterator = excel->get_styles_iterator( ). - WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_style ?= lo_iterator->if_object_collection_iterator~get_next( ). - ls_font = lo_style->font->get_structure( ). - ls_fill = lo_style->fill->get_structure( ). - ls_border = lo_style->borders->get_structure( ). - ls_alignment = lo_style->alignment->get_structure( ). - ls_protection = lo_style->protection->get_structure( ). - ls_numfmt = lo_style->number_format->get_structure( ). + lo_iterator = excel->get_styles_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style ?= lo_iterator->if_object_collection_iterator~get_next( ). + ls_font = lo_style->font->get_structure( ). + ls_fill = lo_style->fill->get_structure( ). + ls_border = lo_style->borders->get_structure( ). + ls_alignment = lo_style->alignment->get_structure( ). + ls_protection = lo_style->protection->get_structure( ). + ls_numfmt = lo_style->number_format->get_structure( ). - CLEAR ls_cellxfs. + CLEAR ls_cellxfs. * Compress fonts - READ TABLE lt_fonts FROM ls_font TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_cellxfs-fontid = sy-tabix. - ELSE. - APPEND ls_font TO lt_fonts. - DESCRIBE TABLE lt_fonts LINES ls_cellxfs-fontid. - ENDIF. - SUBTRACT 1 FROM ls_cellxfs-fontid. + READ TABLE lt_fonts FROM ls_font TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-fontid = sy-tabix. + ELSE. + APPEND ls_font TO lt_fonts. + DESCRIBE TABLE lt_fonts LINES ls_cellxfs-fontid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-fontid. * Compress alignment - READ TABLE lt_alignments FROM ls_alignment TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_cellxfs-alignmentid = sy-tabix. - ELSE. - APPEND ls_alignment TO lt_alignments. - DESCRIBE TABLE lt_alignments LINES ls_cellxfs-alignmentid. - ENDIF. - SUBTRACT 1 FROM ls_cellxfs-alignmentid. + READ TABLE lt_alignments FROM ls_alignment TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-alignmentid = sy-tabix. + ELSE. + APPEND ls_alignment TO lt_alignments. + DESCRIBE TABLE lt_alignments LINES ls_cellxfs-alignmentid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-alignmentid. * Compress fills - READ TABLE lt_fills FROM ls_fill TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_cellxfs-fillid = sy-tabix. - ELSE. - APPEND ls_fill TO lt_fills. - DESCRIBE TABLE lt_fills LINES ls_cellxfs-fillid. - ENDIF. - SUBTRACT 1 FROM ls_cellxfs-fillid. + READ TABLE lt_fills FROM ls_fill TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-fillid = sy-tabix. + ELSE. + APPEND ls_fill TO lt_fills. + DESCRIBE TABLE lt_fills LINES ls_cellxfs-fillid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-fillid. * Compress borders - READ TABLE lt_borders FROM ls_border TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_cellxfs-borderid = sy-tabix. - ELSE. - APPEND ls_border TO lt_borders. - DESCRIBE TABLE lt_borders LINES ls_cellxfs-borderid. - ENDIF. - SUBTRACT 1 FROM ls_cellxfs-borderid. + READ TABLE lt_borders FROM ls_border TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-borderid = sy-tabix. + ELSE. + APPEND ls_border TO lt_borders. + DESCRIBE TABLE lt_borders LINES ls_cellxfs-borderid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-borderid. * Compress protection - IF ls_protection-locked EQ c_on AND ls_protection-hidden EQ c_off. - ls_cellxfs-applyprotection = 0. - ELSE. - READ TABLE lt_protections FROM ls_protection TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_cellxfs-protectionid = sy-tabix. + IF ls_protection-locked EQ c_on AND ls_protection-hidden EQ c_off. + ls_cellxfs-applyprotection = 0. ELSE. - APPEND ls_protection TO lt_protections. - DESCRIBE TABLE lt_protections LINES ls_cellxfs-protectionid. + READ TABLE lt_protections FROM ls_protection TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-protectionid = sy-tabix. + ELSE. + APPEND ls_protection TO lt_protections. + DESCRIBE TABLE lt_protections LINES ls_cellxfs-protectionid. + ENDIF. + ls_cellxfs-applyprotection = 1. ENDIF. - ls_cellxfs-applyprotection = 1. - ENDIF. - SUBTRACT 1 FROM ls_cellxfs-protectionid. + SUBTRACT 1 FROM ls_cellxfs-protectionid. * Compress number formats - "----------- - IF ls_numfmt-numfmt NE zcl_excel_style_number_format=>c_format_date_std." and ls_numfmt-NUMFMT ne 'STD_NDEC'. " ALE Changes on going - "--- - IF ls_numfmt IS NOT INITIAL. + "----------- + IF ls_numfmt-numfmt NE zcl_excel_style_number_format=>c_format_date_std." and ls_numfmt-NUMFMT ne 'STD_NDEC'. " ALE Changes on going + "--- + IF ls_numfmt IS NOT INITIAL. - READ TABLE lt_numfmts FROM ls_numfmt TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_cellxfs-numfmtid = sy-tabix. + READ TABLE lt_numfmts FROM ls_numfmt TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-numfmtid = sy-tabix. + ELSE. + APPEND ls_numfmt TO lt_numfmts. + DESCRIBE TABLE lt_numfmts LINES ls_cellxfs-numfmtid. + ENDIF. + ADD zcl_excel_common=>c_excel_numfmt_offset TO ls_cellxfs-numfmtid. " Add OXML offset for custom styles + ls_cellxfs-applynumberformat = 1. ELSE. - APPEND ls_numfmt TO lt_numfmts. - DESCRIBE TABLE lt_numfmts LINES ls_cellxfs-numfmtid. + ls_cellxfs-applynumberformat = 0. ENDIF. - ADD zcl_excel_common=>c_excel_numfmt_offset TO ls_cellxfs-numfmtid. " Add OXML offset for custom styles - ls_cellxfs-applynumberformat = 1. + "----------- " ALE changes on going ELSE. - ls_cellxfs-applynumberformat = 0. - ENDIF. - "----------- " ALE changes on going - ELSE. - ls_cellxfs-applynumberformat = 1. - IF ls_numfmt-numfmt EQ zcl_excel_style_number_format=>c_format_date_std. - ls_cellxfs-numfmtid = 14. + ls_cellxfs-applynumberformat = 1. + IF ls_numfmt-numfmt EQ zcl_excel_style_number_format=>c_format_date_std. + ls_cellxfs-numfmtid = 14. * elseif ls_numfmt-NUMFMT eq 'STD_NDEC'. * ls_cellxfs-numfmtid = 2. + ENDIF. ENDIF. - ENDIF. - "--- + "--- - IF ls_cellxfs-fontid NE 0. - ls_cellxfs-applyfont = 1. - ELSE. - ls_cellxfs-applyfont = 0. - ENDIF. - IF ls_cellxfs-alignmentid NE 0. - ls_cellxfs-applyalignment = 1. - ELSE. - ls_cellxfs-applyalignment = 0. - ENDIF. - IF ls_cellxfs-fillid NE 0. - ls_cellxfs-applyfill = 1. - ELSE. - ls_cellxfs-applyfill = 0. - ENDIF. - IF ls_cellxfs-borderid NE 0. - ls_cellxfs-applyborder = 1. - ELSE. - ls_cellxfs-applyborder = 0. - ENDIF. + IF ls_cellxfs-fontid NE 0. + ls_cellxfs-applyfont = 1. + ELSE. + ls_cellxfs-applyfont = 0. + ENDIF. + IF ls_cellxfs-alignmentid NE 0. + ls_cellxfs-applyalignment = 1. + ELSE. + ls_cellxfs-applyalignment = 0. + ENDIF. + IF ls_cellxfs-fillid NE 0. + ls_cellxfs-applyfill = 1. + ELSE. + ls_cellxfs-applyfill = 0. + ENDIF. + IF ls_cellxfs-borderid NE 0. + ls_cellxfs-applyborder = 1. + ELSE. + ls_cellxfs-applyborder = 0. + ENDIF. * Remap styles - READ TABLE lt_cellxfs FROM ls_cellxfs TRANSPORTING NO FIELDS. - IF sy-subrc EQ 0. - ls_styles_mapping-style = sy-tabix. - ELSE. - APPEND ls_cellxfs TO lt_cellxfs. - DESCRIBE TABLE lt_cellxfs LINES ls_styles_mapping-style. - ENDIF. - SUBTRACT 1 FROM ls_styles_mapping-style. - ls_styles_mapping-guid = lo_style->get_guid( ). - APPEND ls_styles_mapping TO me->styles_mapping. - ENDWHILE. - - " create numfmt elements - LOOP AT lt_numfmts INTO ls_numfmt. - lo_element_numfmt = lo_document->create_simple_element( name = lc_xml_node_numfmt - parent = lo_document ). - lv_value = sy-tabix + zcl_excel_common=>c_excel_numfmt_offset. - CONDENSE lv_value. - lo_element_numfmt->set_attribute_ns( name = lc_xml_attr_numfmtid - value = lv_value ). - lv_value = ls_numfmt-numfmt. -* REPLACE ALL OCCURRENCES OF '.' IN lv_value WITH '\.'. - lo_element_numfmt->set_attribute_ns( name = lc_xml_attr_formatcode - value = lv_value ). - lo_element_numfmts->append_child( new_child = lo_element_numfmt ). - ENDLOOP. - - " create font elements - LOOP AT lt_fonts INTO ls_font. - lo_element_font = lo_document->create_simple_element( name = lc_xml_node_font - parent = lo_document ). - IF ls_font-bold EQ abap_true. - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_b - parent = lo_document ). - lo_element_font->append_child( new_child = lo_sub_element ). - ENDIF. - IF ls_font-italic EQ abap_true. - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_i - parent = lo_document ). - lo_element_font->append_child( new_child = lo_sub_element ). - ENDIF. - IF ls_font-underline EQ abap_true. - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_u - parent = lo_document ). - lv_value = ls_font-underline_mode. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_val - value = lv_value ). - lo_element_font->append_child( new_child = lo_sub_element ). - ENDIF. - IF ls_font-strikethrough EQ abap_true. - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_strike - parent = lo_document ). - lo_element_font->append_child( new_child = lo_sub_element ). - ENDIF. - "size - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_sz - parent = lo_document ). - lv_value = ls_font-size. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_val - value = lv_value ). - lo_element_font->append_child( new_child = lo_sub_element ). - "color - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_element_font - is_color = ls_font-color ). - - "name - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_name - parent = lo_document ). - lv_value = ls_font-name. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_val - value = lv_value ). - lo_element_font->append_child( new_child = lo_sub_element ). - "family - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_family - parent = lo_document ). - lv_value = ls_font-family. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_val - value = lv_value ). - lo_element_font->append_child( new_child = lo_sub_element ). - "scheme - IF ls_font-scheme IS NOT INITIAL. - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_scheme - parent = lo_document ). - lv_value = ls_font-scheme. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_val - value = lv_value ). - lo_element_font->append_child( new_child = lo_sub_element ). - ENDIF. - lo_element_fonts->append_child( new_child = lo_element_font ). - ENDLOOP. - - " create fill elements - LOOP AT lt_fills INTO ls_fill. - lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill - parent = lo_document ). - "pattern - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_patternfill - parent = lo_document ). - lv_value = ls_fill-filltype. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_patterntype - value = lv_value ). - " fgcolor - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_fill-fgcolor - iv_color_elem_name = lc_xml_node_fgcolor ). - - " bgcolor - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_fill-bgcolor - iv_color_elem_name = lc_xml_node_bgcolor ). - - lo_element_fill->append_child( new_child = lo_sub_element )."pattern - lo_element_fills->append_child( new_child = lo_element_fill ). - ENDLOOP. - - " create border elements - LOOP AT lt_borders INTO ls_border. - lo_element_border = lo_document->create_simple_element( name = lc_xml_node_border - parent = lo_document ). - - IF ls_border-diagonalup IS NOT INITIAL. - lv_value = ls_border-diagonalup. - CONDENSE lv_value. - lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonalup - value = lv_value ). - ENDIF. - - IF ls_border-diagonaldown IS NOT INITIAL. - lv_value = ls_border-diagonaldown. - CONDENSE lv_value. - lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonaldown - value = lv_value ). - ENDIF. - - "left - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_left - parent = lo_document ). - IF ls_border-left_style IS NOT INITIAL. - lv_value = ls_border-left_style. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_style - value = lv_value ). - ENDIF. - - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_border-left_color ). - - lo_element_border->append_child( new_child = lo_sub_element ). - - "right - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_right - parent = lo_document ). - IF ls_border-right_style IS NOT INITIAL. - lv_value = ls_border-right_style. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_style - value = lv_value ). - ENDIF. - - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_border-right_color ). - - lo_element_border->append_child( new_child = lo_sub_element ). - - "top - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_top - parent = lo_document ). - IF ls_border-top_style IS NOT INITIAL. - lv_value = ls_border-top_style. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_style - value = lv_value ). - ENDIF. - - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_border-top_color ). - - lo_element_border->append_child( new_child = lo_sub_element ). - - "bottom - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_bottom - parent = lo_document ). - IF ls_border-bottom_style IS NOT INITIAL. - lv_value = ls_border-bottom_style. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_style - value = lv_value ). - ENDIF. - - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_border-bottom_color ). - - lo_element_border->append_child( new_child = lo_sub_element ). - - "diagonal - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_diagonal - parent = lo_document ). - IF ls_border-diagonal_style IS NOT INITIAL. - lv_value = ls_border-diagonal_style. - lo_sub_element->set_attribute_ns( name = lc_xml_attr_style - value = lv_value ). - ENDIF. - - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element - is_color = ls_border-diagonal_color ). - - lo_element_border->append_child( new_child = lo_sub_element ). - lo_element_borders->append_child( new_child = lo_element_border ). - ENDLOOP. - - " update attribute "count" - DESCRIBE TABLE lt_fonts LINES lv_fonts_count. - MOVE lv_fonts_count TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element_fonts->set_attribute_ns( name = lc_xml_attr_count - value = lv_value ). - DESCRIBE TABLE lt_fills LINES lv_fills_count. - MOVE lv_fills_count TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element_fills->set_attribute_ns( name = lc_xml_attr_count - value = lv_value ). - DESCRIBE TABLE lt_borders LINES lv_borders_count. - MOVE lv_borders_count TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element_borders->set_attribute_ns( name = lc_xml_attr_count - value = lv_value ). - DESCRIBE TABLE lt_cellxfs LINES lv_cellxfs_count. - MOVE lv_cellxfs_count TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element_cellxfs->set_attribute_ns( name = lc_xml_attr_count - value = lv_value ). - - " Append to root node - lo_element_root->append_child( new_child = lo_element_numfmts ). - lo_element_root->append_child( new_child = lo_element_fonts ). - lo_element_root->append_child( new_child = lo_element_fills ). - lo_element_root->append_child( new_child = lo_element_borders ). - - " cellstylexfs node - lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstylexfs - parent = lo_document ). - lo_element->set_attribute_ns( name = lc_xml_attr_count - value = '1' ). - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_xf - parent = lo_document ). - - lo_sub_element->set_attribute_ns( name = lc_xml_attr_numfmtid - value = c_off ). - lo_sub_element->set_attribute_ns( name = lc_xml_attr_fontid - value = c_off ). - lo_sub_element->set_attribute_ns( name = lc_xml_attr_fillid - value = c_off ). - lo_sub_element->set_attribute_ns( name = lc_xml_attr_borderid - value = c_off ). - - lo_element->append_child( new_child = lo_sub_element ). - lo_element_root->append_child( new_child = lo_element ). - - LOOP AT lt_cellxfs INTO ls_cellxfs. - lo_element = lo_document->create_simple_element( name = lc_xml_node_xf - parent = lo_document ). - MOVE ls_cellxfs-numfmtid TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_numfmtid - value = lv_value ). - MOVE ls_cellxfs-fontid TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_fontid - value = lv_value ). - MOVE ls_cellxfs-fillid TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_fillid - value = lv_value ). - MOVE ls_cellxfs-borderid TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_borderid - value = lv_value ). - MOVE ls_cellxfs-xfid TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_xfid - value = lv_value ). - IF ls_cellxfs-applynumberformat EQ 1. - MOVE ls_cellxfs-applynumberformat TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_applynumberformat - value = lv_value ). - ENDIF. - IF ls_cellxfs-applyfont EQ 1. - MOVE ls_cellxfs-applyfont TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_applyfont - value = lv_value ). - ENDIF. - IF ls_cellxfs-applyfill EQ 1. - MOVE ls_cellxfs-applyfill TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_applyfill - value = lv_value ). - ENDIF. - IF ls_cellxfs-applyborder EQ 1. - MOVE ls_cellxfs-applyborder TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_applyborder - value = lv_value ). - ENDIF. - IF ls_cellxfs-applyalignment EQ 1. " depends on each style not for all the sheet - MOVE ls_cellxfs-applyalignment TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_element->set_attribute_ns( name = lc_xml_attr_applyalignment - value = lv_value ). - lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_alignment - parent = lo_document ). - ADD 1 TO ls_cellxfs-alignmentid. "Table index starts from 1 - READ TABLE lt_alignments INTO ls_alignment INDEX ls_cellxfs-alignmentid. - SUBTRACT 1 FROM ls_cellxfs-alignmentid. - IF ls_alignment-horizontal IS NOT INITIAL. - MOVE ls_alignment-horizontal TO lv_value. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_horizontal - value = lv_value ). + READ TABLE lt_cellxfs FROM ls_cellxfs TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_styles_mapping-style = sy-tabix. + ELSE. + APPEND ls_cellxfs TO lt_cellxfs. + DESCRIBE TABLE lt_cellxfs LINES ls_styles_mapping-style. ENDIF. - IF ls_alignment-vertical IS NOT INITIAL. - MOVE ls_alignment-vertical TO lv_value. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_vertical - value = lv_value ). - ENDIF. - IF ls_alignment-wraptext EQ abap_true. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_wraptext - value = c_on ). - ENDIF. - IF ls_alignment-textrotation IS NOT INITIAL. - MOVE ls_alignment-textrotation TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_textrotation - value = lv_value ). - ENDIF. - IF ls_alignment-shrinktofit EQ abap_true. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_shrinktofit - value = c_on ). - ENDIF. - IF ls_alignment-indent IS NOT INITIAL. - MOVE ls_alignment-indent TO lv_value. - SHIFT lv_value RIGHT DELETING TRAILING space. - SHIFT lv_value LEFT DELETING LEADING space. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_indent - value = lv_value ). - ENDIF. - - lo_element->append_child( new_child = lo_sub_element_2 ). - ENDIF. - IF ls_cellxfs-applyprotection EQ 1. - MOVE ls_cellxfs-applyprotection TO lv_value. - CONDENSE lv_value NO-GAPS. - lo_element->set_attribute_ns( name = lc_xml_attr_applyprotection - value = lv_value ). - lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_protection - parent = lo_document ). - ADD 1 TO ls_cellxfs-protectionid. "Table index starts from 1 - READ TABLE lt_protections INTO ls_protection INDEX ls_cellxfs-protectionid. - SUBTRACT 1 FROM ls_cellxfs-protectionid. - IF ls_protection-locked IS NOT INITIAL. - MOVE ls_protection-locked TO lv_value. - CONDENSE lv_value. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_locked - value = lv_value ). - ENDIF. - IF ls_protection-hidden IS NOT INITIAL. - MOVE ls_protection-hidden TO lv_value. - CONDENSE lv_value. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_hidden - value = lv_value ). - ENDIF. - lo_element->append_child( new_child = lo_sub_element_2 ). - ENDIF. - lo_element_cellxfs->append_child( new_child = lo_element ). - ENDLOOP. - - lo_element_root->append_child( new_child = lo_element_cellxfs ). - - " cellStyles node - lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstyles - parent = lo_document ). - lo_element->set_attribute_ns( name = lc_xml_attr_count - value = '1' ). - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_cellstyle - parent = lo_document ). - - lo_sub_element->set_attribute_ns( name = lc_xml_attr_name - value = 'Normal' ). - lo_sub_element->set_attribute_ns( name = lc_xml_attr_xfid - value = c_off ). - lo_sub_element->set_attribute_ns( name = lc_xml_attr_builtinid - value = c_off ). - - lo_element->append_child( new_child = lo_sub_element ). - lo_element_root->append_child( new_child = lo_element ). - - " dxfs node - lo_element = lo_document->create_simple_element( name = lc_xml_node_dxfs - parent = lo_document ). - - lo_iterator = me->excel->get_worksheets_iterator( ). - " get sheets - WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). - " Conditional formatting styles into exch sheet - lo_iterator2 = lo_worksheet->get_cond_styles_iterator( ). - WHILE lo_iterator2->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_style_conditional ?= lo_iterator2->if_object_collection_iterator~get_next( ). - CASE lo_style_conditional->rule. - WHEN zcl_excel_style_conditional=>c_rule_cellis. - "if style defined - ls_cellis = lo_style_conditional->mode_cellis. - IF ls_cellis-cell_style IS INITIAL. - CONTINUE. - ENDIF. - READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = ls_cellis-cell_style. - ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 - READ TABLE lt_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. - ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 - - " Style already mapped? - READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. - IF sy-subrc EQ 0. - ls_style_cond_mapping-guid = ls_cellis-cell_style. - APPEND ls_style_cond_mapping TO me->styles_cond_mapping. - ELSE. - ls_style_cond_mapping-guid = ls_cellis-cell_style. - ls_style_cond_mapping-style = ls_styles_mapping-style. - ls_style_cond_mapping-dxf = lv_dfx_count. - APPEND ls_style_cond_mapping TO me->styles_cond_mapping. - ADD 1 TO lv_dfx_count. - - " dxf node - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_dxf - parent = lo_document ). - - READ TABLE lt_fills INTO ls_fill INDEX ls_cellxfs-fillid. - IF ls_fill IS NOT INITIAL. - " fill properties - lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill - parent = lo_document ). - "pattern - lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_patternfill - parent = lo_document ). - lv_value = ls_fill-filltype. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype - value = lv_value ). - " fgcolor - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element_2 - is_color = ls_fill-fgcolor - iv_color_elem_name = lc_xml_node_fgcolor ). - - " bgcolor - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element_2 - is_color = ls_fill-bgcolor - iv_color_elem_name = lc_xml_node_bgcolor ). - - lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern - - lo_sub_element->append_child( new_child = lo_element_fill ). - ENDIF. - ENDIF. - - lo_element->append_child( new_child = lo_sub_element ). - WHEN zcl_excel_style_conditional=>c_rule_expression. - "if style defined - ls_expression = lo_style_conditional->mode_expression. - IF ls_expression-cell_style IS INITIAL. - CONTINUE. - ENDIF. - READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = ls_expression-cell_style. - ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 - READ TABLE lt_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. - ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 - - READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. - IF sy-subrc EQ 0. - ls_style_cond_mapping-guid = ls_expression-cell_style. - APPEND ls_style_cond_mapping TO me->styles_cond_mapping. - ELSE. - ls_style_cond_mapping-guid = ls_expression-cell_style. - ls_style_cond_mapping-style = ls_styles_mapping-style. - ls_style_cond_mapping-dxf = lv_dfx_count. - APPEND ls_style_cond_mapping TO me->styles_cond_mapping. - ADD 1 TO lv_dfx_count. - - " dxf node - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_dxf - parent = lo_document ). - - READ TABLE lt_fills INTO ls_fill INDEX ls_cellxfs-fillid. - IF ls_fill IS NOT INITIAL. - " fill properties - lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill - parent = lo_document ). - "pattern - lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_patternfill - parent = lo_document ). - lv_value = ls_fill-filltype. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype - value = lv_value ). - " fgcolor - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element_2 - is_color = ls_fill-fgcolor - iv_color_elem_name = lc_xml_node_fgcolor ). - - " bgcolor - create_xl_styles_color_node( - io_document = lo_document - io_parent = lo_sub_element_2 - is_color = ls_fill-bgcolor - iv_color_elem_name = lc_xml_node_bgcolor ). - - lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern - - lo_sub_element->append_child( new_child = lo_element_fill ). - ENDIF. - ENDIF. - - lo_element->append_child( new_child = lo_sub_element ). - WHEN OTHERS. - CONTINUE. - ENDCASE. + SUBTRACT 1 FROM ls_styles_mapping-style. + ls_styles_mapping-guid = lo_style->get_guid( ). + APPEND ls_styles_mapping TO me->styles_mapping. ENDWHILE. - ENDWHILE. - lv_value = lv_dfx_count. - CONDENSE lv_value. - lo_element->set_attribute_ns( name = lc_xml_attr_count - value = lv_value ). - lo_element_root->append_child( new_child = lo_element ). - - " tableStyles node - lo_element = lo_document->create_simple_element( name = lc_xml_node_tablestyles - parent = lo_document ). - lo_element->set_attribute_ns( name = lc_xml_attr_count - value = '0' ). - lo_element->set_attribute_ns( name = lc_xml_attr_defaulttablestyle - value = zcl_excel_table=>builtinstyle_medium9 ). - lo_element->set_attribute_ns( name = lc_xml_attr_defaultpivotstyle - value = zcl_excel_table=>builtinstyle_pivot_light16 ). - lo_element_root->append_child( new_child = lo_element ). - - "write legacy color palette in case any indexed color was changed - IF excel->legacy_palette->is_modified( ) = abap_true. - lo_element = lo_document->create_simple_element( name = lc_xml_node_colors - parent = lo_document ). - lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_indexedcolors - parent = lo_document ). - lo_element->append_child( new_child = lo_sub_element ). - - lt_colors = excel->legacy_palette->get_colors( ). - LOOP AT lt_colors INTO ls_color. - lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_rgbcolor - parent = lo_document ). - lv_value = ls_color. - lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_rgb - value = lv_value ). - lo_sub_element->append_child( new_child = lo_sub_element_2 ). + " create numfmt elements + LOOP AT lt_numfmts INTO ls_numfmt. + lo_element_numfmt = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_document ). + lv_value = sy-tabix + zcl_excel_common=>c_excel_numfmt_offset. + CONDENSE lv_value. + lo_element_numfmt->set_attribute_ns( name = lc_xml_attr_numfmtid + value = lv_value ). + lv_value = ls_numfmt-numfmt. +* REPLACE ALL OCCURRENCES OF '.' IN lv_value WITH '\.'. + lo_element_numfmt->set_attribute_ns( name = lc_xml_attr_formatcode + value = lv_value ). + lo_element_numfmts->append_child( new_child = lo_element_numfmt ). ENDLOOP. + " create font elements + LOOP AT lt_fonts INTO ls_font. + lo_element_font = lo_document->create_simple_element( name = lc_xml_node_font + parent = lo_document ). + IF ls_font-bold EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_b + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + IF ls_font-italic EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_i + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + IF ls_font-underline EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_u + parent = lo_document ). + lv_value = ls_font-underline_mode. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + IF ls_font-strikethrough EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_strike + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + "size + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_sz + parent = lo_document ). + lv_value = ls_font-size. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + "color + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_element_font + is_color = ls_font-color ). + + "name + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_name + parent = lo_document ). + lv_value = ls_font-name. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + "family + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_family + parent = lo_document ). + lv_value = ls_font-family. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + "scheme + IF ls_font-scheme IS NOT INITIAL. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_scheme + parent = lo_document ). + lv_value = ls_font-scheme. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + lo_element_fonts->append_child( new_child = lo_element_font ). + ENDLOOP. + + " create fill elements + LOOP AT lt_fills INTO ls_fill. + lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill + parent = lo_document ). + "pattern + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + lo_element_fill->append_child( new_child = lo_sub_element )."pattern + lo_element_fills->append_child( new_child = lo_element_fill ). + ENDLOOP. + + " create border elements + LOOP AT lt_borders INTO ls_border. + lo_element_border = lo_document->create_simple_element( name = lc_xml_node_border + parent = lo_document ). + + IF ls_border-diagonalup IS NOT INITIAL. + lv_value = ls_border-diagonalup. + CONDENSE lv_value. + lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonalup + value = lv_value ). + ENDIF. + + IF ls_border-diagonaldown IS NOT INITIAL. + lv_value = ls_border-diagonaldown. + CONDENSE lv_value. + lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonaldown + value = lv_value ). + ENDIF. + + "left + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_left + parent = lo_document ). + IF ls_border-left_style IS NOT INITIAL. + lv_value = ls_border-left_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-left_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "right + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_right + parent = lo_document ). + IF ls_border-right_style IS NOT INITIAL. + lv_value = ls_border-right_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-right_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "top + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_top + parent = lo_document ). + IF ls_border-top_style IS NOT INITIAL. + lv_value = ls_border-top_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-top_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "bottom + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_bottom + parent = lo_document ). + IF ls_border-bottom_style IS NOT INITIAL. + lv_value = ls_border-bottom_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-bottom_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "diagonal + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_diagonal + parent = lo_document ). + IF ls_border-diagonal_style IS NOT INITIAL. + lv_value = ls_border-diagonal_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-diagonal_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + lo_element_borders->append_child( new_child = lo_element_border ). + ENDLOOP. + + " update attribute "count" + DESCRIBE TABLE lt_fonts LINES lv_fonts_count. + MOVE lv_fonts_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_fonts->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_fills LINES lv_fills_count. + MOVE lv_fills_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_fills->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_borders LINES lv_borders_count. + MOVE lv_borders_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_borders->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_cellxfs LINES lv_cellxfs_count. + MOVE lv_cellxfs_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_cellxfs->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + + " Append to root node + lo_element_root->append_child( new_child = lo_element_numfmts ). + lo_element_root->append_child( new_child = lo_element_fonts ). + lo_element_root->append_child( new_child = lo_element_fills ). + lo_element_root->append_child( new_child = lo_element_borders ). + + " cellstylexfs node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstylexfs + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '1' ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_xf + parent = lo_document ). + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_numfmtid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_fontid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_fillid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_borderid + value = c_off ). + + lo_element->append_child( new_child = lo_sub_element ). lo_element_root->append_child( new_child = lo_element ). - ENDIF. + + LOOP AT lt_cellxfs INTO ls_cellxfs. + lo_element = lo_document->create_simple_element( name = lc_xml_node_xf + parent = lo_document ). + MOVE ls_cellxfs-numfmtid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_numfmtid + value = lv_value ). + MOVE ls_cellxfs-fontid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_fontid + value = lv_value ). + MOVE ls_cellxfs-fillid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_fillid + value = lv_value ). + MOVE ls_cellxfs-borderid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_borderid + value = lv_value ). + MOVE ls_cellxfs-xfid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_xfid + value = lv_value ). + IF ls_cellxfs-applynumberformat EQ 1. + MOVE ls_cellxfs-applynumberformat TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applynumberformat + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyfont EQ 1. + MOVE ls_cellxfs-applyfont TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyfont + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyfill EQ 1. + MOVE ls_cellxfs-applyfill TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyfill + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyborder EQ 1. + MOVE ls_cellxfs-applyborder TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyborder + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyalignment EQ 1. " depends on each style not for all the sheet + MOVE ls_cellxfs-applyalignment TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyalignment + value = lv_value ). + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_alignment + parent = lo_document ). + ADD 1 TO ls_cellxfs-alignmentid. "Table index starts from 1 + READ TABLE lt_alignments INTO ls_alignment INDEX ls_cellxfs-alignmentid. + SUBTRACT 1 FROM ls_cellxfs-alignmentid. + IF ls_alignment-horizontal IS NOT INITIAL. + MOVE ls_alignment-horizontal TO lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_horizontal + value = lv_value ). + ENDIF. + IF ls_alignment-vertical IS NOT INITIAL. + MOVE ls_alignment-vertical TO lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_vertical + value = lv_value ). + ENDIF. + IF ls_alignment-wraptext EQ abap_true. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_wraptext + value = c_on ). + ENDIF. + IF ls_alignment-textrotation IS NOT INITIAL. + MOVE ls_alignment-textrotation TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_textrotation + value = lv_value ). + ENDIF. + IF ls_alignment-shrinktofit EQ abap_true. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_shrinktofit + value = c_on ). + ENDIF. + IF ls_alignment-indent IS NOT INITIAL. + MOVE ls_alignment-indent TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_indent + value = lv_value ). + ENDIF. + + lo_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_cellxfs-applyprotection EQ 1. + MOVE ls_cellxfs-applyprotection TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_applyprotection + value = lv_value ). + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_protection + parent = lo_document ). + ADD 1 TO ls_cellxfs-protectionid. "Table index starts from 1 + READ TABLE lt_protections INTO ls_protection INDEX ls_cellxfs-protectionid. + SUBTRACT 1 FROM ls_cellxfs-protectionid. + IF ls_protection-locked IS NOT INITIAL. + MOVE ls_protection-locked TO lv_value. + CONDENSE lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_locked + value = lv_value ). + ENDIF. + IF ls_protection-hidden IS NOT INITIAL. + MOVE ls_protection-hidden TO lv_value. + CONDENSE lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = lv_value ). + ENDIF. + lo_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + lo_element_cellxfs->append_child( new_child = lo_element ). + ENDLOOP. + + lo_element_root->append_child( new_child = lo_element_cellxfs ). + + " cellStyles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstyles + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '1' ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_cellstyle + parent = lo_document ). + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = 'Normal' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_xfid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_builtinid + value = c_off ). + + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + + " dxfs node + lo_element = lo_document->create_simple_element( name = lc_xml_node_dxfs + parent = lo_document ). + + lo_iterator = me->excel->get_worksheets_iterator( ). + " get sheets + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + " Conditional formatting styles into exch sheet + lo_iterator2 = lo_worksheet->get_cond_styles_iterator( ). + WHILE lo_iterator2->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style_conditional ?= lo_iterator2->if_object_collection_iterator~get_next( ). + CASE lo_style_conditional->rule. + WHEN zcl_excel_style_conditional=>c_rule_cellis. + "if style defined + ls_cellis = lo_style_conditional->mode_cellis. + IF ls_cellis-cell_style IS INITIAL. + CONTINUE. + ENDIF. + READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = ls_cellis-cell_style. + ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 + READ TABLE lt_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. + ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 + + " Style already mapped? + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. + IF sy-subrc EQ 0. + ls_style_cond_mapping-guid = ls_cellis-cell_style. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ELSE. + ls_style_cond_mapping-guid = ls_cellis-cell_style. + ls_style_cond_mapping-style = ls_styles_mapping-style. + ls_style_cond_mapping-dxf = lv_dfx_count. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ADD 1 TO lv_dfx_count. + + " dxf node + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_dxf + parent = lo_document ). + +"Conditional formatting font style correction by Alessandro Iannacci START + READ TABLE lt_fonts into ls_font INDEX ls_cellxfs-FONTID + 1. + IF ls_font IS NOT INITIAL. + lo_element_font = lo_document->create_simple_element( name = lc_xml_node_font + parent = lo_document ). + IF ls_font-bold EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_b + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-italic EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_i + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-underline EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_u + parent = lo_document ). + lv_value = ls_font-underline_mode. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-strikethrough EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_strike + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + "color + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_element_font + is_color = ls_font-color ). + lo_sub_element->append_child( new_child = lo_element_font ). + ENDIF. +"---Conditional formatting font style correction by Alessandro Iannacci END + + + READ TABLE lt_fills INTO ls_fill INDEX ls_cellxfs-fillid. + IF ls_fill IS NOT INITIAL. + " fill properties + lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill + parent = lo_document ). + "pattern + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern + + lo_sub_element->append_child( new_child = lo_element_fill ). + ENDIF. + ENDIF. + + lo_element->append_child( new_child = lo_sub_element ). + WHEN zcl_excel_style_conditional=>c_rule_expression. + "if style defined + ls_expression = lo_style_conditional->mode_expression. + IF ls_expression-cell_style IS INITIAL. + CONTINUE. + ENDIF. + READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = ls_expression-cell_style. + ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 + READ TABLE lt_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. + ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 + + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. + IF sy-subrc EQ 0. + ls_style_cond_mapping-guid = ls_expression-cell_style. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ELSE. + ls_style_cond_mapping-guid = ls_expression-cell_style. + ls_style_cond_mapping-style = ls_styles_mapping-style. + ls_style_cond_mapping-dxf = lv_dfx_count. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ADD 1 TO lv_dfx_count. + + " dxf node + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_dxf + parent = lo_document ). + + READ TABLE lt_fills INTO ls_fill INDEX ls_cellxfs-fillid. + IF ls_fill IS NOT INITIAL. + " fill properties + lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill + parent = lo_document ). + "pattern + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern + + lo_sub_element->append_child( new_child = lo_element_fill ). + ENDIF. + ENDIF. + + lo_element->append_child( new_child = lo_sub_element ). + WHEN OTHERS. + CONTINUE. + ENDCASE. + ENDWHILE. + ENDWHILE. + + lv_value = lv_dfx_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " tableStyles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_tablestyles + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '0' ). + lo_element->set_attribute_ns( name = lc_xml_attr_defaulttablestyle + value = zcl_excel_table=>builtinstyle_medium9 ). + lo_element->set_attribute_ns( name = lc_xml_attr_defaultpivotstyle + value = zcl_excel_table=>builtinstyle_pivot_light16 ). + lo_element_root->append_child( new_child = lo_element ). + + "write legacy color palette in case any indexed color was changed + IF excel->legacy_palette->is_modified( ) = abap_true. + lo_element = lo_document->create_simple_element( name = lc_xml_node_colors + parent = lo_document ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_indexedcolors + parent = lo_document ). + lo_element->append_child( new_child = lo_sub_element ). + + lt_colors = excel->legacy_palette->get_colors( ). + LOOP AT lt_colors INTO ls_color. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_rgbcolor + parent = lo_document ). + lv_value = ls_color. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_rgb + value = lv_value ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + ENDLOOP. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. ********************************************************************** * STEP 5: Create xstring stream - lo_streamfactory = lo_ixml->create_stream_factory( ). - lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). - lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). - lo_renderer->render( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). -endmethod. + endmethod. @@ -5417,12 +18030,12 @@ endmethod. ENDIF. io_parent->append_child( new_child = lo_sub_element ). -endmethod. + endmethod. - METHOD create_xl_table. + method CREATE_XL_TABLE. DATA: lc_xml_node_table TYPE string VALUE 'table', lc_xml_node_relationship TYPE string VALUE 'Relationship', @@ -5594,7 +18207,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -ENDMETHOD. + endmethod. @@ -5683,20 +18296,20 @@ ENDMETHOD. buffer = ep_content. -endmethod. + endmethod. method CREATE_XL_WORKBOOK. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-07 +* - Stefan Schmöcker, (done) 2012-11-07 * - ... * changes: aligning code * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* * issue#235 - repeat rows/columns -* - Stefan Schmöcker, 2012-12-01 +* - Stefan Schmöcker, 2012-12-01 * changes: correction of pointer to localSheetId *--------------------------------------------------------------------* @@ -5877,7 +18490,7 @@ endmethod. lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_sheet parent = lo_document ). lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). - lv_syindex = sy-index. " question by Stefan Schmöcker 2012-12-02: sy-index seems to do the job - but is it proven to work or purely coincedence + lv_syindex = sy-index. " question by Stefan Schmöcker 2012-12-02: sy-index seems to do the job - but is it proven to work or purely coincedence lv_value = lo_worksheet->get_title( ). SHIFT lv_syindex RIGHT DELETING TRAILING space. SHIFT lv_syindex LEFT DELETING LEADING space. @@ -6004,7 +18617,7 @@ endmethod. lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). lo_renderer->render( ). -endmethod. + endmethod. @@ -6017,7 +18630,7 @@ endmethod. ELSE. ep_boolean = 'false'. ENDIF. -endmethod. + endmethod. @@ -6030,11 +18643,11 @@ endmethod. READ TABLE shared_strings INTO ls_shared_string WITH KEY string_value = ip_cell_value BINARY SEARCH. ep_index = ls_shared_string-string_no. -endmethod. + endmethod. - + *"* local class implementation for public class *"* use this source file for the implementation part of *"* local helper classes @@ -6053,7 +18666,7 @@ endmethod. method ZIF_EXCEL_WRITER~WRITE_FILE. me->excel = io_excel. ep_file = me->create( ). -endmethod. + endmethod. @@ -6063,7 +18676,7 @@ endmethod. ep_excel = me->CREATE_CSV( ). -endmethod. + endmethod. @@ -6282,43 +18895,43 @@ endmethod. OTHERS = 2 . -endmethod. + endmethod. method SET_ACTIVE_SHEET_INDEX. CLEAR WORKSHEET_NAME. WORKSHEET_INDEX = i_active_worksheet. -endmethod. + endmethod. method SET_ACTIVE_SHEET_INDEX_BY_NAME. CLEAR WORKSHEET_INDEX. WORKSHEET_NAME = i_worksheet_name. -endmethod. + endmethod. method SET_DELIMITER. delimiter = ip_value. -endmethod. + endmethod. method SET_ENCLOSURE. zcl_excel_writer_csv=>enclosure = ip_value. -endmethod. + endmethod. method SET_ENDOFLINE. zcl_excel_writer_csv=>eol = ip_value. -endmethod. + endmethod. - - - sheetid type string, "ins #235 - repeat rows/cols - needed to identify correct sheet END OF t_relationship '/> - - - - - - - - - - - - - - - + *"* local class implementation for public class *"* use this source file for the implementation part of *"* local helper classes @@ -6424,32 +19037,32 @@ endmethod. - - + + method ZIF_EXCEL_READER~CAN_READ_FILE. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-07 +* - Stefan Schmöcker, (done) 2012-11-07 * - ... * changes: nothing done in code * but started discussion about killing this method *--------------------------------------------------------------------* * For now always Unknown r_readable = abap_undefined. -endmethod. + endmethod. method ZIF_EXCEL_READER~LOAD. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Map Document Properties to ZCL_EXCEL +* 2do§1 Map Document Properties to ZCL_EXCEL *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-07 +* - Stefan Schmöcker, (done) 2012-11-07 * - ... * changes: renaming variables to naming conventions * removing unused variables @@ -6459,7 +19072,7 @@ endmethod. * adding me-> where possible *--------------------------------------------------------------------* * issue#234 - error reading xlsx written by libre office -* - Stefan Schmöcker, 2012-11-07 +* - Stefan Schmöcker, 2012-11-07 * changes: passing new optional input parameter to private attribute *--------------------------------------------------------------------* @@ -6471,9 +19084,9 @@ endmethod. ls_relationship TYPE t_relationship. *--------------------------------------------------------------------* -* §1 Create EXCEL-Object we want to return to caller +* §1 Create EXCEL-Object we want to return to caller -* §2 We need to read the the file "\\_rels\.rels" because it tells +* §2 We need to read the the file "\\_rels\.rels" because it tells * us where in this folder structure the data for the workbook * is located in the xlsx zip-archive * @@ -6486,7 +19099,7 @@ endmethod. * |--> theme * |--> worksheets -* §3 Extracting from this the path&file where the workbook is located +* §3 Extracting from this the path&file where the workbook is located * Following is an example how this file could be set up * <?xml version="1.0" encoding="UTF-8" standalone="true"?> * <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> @@ -6498,24 +19111,24 @@ endmethod. *--------------------------------------------------------------------* -* §1 Create EXCEL-Object we want to return to caller +* §1 Create EXCEL-Object we want to return to caller *--------------------------------------------------------------------* CREATE OBJECT r_excel. *--------------------------------------------------------------------* * issue#234 - error reading xlsx written by libre office - me->zif_excel_reader~gv_use_alternate_zip = iv_use_alternate_zip. + me->zif_excel_reader~gv_use_alternate_zip = i_use_alternate_zip. *--------------------------------------------------------------------* *--------------------------------------------------------------------* -* §2 Get file in folderstructure +* §2 Get file in folderstructure *--------------------------------------------------------------------* me->excel2007 = i_excel2007. lo_rels = me->get_ixml_from_zip_archive( '_rels/.rels' ). *--------------------------------------------------------------------* -* §3 Cycle through the Relationship Tags and use the ones we need +* §3 Cycle through the Relationship Tags and use the ones we need *--------------------------------------------------------------------* lo_node ?= lo_rels->find_from_name( 'Relationship' ). "#EC NOTEXT WHILE lo_node IS BOUND. @@ -6527,7 +19140,7 @@ endmethod. CASE ls_relationship-type. WHEN lcv_core_properties. - " 2do§1 Map Document Properties to ZCL_EXCEL + " 2do§1 Map Document Properties to ZCL_EXCEL WHEN lcv_office_document. me->load_workbook( iv_workbook_full_filename = ls_relationship-target @@ -6541,22 +19154,22 @@ endmethod. ENDWHILE. -endmethod. + endmethod. - method ZIF_EXCEL_READER~LOAD_FILE. + METHOD zif_excel_reader~load_file. *--------------------------------------------------------------------* * ToDos: -* 2do§1 decision whether to load from frontend or backend +* 2do§1 decision whether to load from frontend or backend * current behavior ( autodecide ) should be default * add optional parameter to allow user to choose * to load from backend even when online -* 2do§2 loosen typing of i_filename to CLIKE +* 2do§2 loosen typing of i_filename to CLIKE *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-05 +* - Stefan Schmöcker, (done) 2012-11-05 * - ... * changes: renaming variables to naming conventions * renaming variables to indicate what they are used for @@ -6569,130 +19182,28 @@ endmethod. * added errorhandling for open dataset *--------------------------------------------------------------------* * issue#234 - error reading xlsx written by libre office -* - Stefan Schmöcker, 2012-11-07 +* - Stefan Schmöcker, 2012-11-07 * changes: passing new optional input parameter to private attribute *--------------------------------------------------------------------* - CONSTANTS: lcv_load_from_frontend TYPE char1 VALUE 'F', - lcv_load_from_backend TYPE char1 VALUE 'B'. + DATA: lv_excel_data TYPE xstring. - DATA: lv_load_from_source TYPE char1, +* issue#234 - error reading xlsx written by libre office + me->zif_excel_reader~gv_use_alternate_zip = i_use_alternate_zip. - lv_filelength TYPE i, - lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, - ls_binary_data LIKE LINE OF lt_binary_data, -* Background processing - lv_max_length_line TYPE i, - lv_actual_length_line TYPE i, - - lv_errormessage TYPE string, " Can't pass '...'(abc) to exception-class - lv_excel_data TYPE xstring. " Binary content of .xlsx file - - -*--------------------------------------------------------------------* -* ToDos: 2do§1 Decision whether to load from frontend or backend -*--------------------------------------------------------------------* + IF i_from_applserver = abap_true. + lv_excel_data = me->read_from_applserver( i_filename = i_filename ). + ELSE. + lv_excel_data = me->read_from_local_file( i_filename = i_filename ). + ENDIF. *--------------------------------------------------------------------* * issue#234 - error reading xlsx written by libre office - me->zif_excel_reader~gv_use_alternate_zip = iv_use_alternate_zip. + r_excel = me->zif_excel_reader~load( i_excel2007 = lv_excel_data + i_use_alternate_zip = i_use_alternate_zip ). *--------------------------------------------------------------------* - -*--------------------------------------------------------------------* -* Autodecide on frontend or backend reading -* Background-processing --> backend reading -* Online-processing --> frontend reading -*--------------------------------------------------------------------* - IF sy-batch = abap_true. - lv_load_from_source = lcv_load_from_backend. - ELSE. - lv_load_from_source = lcv_load_from_frontend. - ENDIF. - - CASE lv_load_from_source. - -*--------------------------------------------------------------------* -* Read from backend -*--------------------------------------------------------------------* - WHEN lcv_load_from_backend. - DESCRIBE FIELD ls_binary_data LENGTH lv_max_length_line IN BYTE MODE. - OPEN DATASET i_filename FOR INPUT IN BINARY MODE. - IF sy-subrc <> 0. - lv_errormessage = 'A problem occured when reading the file'(001). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - WHILE sy-subrc = 0. - - READ DATASET i_filename INTO ls_binary_data MAXIMUM LENGTH lv_max_length_line ACTUAL LENGTH lv_actual_length_line. - APPEND ls_binary_data TO lt_binary_data. - lv_filelength = lv_filelength + lv_actual_length_line. - - ENDWHILE. - CLOSE DATASET i_filename. - -*--------------------------------------------------------------------* -* Read from frontend -*--------------------------------------------------------------------* - WHEN lcv_load_from_frontend. - cl_gui_frontend_services=>gui_upload( EXPORTING - filename = i_filename - filetype = 'BIN' " We are basically working with zipped directories --> force binary read - IMPORTING - filelength = lv_filelength - CHANGING - data_tab = lt_binary_data - EXCEPTIONS - file_open_error = 1 - file_read_error = 2 - no_batch = 3 - gui_refuse_filetransfer = 4 - invalid_type = 5 - no_authority = 6 - unknown_error = 7 - bad_data_format = 8 - header_not_allowed = 9 - separator_not_allowed = 10 - header_too_long = 11 - unknown_dp_error = 12 - access_denied = 13 - dp_out_of_memory = 14 - disk_full = 15 - dp_timeout = 16 - not_supported_by_gui = 17 - error_no_gui = 18 - OTHERS = 19 ). - IF sy-subrc <> 0. - lv_errormessage = 'A problem occured when reading the file'(001). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - ENDCASE. - - -*--------------------------------------------------------------------* -* Binary data needs to be provided as XSTRING for further processing -*--------------------------------------------------------------------* - CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' - EXPORTING - input_length = lv_filelength - IMPORTING - buffer = lv_excel_data - TABLES - binary_tab = lt_binary_data. - -*--------------------------------------------------------------------* -* issue#234 - error reading xlsx written by libre office - r_excel = me->zif_excel_reader~load( i_excel2007 = lv_excel_data - iv_use_alternate_zip = iv_use_alternate_zip ). -*--------------------------------------------------------------------* - - -endmethod. + ENDMETHOD. @@ -6700,7 +19211,7 @@ endmethod. method FILL_STRUCT_FROM_ATTRIBUTES. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-07 +* - Stefan Schmöcker, (done) 2012-11-07 * - ... * changes: renaming variables to naming conventions * aligning code @@ -6743,7 +19254,7 @@ endmethod. ENDWHILE. -endmethod. + endmethod. @@ -6752,7 +19263,7 @@ endmethod. method GET_FROM_ZIP_ARCHIVE. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-07 +* - Stefan Schmöcker, (done) 2012-11-07 * - ... * changes: aligning code * adding comments to explain what we are trying to achieve @@ -6760,7 +19271,7 @@ endmethod. * message made to support multilinguality *--------------------------------------------------------------------**--------------------------------------------------------------------* * issue#234 - error reading xlsx written by libre office -* - Stefan Schmöcker, 2012-11-07 +* - Stefan Schmöcker, 2012-11-07 * changes: copying coding and using ALTERNATE_ZIP in ELSE-Branch *--------------------------------------------------------------------* @@ -6869,7 +19380,7 @@ endmethod. * issue#234 - end of insertion *--------------------------------------------------------------------* -endmethod. + endmethod. @@ -6879,12 +19390,12 @@ endmethod. method GET_IXML_FROM_ZIP_ARCHIVE. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Add comment what is being achieved here +* 2do§1 Add comment what is being achieved here *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-07 +* - Stefan Schmöcker, (done) 2012-11-07 * - ... * changes: renaming variables to naming conventions * removing unnecessary type-pool @@ -6900,7 +19411,7 @@ endmethod. *--------------------------------------------------------------------* -* 2do§1 ???? Something happens here ??? +* 2do§1 ???? Something happens here ??? *--------------------------------------------------------------------* lv_content = me->get_from_zip_archive( i_filename ). lo_ixml = cl_ixml=>create( ). @@ -6915,7 +19426,7 @@ endmethod. lo_parser->set_validating( mode = if_ixml_parser=>co_no_validation ). lo_parser->parse( ). -endmethod. + endmethod. @@ -7067,7 +19578,7 @@ endmethod. lo_drawing->load_chart_attributes( rel_drawing-content_xml ). endif. -endmethod. + endmethod. @@ -7075,12 +19586,12 @@ endmethod. method LOAD_SHARED_STRINGS. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Support partial formatting of strings in cells +* 2do§1 Support partial formatting of strings in cells *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-11 +* - Stefan Schmöcker, (done) 2012-11-11 * - ... * changes: renaming variables to naming conventions * renaming variables to indicate what they are used for @@ -7103,10 +19614,10 @@ endmethod. *--------------------------------------------------------------------* -* §1 Parse shared strings file and get into internal table +* §1 Parse shared strings file and get into internal table * So far I have encountered 2 ways how a string can be represented in the shared strings file -* §1.1 - "simple" strings -* §1.2 - rich text formatted strings +* §1.1 - "simple" strings +* §1.2 - rich text formatted strings * Following is an example how this file could be set up; 2 strings in simple formatting, 3rd string rich textformatted @@ -7158,15 +19669,15 @@ endmethod. lv_tag_name = lo_node_si_child->get_name( ). IF lv_tag_name = 't'. *--------------------------------------------------------------------* -* §1.1 - "simple" strings +* §1.1 - "simple" strings * Example: see above *--------------------------------------------------------------------* <lv_shared_string> = lo_node_si_child->get_value( ). ELSE. *--------------------------------------------------------------------* -* §1.2 - rich text formatted strings +* §1.2 - rich text formatted strings * it is sufficient to strip the <t>...</t> tag from each <r>-tag and concatenate these -* as long as rich text formatting is not supported (2do§1) ignore all info about formatting +* as long as rich text formatting is not supported (2do§1) ignore all info about formatting * Example: see above *--------------------------------------------------------------------* WHILE lo_node_si_child IS BOUND. " actually these children of <si> are <r>-tags @@ -7186,7 +19697,7 @@ endmethod. lo_node_si ?= lo_node_si->get_next( ). ENDWHILE. -endmethod. + endmethod. @@ -7196,7 +19707,7 @@ endmethod. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (wip ) 2012-11-25 +* - Stefan Schmöcker, (wip ) 2012-11-25 * - ... * changes: renaming variables and types to naming conventions * aligning code @@ -7264,16 +19775,16 @@ endmethod. *--------------------------------------------------------------------* * To build a complete style that fully describes how a cell looks like * we need the various parts -* §1 - Numberformat -* §2 - Fillstyle -* §3 - Borders -* §4 - Font -* §5 - Alignment -* §6 - Protection +* §1 - Numberformat +* §2 - Fillstyle +* §3 - Borders +* §4 - Font +* §5 - Alignment +* §6 - Protection * Following is an example how this part of a file could be set up * ... -* parts with various formatinformation - see §1,§2,§3,§4 +* parts with various formatinformation - see §1,§2,§3,§4 * ... * <cellXfs count="26"> * <xf numFmtId="0" borderId="0" fillId="0" fontId="0" xfId="0"/> @@ -7291,17 +19802,17 @@ endmethod. *--------------------------------------------------------------------* * The styles are build up from -* §1 number formats -* §2 fill styles -* §3 border styles -* §4 fonts +* §1 number formats +* §2 fill styles +* §3 border styles +* §4 fonts * These need to be read before we can try to build up a complete * style that describes the look of a cell *--------------------------------------------------------------------* - lt_num_formats = load_style_num_formats( lo_styles_xml ). " §1 - lt_fills = load_style_fills( lo_styles_xml ). " §2 - lt_borders = load_style_borders( lo_styles_xml ). " §3 - lt_fonts = load_style_fonts( lo_styles_xml ). " §4 + lt_num_formats = load_style_num_formats( lo_styles_xml ). " §1 + lt_fills = load_style_fills( lo_styles_xml ). " §2 + lt_borders = load_style_borders( lo_styles_xml ). " §3 + lt_fonts = load_style_fonts( lo_styles_xml ). " §4 *--------------------------------------------------------------------* * Now everything is prepared to build a "full" style @@ -7319,7 +19830,7 @@ endmethod. CHANGING cp_structure = ls_xf ). *--------------------------------------------------------------------* -* §2 fill style +* §2 fill style *--------------------------------------------------------------------* IF ls_xf-applyfill = '1' AND ls_xf-fillid IS NOT INITIAL. lv_index = ls_xf-fillid + 1. @@ -7330,7 +19841,7 @@ endmethod. ENDIF. *--------------------------------------------------------------------* -* §1 number format +* §1 number format *--------------------------------------------------------------------* IF ls_xf-numfmtid IS NOT INITIAL. READ TABLE lt_num_formats INTO ls_num_format WITH TABLE KEY id = ls_xf-numfmtid. @@ -7340,7 +19851,7 @@ endmethod. ENDIF. *--------------------------------------------------------------------* -* §3 border style +* §3 border style *--------------------------------------------------------------------* IF ls_xf-applyborder = '1' AND ls_xf-borderid IS NOT INITIAL. lv_index = ls_xf-borderid + 1. @@ -7351,7 +19862,7 @@ endmethod. ENDIF. *--------------------------------------------------------------------* -* §4 font +* §4 font *--------------------------------------------------------------------* IF ls_xf-applyfont = '1' AND ls_xf-fontid IS NOT INITIAL. lv_index = ls_xf-fontid + 1. @@ -7362,7 +19873,7 @@ endmethod. ENDIF. *--------------------------------------------------------------------* -* §5 - Alignment +* §5 - Alignment *--------------------------------------------------------------------* lo_node_cellxfs_xf_alignment ?= lo_node_cellxfs_xf->find_from_name( 'alignment' ). IF lo_node_cellxfs_xf_alignment IS BOUND. @@ -7396,7 +19907,7 @@ endmethod. ENDIF. *--------------------------------------------------------------------* -* §6 - Protection +* §6 - Protection *--------------------------------------------------------------------* lo_node_cellxfs_xf_protection ?= lo_node_cellxfs_xf->find_from_name( 'protection' ). IF lo_node_cellxfs_xf_protection IS BOUND. @@ -7425,7 +19936,7 @@ endmethod. ENDWHILE. ENDIF. -endmethod. + endmethod. @@ -7434,7 +19945,7 @@ endmethod. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-25 +* - Stefan Schmöcker, (done) 2012-11-25 * - ... * changes: renaming variables and types to naming conventions * aligning code @@ -7450,11 +19961,11 @@ endmethod. *--------------------------------------------------------------------* * We need a table of used borderformats to build up our styles -* §1 A cell has 4 outer borders and 2 diagonal "borders" +* §1 A cell has 4 outer borders and 2 diagonal "borders" * These borders can be formatted separately but the diagonal borders * are always being formatted the same * We'll parse through the <border>-tag for each of the bordertypes -* §2 and read the corresponding formatting information +* §2 and read the corresponding formatting information * Following is an example how this part of a file could be set up * <border diagonalDown="1"> @@ -7497,7 +20008,7 @@ endmethod. lo_node_bordertype ?= lo_node_border->get_first_child( ). WHILE lo_node_bordertype IS BOUND. *--------------------------------------------------------------------* -* §1 Determine what kind of border we are talking about +* §1 Determine what kind of border we are talking about *--------------------------------------------------------------------* * Up, down, left, right, diagonal *--------------------------------------------------------------------* @@ -7523,7 +20034,7 @@ endmethod. ENDCASE. *--------------------------------------------------------------------* -* §2 Read the border-formatting +* §2 Read the border-formatting *--------------------------------------------------------------------* lo_border->border_style = lo_node_bordertype->get_attribute( 'style' ). lo_node_bordercolor ?= lo_node_bordertype->find_from_name( 'color' ). @@ -7555,7 +20066,7 @@ endmethod. ENDWHILE. -endmethod. + endmethod. @@ -7563,12 +20074,12 @@ endmethod. method LOAD_STYLE_FILLS. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Support gradientFill +* 2do§1 Support gradientFill *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-25 +* - Stefan Schmöcker, (done) 2012-11-25 * - ... * changes: renaming variables and types to naming conventions * aligning code @@ -7659,7 +20170,7 @@ endmethod. * gradientFill *--------------------------------------------------------------------* WHEN 'gradientFill'. - " 2do§1 Support gradientFill + " 2do§1 Support gradientFill WHEN OTHERS. @@ -7673,7 +20184,7 @@ endmethod. ENDWHILE. -endmethod. + endmethod. @@ -7682,7 +20193,7 @@ endmethod. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-25 +* - Stefan Schmöcker, (done) 2012-11-25 * - ... * changes: renaming variables and types to naming conventions * aligning code @@ -7799,7 +20310,7 @@ endmethod. ENDWHILE. -endmethod. + endmethod. @@ -7807,12 +20318,12 @@ endmethod. method LOAD_STYLE_NUM_FORMATS. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Explain gaps in predefined formats +* 2do§1 Explain gaps in predefined formats *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-25 +* - Stefan Schmöcker, (done) 2012-11-25 * - ... * changes: renaming variables and types to naming conventions * adding comments to explain what we are trying to achieve @@ -7824,12 +20335,12 @@ endmethod. *--------------------------------------------------------------------* * We need a table of used numberformats to build up our styles * there are two kinds of numberformats -* §1 those that have been explicitly added by the createor of the excel-file -* §2 and built-in numberformats +* §1 those that have been explicitly added by the createor of the excel-file +* §2 and built-in numberformats *--------------------------------------------------------------------* *--------------------------------------------------------------------* -* §1 Get non-internal numberformats that are found in the file explicitly +* §1 Get non-internal numberformats that are found in the file explicitly * Following is an example how this part of a file could be set up * <numFmts count="1"> @@ -7858,7 +20369,7 @@ endmethod. END-OF-DEFINITION. *--------------------------------------------------------------------* -* §1 Get internal predefined numberformats +* §1 Get internal predefined numberformats *--------------------------------------------------------------------* predefined_format '1' '0'. predefined_format '2' '0.00'. @@ -7882,7 +20393,7 @@ endmethod. predefined_format '20' 'h:mm'. predefined_format '21' 'h:mm:ss'. predefined_format '22' 'm/d/yyyy h:mm'. -* 2do§1 Why is there a gap in here? +* 2do§1 Why is there a gap in here? @@ -7900,7 +20411,7 @@ endmethod. predefined_format '38' '#,##0_);[Red](#,##0)'. predefined_format '39' '#,##0.00_);(#,##0.00)'. predefined_format '40' '#,##0.00_);[Red](#,##0.00)'. -* 2do§1 Why is there a gap in here? +* 2do§1 Why is there a gap in here? @@ -7909,26 +20420,26 @@ endmethod. predefined_format '47' 'mm:ss.0'. predefined_format '48' '##0.0E+0'. predefined_format '49' '@'. -* 2do§1 Is 49 really the last predefined format? +* 2do§1 Is 49 really the last predefined format? -endmethod. + endmethod. - METHOD load_workbook. + method LOAD_WORKBOOK. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Move macro-reading from zcl_excel_reader_xlsm to this class +* 2do§1 Move macro-reading from zcl_excel_reader_xlsm to this class * autodetect existance of macro/vba content * Allow inputparameter to explicitly tell reader to ignore vba-content *--------------------------------------------------------------------* *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-10 +* - Stefan Schmöcker, (done) 2012-11-10 * - ... * changes: renaming variables to naming conventions * aligning code @@ -7940,15 +20451,15 @@ endmethod. * ip_excel renamed while being at it --> rename to io_excel *--------------------------------------------------------------------* * issue #232 - Read worksheetstate hidden/veryHidden -* - Stefan Schmöcker, 2012-11-11 +* - Stefan Schmöcker, 2012-11-11 *--------------------------------------------------------------------* * issue#235 - repeat rows/columns -* - Stefan Schmöcker, 2012-12-02 +* - Stefan Schmöcker, 2012-12-02 * changes: correction in named ranges to correctly attach * sheetlocal names/ranges to the correct sheet *--------------------------------------------------------------------* * issue#284 - Copied formulae ignored when reading excelfile -* - Stefan Schmöcker, 2013-08-02 +* - Stefan Schmöcker, 2013-08-02 * changes: initialize area to hold referenced formulaedata * after all worksheets have been read resolve formuae *--------------------------------------------------------------------* @@ -8011,7 +20522,7 @@ endmethod. *--------------------------------------------------------------------* -* §1 Get the position of files related to this workbook +* §1 Get the position of files related to this workbook * Usually this will be <root>/xl/workbook.xml * Thus the workbookroot will be <root>/xl/ * The position of all related files will be given in file @@ -8031,19 +20542,19 @@ endmethod. * <Relationship Target="sharedStrings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Id="rId7"/> * </Relationships> * -* §2 Load data that is relevant to the complete workbook +* §2 Load data that is relevant to the complete workbook * Currently supported is: -* §2.1 Shared strings - This holds all strings that are used in all worksheets -* §2.2 Styles - This holds all styles that are used in all worksheets -* §2.3 Worksheets - For each worksheet in the workbook one entry appears here to point to the file that holds the content of this worksheet -* §2.4 [Themes] - not supported -* §2.5 [VBA (Macro)] - supported in class zcl_excel_reader_xlsm but should be moved here and autodetect +* §2.1 Shared strings - This holds all strings that are used in all worksheets +* §2.2 Styles - This holds all styles that are used in all worksheets +* §2.3 Worksheets - For each worksheet in the workbook one entry appears here to point to the file that holds the content of this worksheet +* §2.4 [Themes] - not supported +* §2.5 [VBA (Macro)] - supported in class zcl_excel_reader_xlsm but should be moved here and autodetect * ... * -* §3 Some information is held in the workbookfile as well -* §3.1 Names and order of of worksheets -* §3.2 Active worksheet -* §3.3 Defined names +* §3 Some information is held in the workbookfile as well +* §3.1 Names and order of of worksheets +* §3.2 Active worksheet +* §3.3 Defined names * ... * Following is an example how this file could be set up @@ -8068,7 +20579,7 @@ endmethod. CLEAR me->mt_ref_formulae. " ins issue#284 *--------------------------------------------------------------------* -* §1 Get the position of files related to this workbook +* §1 Get the position of files related to this workbook * Entry into this method is with the filename of the workbook *--------------------------------------------------------------------* CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' @@ -8090,7 +20601,7 @@ endmethod. CASE ls_relationship-type. *--------------------------------------------------------------------* -* §2.1 Shared strings - This holds all strings that are used in all worksheets +* §2.1 Shared strings - This holds all strings that are used in all worksheets *--------------------------------------------------------------------* WHEN lcv_shared_strings. CONCATENATE lv_path ls_relationship-target @@ -8098,7 +20609,7 @@ endmethod. me->load_shared_strings( lv_full_filename ). *--------------------------------------------------------------------* -* §2.3 Worksheets +* §2.3 Worksheets * For each worksheet in the workbook one entry appears here to point to the file that holds the content of this worksheet * Shared strings and styles have to be present before we can start with creating the worksheets * thus we only store this information for use when parsing the workbookfile for sheetinformations @@ -8107,7 +20618,7 @@ endmethod. APPEND ls_relationship TO lt_worksheets. *--------------------------------------------------------------------* -* §2.2 Styles - This holds the styles that are used in all worksheets +* §2.2 Styles - This holds the styles that are used in all worksheets *--------------------------------------------------------------------* WHEN lcv_styles. CONCATENATE lv_path ls_relationship-target @@ -8124,12 +20635,12 @@ endmethod. ENDWHILE. *--------------------------------------------------------------------* -* §3 Some information held in the workbookfile +* §3 Some information held in the workbookfile *--------------------------------------------------------------------* lo_workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). *--------------------------------------------------------------------* -* §3.1 Names and order of of worksheets +* §3.1 Names and order of of worksheets *--------------------------------------------------------------------* lo_node ?= lo_workbook->find_from_name( 'sheet' ). lv_workbook_index = 1. @@ -8192,7 +20703,7 @@ endmethod. " ins issue#284 *--------------------------------------------------------------------* * #229: Set active worksheet - begin coding -* §3.2 Active worksheet +* §3.2 Active worksheet *--------------------------------------------------------------------* lv_zexcel_active_worksheet = 1. " First sheet = active sheet if nothing else specified. lo_node ?= lo_workbook->find_from_name( 'workbookView' ). @@ -8210,7 +20721,7 @@ endmethod. *--------------------------------------------------------------------* -* §3.3 Defined names +* §3.3 Defined names * So far I have encountered these * - named ranges - sheetlocal * - named ranges - workbookglobal @@ -8331,16 +20842,16 @@ endmethod. ENDWHILE. -ENDMETHOD. + endmethod. - METHOD load_worksheet. + method LOAD_WORKSHEET. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Header/footer +* 2do§1 Header/footer * * Please don't just delete these ToDos if they are not * needed but leave a comment that states this @@ -8348,7 +20859,7 @@ ENDMETHOD. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, +* - Stefan Schmöcker, * - ... * changes: renaming variables to naming conventions * aligning code (started) @@ -8519,7 +21030,7 @@ ENDMETHOD. *--------------------------------------------------------------------* -* §2 We need to read the the file "\\_rels\.rels" because it tells +* §2 We need to read the the file "\\_rels\.rels" because it tells * us where in this folder structure the data for the workbook * is located in the xlsx zip-archive * @@ -8918,7 +21429,7 @@ ENDMETHOD. ls_odd_footer-left_value = lo_ixml_hf_value_elem->get_value( ). ENDIF. -* 2do§1 Header/footer +* 2do§1 Header/footer " TODO.. get the rest. io_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_odd_header @@ -8955,7 +21466,7 @@ ENDMETHOD. ENDIF. " End fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 -ENDMETHOD. + endmethod. @@ -9025,11 +21536,6 @@ ENDMETHOD. path2 = path. zcl_excel_common=>split_file( EXPORTING ip_file = path2 IMPORTING ep_extension = file_ext2 ). -* CALL FUNCTION 'CV120_SPLIT_FILE' -* EXPORTING -* pf_file = path2 -* IMPORTING -* pfx_extension = file_ext2. rel_drawing-file_ext = file_ext2. "-------------Added by Alessandro Iannacci - Should load graph xml @@ -9079,7 +21585,110 @@ ENDMETHOD. ENDDO. -endmethod. + endmethod. + + + + + METHOD read_from_applserver. + + DATA: lv_filelength TYPE i, + lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, + ls_binary_data LIKE LINE OF lt_binary_data, + lv_filename TYPE string, + lv_max_length_line TYPE i, + lv_actual_length_line TYPE i, + lv_errormessage TYPE string. + + MOVE i_filename TO lv_filename. + + DESCRIBE FIELD ls_binary_data LENGTH lv_max_length_line IN BYTE MODE. + OPEN DATASET lv_filename FOR INPUT IN BINARY MODE. + IF sy-subrc <> 0. + lv_errormessage = 'A problem occured when reading the file'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + WHILE sy-subrc = 0. + + READ DATASET lv_filename INTO ls_binary_data MAXIMUM LENGTH lv_max_length_line ACTUAL LENGTH lv_actual_length_line. + APPEND ls_binary_data TO lt_binary_data. + lv_filelength = lv_filelength + lv_actual_length_line. + + ENDWHILE. + CLOSE DATASET lv_filename. + +*--------------------------------------------------------------------* +* Binary data needs to be provided as XSTRING for further processing +*--------------------------------------------------------------------* + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filelength + IMPORTING + buffer = r_excel_data + TABLES + binary_tab = lt_binary_data. + ENDMETHOD. + + + + + METHOD read_from_local_file. + DATA: lv_filelength TYPE i, + lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, + ls_binary_data LIKE LINE OF lt_binary_data, + lv_filename TYPE string, + lv_errormessage TYPE string. + + MOVE i_filename TO lv_filename. + + cl_gui_frontend_services=>gui_upload( EXPORTING + filename = lv_filename + filetype = 'BIN' " We are basically working with zipped directories --> force binary read + IMPORTING + filelength = lv_filelength + CHANGING + data_tab = lt_binary_data + EXCEPTIONS + file_open_error = 1 + file_read_error = 2 + no_batch = 3 + gui_refuse_filetransfer = 4 + invalid_type = 5 + no_authority = 6 + unknown_error = 7 + bad_data_format = 8 + header_not_allowed = 9 + separator_not_allowed = 10 + header_too_long = 11 + unknown_dp_error = 12 + access_denied = 13 + dp_out_of_memory = 14 + disk_full = 15 + dp_timeout = 16 + not_supported_by_gui = 17 + error_no_gui = 18 + OTHERS = 19 ). + IF sy-subrc <> 0. + lv_errormessage = 'A problem occured when reading the file'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Binary data needs to be provided as XSTRING for further processing +*--------------------------------------------------------------------* + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filelength + IMPORTING + buffer = r_excel_data + TABLES + binary_tab = lt_binary_data. + + ENDMETHOD. @@ -9087,10 +21696,10 @@ endmethod. method RESOLVE_PATH. *--------------------------------------------------------------------* * ToDos: -* 2do§1 Determine whether the replacement should be done +* 2do§1 Determine whether the replacement should be done * iterative to allow /../../.. or something alike -* 2do§2 Determine whether /./ has to be supported as well -* 2do§3 Create unit-test for this method +* 2do§2 Determine whether /./ has to be supported as well +* 2do§3 Create unit-test for this method * * Please don't just delete these ToDos if they are not * needed but leave a comment that states this @@ -9098,14 +21707,14 @@ endmethod. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-11 +* - Stefan Schmöcker, (done) 2012-11-11 * - ... * changes: replaced previous coding by regular expression * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* *--------------------------------------------------------------------* -* §1 This routine will receive a path, that may have a relative pathname (/../) included somewhere +* §1 This routine will receive a path, that may have a relative pathname (/../) included somewhere * The output should be a resolved path without relative references * Example: Input xl/worksheets/../drawings/drawing1.xml * Output xl/drawings/drawing1.xml @@ -9113,7 +21722,7 @@ endmethod. rp_result = ip_path. *--------------------------------------------------------------------* -* §1 Remove relative pathnames +* §1 Remove relative pathnames *--------------------------------------------------------------------* * Regular expression [^/]*/\.\./ * [^/]* --> any number of characters other than / @@ -9123,10 +21732,10 @@ endmethod. REPLACE REGEX '[^/]*/\.\./' IN rp_result WITH ``. -endmethod. + endmethod. - METHOD resolve_referenced_formulae. + method RESOLVE_REFERENCED_FORMULAE. TYPES: BEGIN OF ty_referenced_cells, sheet TYPE REF TO zcl_excel_worksheet, si TYPE i, @@ -9222,7 +21831,7 @@ endmethod. ENDLOOP. ENDLOOP. -ENDMETHOD. + endmethod. @@ -9255,7 +21864,7 @@ ENDMETHOD. border_style = zcl_excel_style_border=>c_border_none. border_color-theme = zcl_excel_style_color=>c_theme_not_set. border_color-indexed = zcl_excel_style_color=>c_indexed_not_set. -endmethod. + endmethod. @@ -9267,1043 +21876,11 @@ endmethod. *"* implementation or private method's signature *"* use this source file for any macro definitions you need *"* in the implementation part of the class - CLASS lcl_excel_common_test DEFINITION DEFERRED. -CLASS zcl_excel_common DEFINITION LOCAL FRIENDS lcl_excel_common_test. - -*----------------------------------------------------------------------* -* CLASS lcl_Excel_Common_Test DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_excel_common_test DEFINITION FOR TESTING "#AU Risk_Level Harmless - . "#AU Duration Short -*?<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> -*?<asx:values> -*?<TESTCLASS_OPTIONS> -*?<TEST_CLASS>lcl_Excel_Common_Test -*?</TEST_CLASS> -*?<TEST_MEMBER>f_Cut -*?</TEST_MEMBER> -*?<OBJECT_UNDER_TEST>ZCL_EXCEL_COMMON -*?</OBJECT_UNDER_TEST> -*?<OBJECT_IS_LOCAL/> -*?<GENERATE_FIXTURE>X -*?</GENERATE_FIXTURE> -*?<GENERATE_CLASS_FIXTURE>X -*?</GENERATE_CLASS_FIXTURE> -*?<GENERATE_INVOCATION>X -*?</GENERATE_INVOCATION> -*?<GENERATE_ASSERT_EQUAL>X -*?</GENERATE_ASSERT_EQUAL> -*?</TESTCLASS_OPTIONS> -*?</asx:values> -*?</asx:abap> - PRIVATE SECTION. -* ================ - DATA: - lx_excel TYPE REF TO zcx_excel, - ls_symsg_act TYPE symsg, " actual messageinformation of exception - ls_symsg_exp TYPE symsg, " expected messageinformation of exception - f_cut TYPE REF TO zcl_excel_common. "class under test - - CLASS-METHODS: class_setup. - CLASS-METHODS: class_teardown. - METHODS: setup. - METHODS: teardown. -* METHODS: char2hex FOR TESTING. - METHODS: convert_column2alpha FOR TESTING. - METHODS: convert_column2int FOR TESTING. - METHODS: date_to_excel_string FOR TESTING. - METHODS: encrypt_password FOR TESTING. - METHODS: excel_string_to_date FOR TESTING. - METHODS: excel_string_to_time FOR TESTING. -* METHODS: number_to_excel_string FOR TESTING. - METHODS: time_to_excel_string FOR TESTING. - METHODS: split_file FOR TESTING. - METHODS: convert_range2column_a_row FOR TESTING. - METHODS: describe_structure FOR TESTING. - METHODS: calculate_cell_distance FOR TESTING. - METHODS: shift_formula FOR TESTING. -ENDCLASS. "lcl_Excel_Common_Test - - -*----------------------------------------------------------------------* -* CLASS lcl_Excel_Common_Test IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS lcl_excel_common_test IMPLEMENTATION. -* =========================================== - - METHOD class_setup. -* =================== - - - ENDMETHOD. "class_Setup - - - METHOD class_teardown. -* ====================== - - - ENDMETHOD. "class_Teardown - - - METHOD setup. -* ============= - - CREATE OBJECT f_cut. - ENDMETHOD. "setup - - - METHOD teardown. -* ================ - - - ENDMETHOD. "teardown - - - METHOD convert_column2alpha. -* ============================ - DATA ep_column TYPE zexcel_cell_column_alpha. - -* Test 1. Simple test - TRY. - ep_column = zcl_excel_common=>convert_column2alpha( 1 ). - - zcl_excel_common=>assert_equals( - act = ep_column - exp = 'A' - msg = 'Wrong column conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Max column for OXML #16,384 = XFD - TRY. - ep_column = zcl_excel_common=>convert_column2alpha( 16384 ). - - zcl_excel_common=>assert_equals( - act = ep_column - exp = 'XFD' - msg = 'Wrong column conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 3. Index 0 is out of bounds - TRY. - ep_column = zcl_excel_common=>convert_column2alpha( 0 ). - - zcl_excel_common=>assert_equals( - act = ep_column - exp = 'A' - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>assert_equals( - act = lx_excel->error - exp = 'Index out of bounds' - msg = 'Colum index 0 is out of bounds, min column index is 1' - level = if_aunit_constants=>fatal - ). - ENDTRY. - -* Test 4. Exception should be thrown index out of bounds - TRY. - ep_column = zcl_excel_common=>convert_column2alpha( 16385 ). - - zcl_excel_common=>assert_differs( - act = ep_column - exp = 'XFE' - msg = 'Colum index 16385 is out of bounds, max column index is 16384' - level = if_aunit_constants=>fatal - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>assert_equals( - act = lx_excel->error - exp = 'Index out of bounds' - msg = 'Wrong exception is thrown' - level = if_aunit_constants=>tolerable - ). - ENDTRY. - ENDMETHOD. "convert_Column2alpha - - - METHOD convert_column2int. -* ========================== - DATA ep_column TYPE zexcel_cell_column. - -* Test 1. Basic test - TRY. - ep_column = zcl_excel_common=>convert_column2int( 'A' ). - - zcl_excel_common=>assert_equals( - act = ep_column - exp = 1 - msg = 'Wrong column conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Max column - TRY. - ep_column = zcl_excel_common=>convert_column2int( 'XFD' ). - - zcl_excel_common=>assert_equals( - act = ep_column - exp = 16384 - msg = 'Wrong column conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 3. Out of bounds - TRY. - ep_column = zcl_excel_common=>convert_column2int( '' ). - - zcl_excel_common=>assert_differs( act = ep_column - exp = '0' - msg = 'Wrong column conversion' - level = if_aunit_constants=>critical ). - CATCH zcx_excel INTO lx_excel. - CLEAR: ls_symsg_act, - ls_symsg_exp. - ls_symsg_exp-msgid = 'ZABAP2XLSX'. - ls_symsg_exp-msgno = '800'. - ls_symsg_act-msgid = lx_excel->syst_at_raise-msgid. - ls_symsg_act-msgno = lx_excel->syst_at_raise-msgno. - zcl_excel_common=>assert_equals( act = ls_symsg_act - exp = ls_symsg_exp - msg = 'Colum name should be a valid string' - level = if_aunit_constants=>fatal ). - ENDTRY. - -* Test 4. Out of bounds - TRY. - ep_column = zcl_excel_common=>convert_column2int( 'XFE' ). - - zcl_excel_common=>assert_differs( act = ep_column - exp = 16385 - msg = 'Wrong column conversion' - level = if_aunit_constants=>critical ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>assert_equals( act = lx_excel->error - exp = 'Index out of bounds' - msg = 'Colum XFE is out of range' - level = if_aunit_constants=>fatal ). - ENDTRY. - ENDMETHOD. "convert_Column2int - - - METHOD date_to_excel_string. -* ============================ - DATA ep_value TYPE zexcel_cell_value. - -* Test 1. Basic conversion - TRY. - ep_value = zcl_excel_common=>date_to_excel_string( '19000101' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = 1 - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. -* Check around the "Excel Leap Year" 1900 - TRY. - ep_value = zcl_excel_common=>date_to_excel_string( '19000228' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = 59 - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - TRY. - ep_value = zcl_excel_common=>date_to_excel_string( '19000301' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = 61 - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - - -* Test 2. Basic conversion - TRY. - ep_value = zcl_excel_common=>date_to_excel_string( '99991212' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = 2958446 - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 3. Initial date - TRY. - DATA: lv_date TYPE d. - ep_value = zcl_excel_common=>date_to_excel_string( lv_date ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Basic conversion - TRY. - DATA exp_value TYPE zexcel_cell_value VALUE 0. - ep_value = zcl_excel_common=>date_to_excel_string( '18991231' ). - - zcl_excel_common=>assert_differs( - act = ep_value - exp = exp_value - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>assert_equals( - act = lx_excel->error - exp = 'Index out of bounds' - msg = 'Dates prior of 1900 are not available in excel' - level = if_aunit_constants=>critical - ). - ENDTRY. - - ENDMETHOD. "date_To_Excel_String - - - METHOD encrypt_password. -* ======================== - DATA lv_encrypted_pwd TYPE zexcel_aes_password. - - TRY. - lv_encrypted_pwd = zcl_excel_common=>encrypt_password( 'test' ). - - zcl_excel_common=>assert_equals( - act = lv_encrypted_pwd - exp = 'CBEB' - msg = 'Wrong password encryption' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - ENDMETHOD. "encrypt_Password - - - METHOD excel_string_to_date. -* ============================ - DATA ep_value TYPE d. - - -* Test 1. Simple test -> ABAP Manage also date prior of 1900 - TRY. - ep_value = zcl_excel_common=>excel_string_to_date( '0' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '18991231' - msg = 'Wrong date conversion' - level = if_aunit_constants=>tolerable - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. -* Check around the "Excel Leap Year" 1900 - TRY. - ep_value = zcl_excel_common=>excel_string_to_date( '59' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '19000228' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - TRY. - ep_value = zcl_excel_common=>excel_string_to_date( '61' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '19000301' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Simple test - TRY. - ep_value = zcl_excel_common=>excel_string_to_date( '1' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '19000101' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 3. Index 0 is out of bounds - TRY. - ep_value = zcl_excel_common=>excel_string_to_date( '2958446' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '99991212' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 4. Exception should be thrown index out of bounds - TRY. - ep_value = zcl_excel_common=>excel_string_to_date( '2958447' ). - - zcl_excel_common=>assert_differs( - act = ep_value - exp = '99991212' - msg = 'Wrong date conversion' - level = if_aunit_constants=>fatal - ). - - zcl_excel_common=>assert_differs( - act = ep_value - exp = '00000000' - msg = 'Wrong date conversion' - level = if_aunit_constants=>fatal - ). - - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>assert_equals( - act = lx_excel->error - exp = 'Index out of bounds' - msg = 'Wrong exception is thrown' - level = if_aunit_constants=>tolerable - ). - ENDTRY. - ENDMETHOD. "excel_String_To_Date - - - METHOD excel_string_to_time. -* ============================ - DATA ep_value TYPE t. - -* Test 1. Simple test - TRY. - ep_value = zcl_excel_common=>excel_string_to_time( '0' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '000000' - msg = 'Wrong date conversion' - level = if_aunit_constants=>tolerable - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Simple test - TRY. - ep_value = zcl_excel_common=>excel_string_to_time( '1' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '000000' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 3. Simple test - TRY. - ep_value = zcl_excel_common=>excel_string_to_time( '0.99999' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '235959' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 4. Also string greater than 1 should be managed - TRY. - ep_value = zcl_excel_common=>excel_string_to_time( '4.1' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '022400' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 4. string is not a number - TRY. - ep_value = zcl_excel_common=>excel_string_to_time( 'NaN' ). - - zcl_excel_common=>assert_differs( - act = ep_value - exp = '000000' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>assert_equals( - act = lx_excel->error - exp = 'Unable to interpret time' - msg = 'Time should be a valid string' - level = if_aunit_constants=>fatal - ). - ENDTRY. - ENDMETHOD. "excel_String_To_Time - - - METHOD time_to_excel_string. -* ============================ - DATA ep_value TYPE zexcel_cell_value. - -* Test 1. Basic conversion - TRY. - ep_value = zcl_excel_common=>time_to_excel_string( '000001' ). - " A test directly in Excel returns the value 0.0000115740740740741000 - zcl_excel_common=>assert_equals( - act = ep_value - exp = '0.0000115740740741' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Basic conversion - TRY. - ep_value = zcl_excel_common=>time_to_excel_string( '235959' ). - " A test directly in Excel returns the value 0.9999884259259260000000 - zcl_excel_common=>assert_equals( - act = ep_value - exp = '0.9999884259259260' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 3. Initial date - TRY. - ep_value = zcl_excel_common=>time_to_excel_string( '000000' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '0' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - -* Test 2. Basic conversion - TRY. - ep_value = zcl_excel_common=>time_to_excel_string( '022400' ). - - zcl_excel_common=>assert_equals( - act = ep_value - exp = '0.1000000000000000' - msg = 'Wrong date conversion' - level = if_aunit_constants=>critical - ). - CATCH zcx_excel INTO lx_excel. - zcl_excel_common=>fail( - msg = 'unexpected exception' - level = if_aunit_constants=>critical " Error Severity - ). - ENDTRY. - - ENDMETHOD. "time_To_Excel_String - - METHOD split_file. -* ============================ - - DATA: ep_file TYPE text255, - ep_extension TYPE char10, - ep_dotextension TYPE char10. - - -* Test 1. Basic conversion - zcl_excel_common=>split_file( EXPORTING ip_file = 'filename.xml' - IMPORTING ep_file = ep_file - ep_extension = ep_extension - ep_dotextension = ep_dotextension ). - - zcl_excel_common=>assert_equals( - act = ep_file - exp = 'filename' - msg = 'Split filename failed' - level = if_aunit_constants=>critical ). - - zcl_excel_common=>assert_equals( - act = ep_extension - exp = 'xml' - msg = 'Split extension failed' - level = if_aunit_constants=>critical ). - - zcl_excel_common=>assert_equals( - act = ep_dotextension - exp = '.xml' - msg = 'Split extension failed' - level = if_aunit_constants=>critical ). - -* Test 2. no extension - zcl_excel_common=>split_file( EXPORTING ip_file = 'filename' - IMPORTING ep_file = ep_file - ep_extension = ep_extension - ep_dotextension = ep_dotextension ). - - zcl_excel_common=>assert_equals( - act = ep_file - exp = 'filename' - msg = 'Split filename failed' - level = if_aunit_constants=>critical ). - - zcl_excel_common=>assert_equals( - act = ep_extension - exp = '' - msg = 'Split extension failed' - level = if_aunit_constants=>critical ). - - zcl_excel_common=>assert_equals( - act = ep_dotextension - exp = '' - msg = 'Split extension failed' - level = if_aunit_constants=>critical ). - - ENDMETHOD. "split_file - - METHOD convert_range2column_a_row. - DATA: lv_range TYPE string. - DATA: lv_column_start TYPE zexcel_cell_column_alpha, - lv_column_end TYPE zexcel_cell_column_alpha, - lv_row_start TYPE zexcel_cell_row, - lv_row_end TYPE zexcel_cell_row, - lv_sheet TYPE string. - -* a) input empty --> nothing to do - zcl_excel_common=>convert_range2column_a_row( - EXPORTING - i_range = lv_range - IMPORTING - e_column_start = lv_column_start " Cell Column Start - e_column_end = lv_column_end " Cell Column End - e_row_start = lv_row_start " Cell Row - e_row_end = lv_row_end " Cell Row - e_sheet = lv_sheet " Title - ). - - zcl_excel_common=>assert_equals( - act = lv_column_start - exp = '' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_column_end - exp = '' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_start - exp = '' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_end - exp = '' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_sheet - exp = '' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). -* b) sheetname existing - starts with ' example 'Sheet 1'!$B$6:$D$13 - lv_range = `'Sheet 1'!$B$6:$D$13`. - zcl_excel_common=>convert_range2column_a_row( - EXPORTING - i_range = lv_range - IMPORTING - e_column_start = lv_column_start " Cell Column Start - e_column_end = lv_column_end " Cell Column End - e_row_start = lv_row_start " Cell Row - e_row_end = lv_row_end " Cell Row - e_sheet = lv_sheet " Title - ). - - zcl_excel_common=>assert_equals( - act = lv_column_start - exp = 'B' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_column_end - exp = 'D' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_start - exp = '6' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_end - exp = '13' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_sheet - exp = 'Sheet 1' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). -* c) sheetname existing - does not start with ' example Sheet1!$B$6:$D$13 - lv_range = `Sheet1!B6:$D$13`. - zcl_excel_common=>convert_range2column_a_row( - EXPORTING - i_range = lv_range - IMPORTING - e_column_start = lv_column_start " Cell Column Start - e_column_end = lv_column_end " Cell Column End - e_row_start = lv_row_start " Cell Row - e_row_end = lv_row_end " Cell Row - e_sheet = lv_sheet " Title - ). - - zcl_excel_common=>assert_equals( - act = lv_column_start - exp = 'B' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_column_end - exp = 'D' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_start - exp = '6' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_end - exp = '13' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_sheet - exp = 'Sheet1' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). -* d) no sheetname - just area example $B$6:$D$13 - lv_range = `$B$6:D13`. - zcl_excel_common=>convert_range2column_a_row( - EXPORTING - i_range = lv_range - IMPORTING - e_column_start = lv_column_start " Cell Column Start - e_column_end = lv_column_end " Cell Column End - e_row_start = lv_row_start " Cell Row - e_row_end = lv_row_end " Cell Row - e_sheet = lv_sheet " Title - ). - - zcl_excel_common=>assert_equals( - act = lv_column_start - exp = 'B' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_column_end - exp = 'D' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_start - exp = '6' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_row_end - exp = '13' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - zcl_excel_common=>assert_equals( - act = lv_sheet - exp = '' - msg = 'Conversion of range failed' - level = if_aunit_constants=>critical ). - ENDMETHOD. "convert_range2column_a_row - - - METHOD describe_structure. - DATA: ls_test TYPE scarr. - DATA: lo_structdescr TYPE REF TO cl_abap_structdescr. - DATA: lt_structure TYPE ddfields. - FIELD-SYMBOLS: <line> LIKE LINE OF lt_structure. - - " Test with DDIC Type - lo_structdescr ?= cl_abap_structdescr=>describe_by_data( p_data = ls_test ). - lt_structure = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). - READ TABLE lt_structure ASSIGNING <line> INDEX 1. - zcl_excel_common=>assert_equals( - act = <line>-fieldname - exp = 'MANDT' - msg = 'Describe structure failed' - level = if_aunit_constants=>critical ). - - " Test with local defined structure having DDIC and non DDIC elements - TYPES: - BEGIN OF t_test, - carrid TYPE s_carr_id, - carrname TYPE s_carrname, - carrdesc TYPE string, - END OF t_test. - DATA: ls_ttest TYPE t_test. - - lo_structdescr ?= cl_abap_structdescr=>describe_by_data( p_data = ls_ttest ). - lt_structure = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). - READ TABLE lt_structure ASSIGNING <line> INDEX 1. - zcl_excel_common=>assert_equals( - act = <line>-fieldname - exp = 'CARRID' - msg = 'Describe structure failed' - level = if_aunit_constants=>critical ). - - ENDMETHOD. "describe_structure - - - METHOD calculate_cell_distance. - DATA: lv_offset_rows TYPE i, - lv_offset_cols TYPE i, - lv_message TYPE string. - - DEFINE macro_calculate_cell_distance. - zcl_excel_common=>calculate_cell_distance( exporting iv_reference_cell = &1 - iv_current_cell = &2 - importing ev_row_difference = lv_offset_rows - ev_col_difference = lv_offset_cols ). -* Check delta columns - concatenate 'Error calculating column difference in test:' - &1 - '->' - &2 - into lv_message separated by space. - zcl_excel_common=>assert_equals( act = lv_offset_cols - exp = &3 - msg = lv_message - quit = 0 " continue tests - level = if_aunit_constants=>critical ). -* Check delta rows - concatenate 'Error calculating row difference in test:' - &1 - '->' - &2 - into lv_message separated by space. - zcl_excel_common=>assert_equals( act = lv_offset_rows - exp = &4 - msg = lv_message - quit = 0 " continue tests - level = if_aunit_constants=>critical ). - END-OF-DEFINITION. - - - macro_calculate_cell_distance: - 'C12' 'C12' 0 0 , " Same cell - 'C12' 'C13' 0 1 , " Shift down 1 place - 'C12' 'C25' 0 13 , " Shift down some places - 'C12' 'C11' 0 -1 , " Shift up 1 place - 'C12' 'C1' 0 -11 , " Shift up some place - 'C12' 'D12' 1 0 , " Shift right 1 place - 'C12' 'AA12' 24 0 , " Shift right some places - 'C12' 'B12' -1 0 , " Shift left 1 place - 'AA12' 'C12' -24 0 , " Shift left some place - 'AA121' 'C12' -24 -109 . " The full package. - - ENDMETHOD. "CALCULATE_CELL_DISTANCE - - METHOD shift_formula. - DATA: lv_resulting_formula TYPE string, - lv_message TYPE string, - lv_counter TYPE num8. - - DEFINE macro_shift_formula. - add 1 to lv_counter. - clear lv_resulting_formula. - try. - lv_resulting_formula = zcl_excel_common=>shift_formula( iv_reference_formula = &1 - iv_shift_cols = &2 - iv_shift_rows = &3 ). - concatenate 'Wrong result in test' - lv_counter - 'shifting formula ' - &1 - into lv_message separated by space. - zcl_excel_common=>assert_equals( act = lv_resulting_formula - exp = &4 - msg = lv_message - quit = 0 " continue tests - level = if_aunit_constants=>critical ). - catch zcx_excel. - concatenate 'Unexpected exception occurred in test' - lv_counter - 'shifting formula ' - &1 - into lv_message separated by space. - zcl_excel_common=>assert_equals( act = lv_resulting_formula - exp = &4 - msg = lv_message - quit = 0 " continue tests - level = if_aunit_constants=>critical ). - endtry. - END-OF-DEFINITION. - -* Test shifts that should result in a valid output - macro_shift_formula: - 'C17' 0 0 'C17', " Very basic check - 'C17' 2 3 'E20', " Check shift right and down - 'C17' -2 -3 'A14', " Check shift left and up - '$C$17' 1 1 '$C$17', " Fixed columns/rows - 'SUM($C17:C$23)+C30' 1 11 'SUM($C28:D$23)+D41', " Operators and Ranges, mixed fixed rows or columns - 'RNGNAME1+C7' -1 -4 'RNGNAME1+B3', " Operators and Rangename - '"Date:"&TEXT(B2)' 1 1 '"Date:"&TEXT(C3)', " String literals and string concatenation - '[TEST6.XLSX]SHEET1!A1' 1 11 '[TEST6.XLSX]SHEET1!B12', " External sheet reference - `X(B13, "KK" ) ` 1 1 `X(C14,"KK")`, " superflous blanks, multi-argument functions, literals in function, unknown functions -* 'SIN((((((B2))))))' 1 1 'SIN((((((C3))))))', " Deep nesting -* 'SIN(SIN(SIN(SIN(E22))))' 0 1 'SIN(SIN(SIN(SIN(E23))))', " Different type of deep nesting - `SIN(SIN(SIN(SIN(E22))))` 0 1 'SIN(SIN(SIN(SIN(E23))))', " same as above - but with string input instead of Char-input - 'HEUTE()' 2 5 'HEUTE()', " Functions w/o arguments, No cellreferences - '"B2"' 2 5 '"B2"', " No cellreferences - '' 2 5 '', " Empty - 'A1+$A1+A$1+$A$1+B2' -1 0 '#REF!+$A1+#REF!+$A$1+A2', " Referencing error , column only , underflow - 'A1+$A1+A$1+$A$1+B2' 0 -1 '#REF!+#REF!+A$1+$A$1+B1', " Referencing error , row only , underflow - 'A1+$A1+A$1+$A$1+B2' -1 -1 '#REF!+#REF!+#REF!+$A$1+A1'. " Referencing error , row and column , underflow - ENDMETHOD. "SHIFT_FORMULA - - - - - -ENDCLASS. "lcl_Excel_Common_Test + *"* use this source file for your ABAP unit test classes - + @@ -10373,7 +21950,7 @@ ENDCLASS. "lcl_Excel_Common_Test * We do nothing for now not supported ENDIF. ENDIF. -endmethod. + endmethod. @@ -10384,7 +21961,7 @@ endmethod. - METHOD assert_equals. + method ASSERT_EQUALS. DATA: ls_seoclass TYPE seoclass. " Let see >=7.02 @@ -10426,7 +22003,7 @@ endmethod. * We do nothing for now not supported ENDIF. ENDIF. -ENDMETHOD. + endmethod. @@ -10434,7 +22011,7 @@ ENDMETHOD. - METHOD calculate_cell_distance. + method CALCULATE_CELL_DISTANCE. DATA: lv_reference_row TYPE i, lv_reference_col_alpha TYPE zexcel_cell_column_alpha, @@ -10473,7 +22050,7 @@ ENDMETHOD. ev_row_difference = lv_current_row - lv_reference_row. ev_col_difference = lv_current_col - lv_reference_col. -ENDMETHOD. + endmethod. @@ -10490,13 +22067,13 @@ ENDMETHOD. CALL METHOD o_conv->write( data = i_char ). r_hex+1 = o_conv->get_buffer( ). " x'65' must be x'0065' -endmethod. + endmethod. - METHOD convert_column2alpha. + method CONVERT_COLUMN2ALPHA. DATA: lv_uccpi TYPE i, lv_text TYPE sychar02, @@ -10531,17 +22108,17 @@ endmethod. ENDWHILE. -ENDMETHOD. + endmethod. - METHOD convert_column2int. + method CONVERT_COLUMN2INT. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-12-29 +* - Stefan Schmöcker, (done) 2012-12-29 * - ... * changes: renaming variables to naming conventions * removing unused variables @@ -10550,7 +22127,7 @@ ENDMETHOD. * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* * issue#246 - error converting lower case column names -* - Stefan Schmöcker, 2012-12-29 +* - Stefan Schmöcker, 2012-12-29 * changes: translating the correct variable to upper dase * adding missing exception if input is a number * that is out of bounds @@ -10690,7 +22267,7 @@ ENDMETHOD. ENDIF. -ENDMETHOD. + endmethod. @@ -10700,7 +22277,7 @@ ENDMETHOD. *--------------------------------------------------------------------* "issue #256 - replacing char processing with regex *--------------------------------------------------------------------* -* Stefan Schmöcker, 2013-08-11 +* Stefan Schmöcker, 2013-08-11 * Allow input to be CLIKE instead of STRING *--------------------------------------------------------------------* @@ -10713,7 +22290,7 @@ ENDMETHOD. pane_cell_row_a. e_row = pane_cell_row_a. -endmethod. + endmethod. @@ -10726,7 +22303,7 @@ endmethod. method CONVERT_RANGE2COLUMN_A_ROW. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-12-07 +* - Stefan Schmöcker, (done) 2012-12-07 * - ... * changes: renaming variables to naming conventions * aligning code @@ -10736,12 +22313,12 @@ endmethod. *--------------------------------------------------------------------* * issue#241 - error when sheetname contains "!" * - sheetname should be returned unescaped -* - Stefan Schmöcker, 2012-12-07 +* - Stefan Schmöcker, 2012-12-07 * changes: changed coding to support sheetnames with "!" * unescaping sheetname *--------------------------------------------------------------------* * issue#155 - lessening restrictions of input parameters -* - Stefan Schmöcker, 2012-12-07 +* - Stefan Schmöcker, 2012-12-07 * changes: i_range changed to clike * e_sheet changed to clike *--------------------------------------------------------------------* @@ -10806,7 +22383,7 @@ endmethod. e_row = e_row_end ). e_sheet = unescape_string( lv_sheet ). " Return in unescaped form -endmethod. + endmethod. @@ -10824,7 +22401,7 @@ endmethod. lv_date_diff = ip_value - c_excel_baseline_date + 1. ENDIF. ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_date_diff ). -endmethod. + endmethod. @@ -10875,11 +22452,11 @@ endmethod. ENDIF. ENDLOOP. ENDIF. -endmethod. + endmethod. method DESCRIBE_TABLE. -endmethod. + endmethod. @@ -10887,7 +22464,7 @@ endmethod. - METHOD determine_resulting_formula. + method DETERMINE_RESULTING_FORMULA. DATA: lv_row_difference TYPE i, lv_col_difference TYPE i. @@ -10909,7 +22486,7 @@ endmethod. iv_shift_rows = lv_row_difference iv_shift_cols = lv_col_difference ). -ENDMETHOD. "determine_resulting_formula + endmethod. @@ -10951,7 +22528,7 @@ ENDMETHOD. "determine_resulting_formula WRITE lv_pwd_hash TO r_encrypted_pwd. -endmethod. + endmethod. @@ -10959,19 +22536,19 @@ endmethod. method ESCAPE_STRING. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-12-08 +* - Stefan Schmöcker, (done) 2012-12-08 * - ... * changes: aligning code * adding comments to explain what we are trying to achieve *--------------------------------------------------------------------* * issue#242 - Support escaping for white-spaces * - Escaping also necessary when ' encountered in input -* - Stefan Schmöcker, 2012-12-08 +* - Stefan Schmöcker, 2012-12-08 * changes: switched check if escaping is necessary to regular expression * and moved the "REPLACE" *--------------------------------------------------------------------* * issue#155 - lessening restrictions of input parameters -* - Stefan Schmöcker, 2012-12-08 +* - Stefan Schmöcker, 2012-12-08 * changes: ip_value changed to clike *--------------------------------------------------------------------* DATA: lv_value TYPE string. @@ -11002,7 +22579,7 @@ endmethod. ep_escaped_value = lv_value. -endmethod. + endmethod. @@ -11025,7 +22602,7 @@ endmethod. EXPORTING error = 'Index out of bounds'. ENDTRY. -endmethod. + endmethod. @@ -11048,7 +22625,7 @@ endmethod. EXPORTING error = 'Unable to interpret time'. ENDTRY. -endmethod. + endmethod. @@ -11088,7 +22665,7 @@ endmethod. ENDIF. ENDIF. -endmethod. + endmethod. @@ -11149,7 +22726,7 @@ endmethod. ENDLOOP. -endmethod. + endmethod. @@ -11168,7 +22745,7 @@ endmethod. ELSEIF ip_value EQ 0. ep_value = '0'. ENDIF. -endmethod. + endmethod. @@ -11227,7 +22804,7 @@ endmethod. ENDCASE. ENDLOOP. -endmethod. + endmethod. @@ -11291,7 +22868,7 @@ endmethod. ENDCASE. ENDLOOP. -endmethod. + endmethod. @@ -11299,7 +22876,7 @@ endmethod. - METHOD shift_formula. + method SHIFT_FORMULA. CONSTANTS: lcv_operators TYPE string VALUE '+-/*^%=<>&, !', lcv_letters TYPE string VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ$', @@ -11336,10 +22913,10 @@ endmethod. * are copied as well. Cell-references in the formula are being adjusted * by the distance of the new cell to the original one *--------------------------------------------------------------------* -* §1 Parse reference formula character by character -* §2 Identify Cell-references -* §3 Shift cell-reference -* §4 Build resulting formula +* §1 Parse reference formula character by character +* §2 Identify Cell-references +* §3 Shift cell-reference +* §4 Build resulting formula *--------------------------------------------------------------------* *--------------------------------------------------------------------* @@ -11356,7 +22933,7 @@ endmethod. lv_numchars = 1. *--------------------------------------------------------------------* -* §1 Parse reference formula character by character +* §1 Parse reference formula character by character *--------------------------------------------------------------------* DO lv_flen TIMES. @@ -11632,7 +23209,7 @@ endmethod. MOVE lv_cur_form TO ev_resulting_formula. ENDIF. -ENDMETHOD. + endmethod. @@ -11652,7 +23229,7 @@ ENDMETHOD. ENDDO. SET BIT 16 OF r_pwd_hash TO 0. -endmethod. + endmethod. @@ -11679,7 +23256,7 @@ endmethod. SET BIT 1 OF r_pwd_hash TO 0. ENDDO. -endmethod. + endmethod. @@ -11727,7 +23304,7 @@ endmethod. ep_file = ip_file(lf_len). ENDIF. -endmethod. + endmethod. @@ -11746,7 +23323,7 @@ endmethod. WHEN OTHERS. "cl_abap_typedescr=>kind_ref or cl_abap_typedescr=>kind_class or cl_abap_typedescr=>kind_intf. * We skip it. for now. ENDCASE. -endmethod. + endmethod. @@ -11766,7 +23343,7 @@ endmethod. CHANGING xt_components = rt_components ) . ENDLOOP. -endmethod. + endmethod. @@ -11780,7 +23357,7 @@ endmethod. lv_seconds_in_day = ip_value - lc_time_baseline. lv_day_fraction = lv_seconds_in_day / lc_seconds_in_day. ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_day_fraction ). -endmethod. + endmethod. @@ -11840,13 +23417,13 @@ endmethod. REPLACE ALL OCCURRENCES OF `''` IN ev_unescaped_string WITH `'`. -endmethod. + endmethod. - - - + + + *"* local class implementation for public class *"* use this source file for the implementation part of *"* local helper classes @@ -11855,106 +23432,6 @@ endmethod. *"* implementation or private method's signature *"* use this source file for any macro definitions you need *"* in the implementation part of the class - CLASS zcl_tc_excel DEFINITION DEFERRED. -CLASS zcl_excel DEFINITION LOCAL FRIENDS zcl_tc_excel. - -*----------------------------------------------------------------------* -* CLASS zcl_Tc_Excel DEFINITION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS zcl_tc_excel DEFINITION FOR TESTING - DURATION SHORT - RISK LEVEL HARMLESS -. -*?<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> -*?<asx:values> -*?<TESTCLASS_OPTIONS> -*?<TEST_CLASS>zcl_Tc_Excel -*?</TEST_CLASS> -*?<TEST_MEMBER>f_Cut -*?</TEST_MEMBER> -*?<OBJECT_UNDER_TEST>ZCL_EXCEL -*?</OBJECT_UNDER_TEST> -*?<OBJECT_IS_LOCAL/> -*?<GENERATE_FIXTURE>X -*?</GENERATE_FIXTURE> -*?<GENERATE_CLASS_FIXTURE>X -*?</GENERATE_CLASS_FIXTURE> -*?<GENERATE_INVOCATION>X -*?</GENERATE_INVOCATION> -*?<GENERATE_ASSERT_EQUAL>X -*?</GENERATE_ASSERT_EQUAL> -*?</TESTCLASS_OPTIONS> -*?</asx:values> -*?</asx:abap> - PRIVATE SECTION. -* ================ - DATA: - f_cut TYPE REF TO zcl_excel. "class under test - - CLASS-METHODS: class_setup. - CLASS-METHODS: class_teardown. - METHODS: setup. - METHODS: teardown. - METHODS: create_empty_excel FOR TESTING. - -ENDCLASS. "zcl_Tc_Excel - - -*----------------------------------------------------------------------* -* CLASS zcl_Tc_Excel IMPLEMENTATION -*----------------------------------------------------------------------* -* -*----------------------------------------------------------------------* -CLASS zcl_tc_excel IMPLEMENTATION. -* ================================== - - METHOD class_setup. -* =================== - - - ENDMETHOD. "class_Setup - - - METHOD class_teardown. -* ====================== - - - ENDMETHOD. "class_Teardown - - - METHOD setup. -* ============= - - CREATE OBJECT f_cut. - ENDMETHOD. "setup - - - METHOD teardown. -* ================ - - - ENDMETHOD. "teardown - -*// START TEST METHODS - - METHOD create_empty_excel. -* ================================== - - DATA: lv_count TYPE i. - lv_count = f_cut->get_worksheets_size( ). - - cl_abap_unit_assert=>assert_equals( act = lv_count - exp = 1 - msg = 'Testing number of sheet' - level = if_aunit_constants=>tolerable ). - ENDMETHOD. "create_empty_excel - -*// END TEST METHODS - - -ENDCLASS. "zcl_Tc_Excel @@ -11979,7 +23456,7 @@ ENDCLASS. "zcl_Tc_Excel me->zif_excel_book_properties~creator = sy-uname. me->zif_excel_book_properties~modified = lv_timestamp. me->zif_excel_book_properties~lastmodifiedby = sy-uname. -endmethod. + endmethod. method ZIF_EXCEL_BOOK_PROTECTION~INITIALIZE. @@ -11989,22 +23466,22 @@ endmethod. me->zif_excel_book_protection~lockwindows = zif_excel_book_protection=>c_unlocked. CLEAR me->zif_excel_book_protection~workbookpassword. CLEAR me->zif_excel_book_protection~revisionspassword. -endmethod. + endmethod. method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_CODENAME. me->zif_excel_book_vba_project~codename = ip_codename. -endmethod. + endmethod. method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_CODENAME_PR. me->zif_excel_book_vba_project~codename_pr = ip_codename_pr. -endmethod. + endmethod. method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_VBAPROJECT. me->zif_excel_book_vba_project~vbaproject = ip_vbaproject. -endmethod. + endmethod. @@ -12012,7 +23489,7 @@ endmethod. method ADD_NEW_AUTOFILTER. * Check for autofilter reference: new or overwrite; only one per sheet ro_autofilter = autofilters->add( io_sheet = io_sheet ) . -endmethod. + endmethod. @@ -12032,7 +23509,7 @@ endmethod. WHEN 'chart'. charts->add( eo_drawing ). ENDCASE. -endmethod. + endmethod. @@ -12040,7 +23517,7 @@ endmethod. * Create default blank range CREATE OBJECT eo_range. ranges->add( eo_range ). -endmethod. + endmethod. @@ -12064,13 +23541,13 @@ endmethod. INSERT style2 INTO TABLE t_stylemapping2. * End of insertion # issue 139 - Dateretention of cellstyles -endmethod. + endmethod. - METHOD add_new_worksheet. + method ADD_NEW_WORKSHEET. DATA: lv_guid TYPE guid_16. * Create default blank worksheet @@ -12081,16 +23558,16 @@ endmethod. worksheets->add( eo_worksheet ). worksheets->active_worksheet = worksheets->size( ). -ENDMETHOD. + endmethod. method ADD_STATIC_STYLES. " # issue 139 -* sp#ƒÂ¤ter hier noch die Worksheets abklappern, welche Styles #ƒÂ#berhaupt noch ben#ƒÂ#tigt werden -* und nur diese dann auch hier zur Verf#ƒÂ#gung stellen +* sp#ƒÂ¤ter hier noch die Worksheets abklappern, welche Styles #ƒÂ#berhaupt noch ben#ƒÂ#tigt werden +* und nur diese dann auch hier zur Verf#ƒÂ#gung stellen * Da muss ich noch mal nachfragen, ob die beiden ersten Styles, die scheinbar immer mit dem -* EXCEL-Objekt erzeugt werden evtl. immer ben#ƒÂ#tigt werden, egal ob verwendet oder nicht -* Aber als Start fange ich mal an einfach alle static styles der Reihe nach hinzuzuf#ƒÂ#gen +* EXCEL-Objekt erzeugt werden evtl. immer ben#ƒÂ#tigt werden, egal ob verwendet oder nicht +* Aber als Start fange ich mal an einfach alle static styles der Reihe nach hinzuzuf#ƒÂ#gen FIELD-SYMBOLS: <style1> LIKE LINE OF t_stylemapping1, <style2> LIKE LINE OF t_stylemapping2. DATA: style TYPE REF TO zcl_excel_style. @@ -12106,7 +23583,7 @@ ENDMETHOD. CHANGING e_target = style ). ENDLOOP. -endmethod. + endmethod. method CONSTRUCTOR. @@ -12135,13 +23612,13 @@ endmethod. lo_style = me->add_new_style( ). " Standard style with fill gray125 lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_pattern_gray125. -endmethod. + endmethod. method GET_ACTIVE_SHEET_INDEX. r_active_worksheet = me->worksheets->active_worksheet. -endmethod. + endmethod. @@ -12149,7 +23626,7 @@ endmethod. eo_worksheet = me->worksheets->get( me->worksheets->active_worksheet ). -endmethod. + endmethod. @@ -12157,13 +23634,13 @@ endmethod. ro_autofilters = autofilters. -endmethod. + endmethod. method GET_DEFAULT_STYLE. ep_style = me->default_style. -endmethod. + endmethod. @@ -12178,7 +23655,7 @@ endmethod. WHEN OTHERS. ENDCASE. -endmethod. + endmethod. @@ -12198,7 +23675,7 @@ endmethod. ADD 1 TO ep_id. -endmethod. + endmethod. @@ -12206,7 +23683,7 @@ endmethod. eo_iterator = me->ranges->get_iterator( ). -endmethod. + endmethod. @@ -12232,7 +23709,7 @@ endmethod. ENDIF. ep_guid = style-guid. -endmethod. + endmethod. @@ -12240,7 +23717,7 @@ endmethod. eo_iterator = me->styles->get_iterator( ). -endmethod. + endmethod. @@ -12271,7 +23748,7 @@ endmethod. else. SUBTRACT 1 from ep_index. " In excel list starts with "0" ENDIF. -endmethod. + endmethod. @@ -12294,7 +23771,7 @@ endmethod. ENDIF. -endmethod. + endmethod. @@ -12302,7 +23779,7 @@ endmethod. eo_iterator = me->worksheets->get_iterator( ). -endmethod. + endmethod. @@ -12310,7 +23787,7 @@ endmethod. ep_name = me->worksheets->name. -endmethod. + endmethod. @@ -12318,7 +23795,7 @@ endmethod. ep_size = me->worksheets->size( ). -endmethod. + endmethod. @@ -12340,13 +23817,13 @@ endmethod. CLEAR eo_worksheet. -endmethod. + endmethod. method SET_ACTIVE_SHEET_INDEX. me->worksheets->active_worksheet = i_active_worksheet. -endmethod. + endmethod. @@ -12369,14 +23846,14 @@ endmethod. count = count + 1. ENDWHILE. -endmethod. + endmethod. method SET_DEFAULT_STYLE. me->default_style = ip_style. -endmethod. + endmethod. @@ -12391,16 +23868,16 @@ endmethod. * don't care about attributes here, since this data may change * dynamically -endmethod. + endmethod. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -12715,7 +24192,7 @@ endmethod. - METHOD create_serie. + method CREATE_SERIE. DATA ls_serie TYPE s_series. DATA: lv_start_row_c TYPE char7, @@ -12758,22 +24235,22 @@ endmethod. ls_serie-sername = ip_sername. APPEND ls_serie TO me->series. SORT me->series BY order ASCENDING. -ENDMETHOD. + endmethod. method SET_PRINT_LBL. me->print_label = ip_value. -endmethod. + endmethod. - METHOD set_style. + method SET_STYLE. me->ns_c14styleval = ip_style-c14style. CONDENSE me->ns_c14styleval NO-GAPS. me->ns_styleval = ip_style-cstyle. CONDENSE me->ns_styleval NO-GAPS. -ENDMETHOD. + endmethod. @@ -12801,49 +24278,49 @@ ENDMETHOD. - METHOD set_show_cat_name. + method SET_SHOW_CAT_NAME. ns_showcatnameval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_leader_lines. + method SET_SHOW_LEADER_LINES. ns_showleaderlinesval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_legend_key. + method SET_SHOW_LEGEND_KEY. ns_showlegendkeyval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_percent. + method SET_SHOW_PERCENT. ns_showpercentval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_ser_name. + method SET_SHOW_SER_NAME. ns_showsernameval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_values. + method SET_SHOW_VALUES. ns_showvalval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_varycolor. + method SET_VARYCOLOR. ns_varycolorsval = ip_value. -ENDMETHOD. + endmethod. - - *"* use this source file for the definition and implementation of *"* local helper classes, interface definitions and type @@ -12874,11 +24351,11 @@ ENDMETHOD. *"* use this source file for any macro definitions you need *"* in the implementation part of the class - - @@ -12911,7 +24388,7 @@ ENDMETHOD. - METHOD create_ax. + method CREATE_AX. DATA ls_ax TYPE s_ax. ls_ax-type = ip_type. @@ -13056,12351 +24533,86 @@ ENDMETHOD. APPEND ls_ax TO me->axes. sort me->axes by axid ascending. -ENDMETHOD. + endmethod. - METHOD set_show_cat_name. + method SET_SHOW_CAT_NAME. ns_showcatnameval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_legend_key. + method SET_SHOW_LEGEND_KEY. ns_showlegendkeyval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_percent. + method SET_SHOW_PERCENT. ns_showpercentval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_ser_name. + method SET_SHOW_SER_NAME. ns_showsernameval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_show_values. + method SET_SHOW_VALUES. ns_showvalval = ip_value. -ENDMETHOD. + endmethod. - METHOD set_varycolor. + method SET_VARYCOLOR. ns_varycolorsval = ip_value. -ENDMETHOD. + endmethod. - - - - *"* use this source file for the definition and implementation of -*"* local helper classes, interface definitions and type -*"* declarations - *"* use this source file for any type of declarations (class -*"* definitions, interfaces or type declarations) you need for -*"* components in the private section - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - METHOD create_ax. - DATA ls_ax TYPE s_ax. - ls_ax-type = ip_type. - - IF ip_type = c_catax. - IF ip_axid IS SUPPLIED. - ls_ax-axid = ip_axid. - ELSE. - ls_ax-axid = '1'. - ENDIF. - IF ip_orientation IS SUPPLIED. - ls_ax-orientation = ip_orientation. - ELSE. - ls_ax-orientation = 'minMax'. - ENDIF. - IF ip_delete IS SUPPLIED. - ls_ax-delete = ip_delete. - ELSE. - ls_ax-delete = '0'. - ENDIF. - IF ip_axpos IS SUPPLIED. - ls_ax-axpos = ip_axpos. - ELSE. - ls_ax-axpos = 'b'. - ENDIF. - IF ip_formatcode IS SUPPLIED. - ls_ax-formatcode = ip_formatcode. - ELSE. - ls_ax-formatcode = 'General'. - ENDIF. - IF ip_sourcelinked IS SUPPLIED. - ls_ax-sourcelinked = ip_sourcelinked. - ELSE. - ls_ax-sourcelinked = '1'. - ENDIF. - IF ip_majortickmark IS SUPPLIED. - ls_ax-majortickmark = ip_majortickmark. - ELSE. - ls_ax-majortickmark = 'out'. - ENDIF. - IF ip_minortickmark IS SUPPLIED. - ls_ax-minortickmark = ip_minortickmark. - ELSE. - ls_ax-minortickmark = 'none'. - ENDIF. - IF ip_ticklblpos IS SUPPLIED. - ls_ax-ticklblpos = ip_ticklblpos. - ELSE. - ls_ax-ticklblpos = 'nextTo'. - ENDIF. - IF ip_crossax IS SUPPLIED. - ls_ax-crossax = ip_crossax. - ELSE. - ls_ax-crossax = '2'. - ENDIF. - IF ip_crosses IS SUPPLIED. - ls_ax-crosses = ip_crosses. - ELSE. - ls_ax-crosses = 'autoZero'. - ENDIF. - IF ip_auto IS SUPPLIED. - ls_ax-auto = ip_auto. - ELSE. - ls_ax-auto = '1'. - ENDIF. - IF ip_lblalgn IS SUPPLIED. - ls_ax-lblalgn = ip_lblalgn. - ELSE. - ls_ax-lblalgn = 'ctr'. - ENDIF. - IF ip_lbloffset IS SUPPLIED. - ls_ax-lbloffset = ip_lbloffset. - ELSE. - ls_ax-lbloffset = '100'. - ENDIF. - IF ip_nomultilvllbl IS SUPPLIED. - ls_ax-nomultilvllbl = ip_nomultilvllbl. - ELSE. - ls_ax-nomultilvllbl = '0'. - ENDIF. - ELSEIF ip_type = c_valax. - IF ip_axid IS SUPPLIED. - ls_ax-axid = ip_axid. - ELSE. - ls_ax-axid = '2'. - ENDIF. - IF ip_orientation IS SUPPLIED. - ls_ax-orientation = ip_orientation. - ELSE. - ls_ax-orientation = 'minMax'. - ENDIF. - IF ip_delete IS SUPPLIED. - ls_ax-delete = ip_delete. - ELSE. - ls_ax-delete = '0'. - ENDIF. - IF ip_axpos IS SUPPLIED. - ls_ax-axpos = ip_axpos. - ELSE. - ls_ax-axpos = 'l'. - ENDIF. - IF ip_formatcode IS SUPPLIED. - ls_ax-formatcode = ip_formatcode. - ELSE. - ls_ax-formatcode = 'General'. - ENDIF. - IF ip_sourcelinked IS SUPPLIED. - ls_ax-sourcelinked = ip_sourcelinked. - ELSE. - ls_ax-sourcelinked = '1'. - ENDIF. - IF ip_majortickmark IS SUPPLIED. - ls_ax-majortickmark = ip_majortickmark. - ELSE. - ls_ax-majortickmark = 'out'. - ENDIF. - IF ip_minortickmark IS SUPPLIED. - ls_ax-minortickmark = ip_minortickmark. - ELSE. - ls_ax-minortickmark = 'none'. - ENDIF. - IF ip_ticklblpos IS SUPPLIED. - ls_ax-ticklblpos = ip_ticklblpos. - ELSE. - ls_ax-ticklblpos = 'nextTo'. - ENDIF. - IF ip_crossax IS SUPPLIED. - ls_ax-crossax = ip_crossax. - ELSE. - ls_ax-crossax = '1'. - ENDIF. - IF ip_crosses IS SUPPLIED. - ls_ax-crosses = ip_crosses. - ELSE. - ls_ax-crosses = 'autoZero'. - ENDIF. - IF ip_crossbetween IS SUPPLIED. - ls_ax-crossbetween = ip_crossbetween. - ELSE. - ls_ax-crossbetween = 'between'. - ENDIF. - ENDIF. - - APPEND ls_ax TO me->axes. - SORT me->axes BY axid ASCENDING. -ENDMETHOD. - - - - METHOD SET_SHOW_CAT_NAME. - ns_showcatnameval = ip_value. -ENDMETHOD. - - - - METHOD SET_SHOW_LEGEND_KEY. - ns_showlegendkeyval = ip_value. -ENDMETHOD. - - - - METHOD SET_SHOW_PERCENT. - ns_showpercentval = ip_value. -ENDMETHOD. - - - - METHOD SET_SHOW_SER_NAME. - ns_showsernameval = ip_value. -ENDMETHOD. - - - - METHOD SET_SHOW_VALUES. - ns_showvalval = ip_value. -ENDMETHOD. - - - - METHOD set_varycolor. - ns_varycolorsval = ip_value. -ENDMETHOD. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - " Initialise instance variables - formula1 = ''. - formula2 = ''. - type = me->c_type_none. - errorstyle = me->c_style_stop. - operator = ''. - allowblank = abap_false. - showdropdown = abap_false. - showinputmessage = abap_true. - showerrormessage = abap_true. - errortitle = ''. - error = ''. - prompttitle = ''. - prompt = ''. -* inizialize dimension range - cell_row = 1. - cell_column = 'A'. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - method ADD. - data_validations->add( ip_data_validation ). -endmethod. - - - method CLEAR. - data_validations->clear( ). -endmethod. - - - method CONSTRUCTOR. - - CREATE OBJECT data_validations. - -endmethod. - - - - method GET_ITERATOR. - eo_iterator ?= data_validations->if_object_collection~get_iterator( ). -endmethod. - - - - method IS_EMPTY. - is_empty = data_validations->if_object_collection~is_empty( ). -endmethod. - - - - method REMOVE. - data_validations->remove( ip_data_validation ). -endmethod. - - - - method SIZE. - ep_size = data_validations->if_object_collection~size( ). -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - - CALL FUNCTION 'GUID_CREATE' - IMPORTING - ev_guid_16 = me->guid. - - IF ip_title IS NOT INITIAL. - title = ip_title. - ELSE. - title = me->guid. - ENDIF. - - me->type = ip_type. - -* inizialize dimension range - anchor = anchor_one_cell. - from_loc-col = 1. - from_loc-row = 1. -endmethod. - - - - method CREATE_MEDIA_NAME. - -* if media name is initial, create unique name - CHECK media_name IS INITIAL. - - index = ip_index. - CONCATENATE me->type index INTO media_name. - CONDENSE media_name NO-GAPS. -endmethod. - - - - method GET_FROM_COL. - r_from_col = me->from_loc-col. -endmethod. - - - - method GET_FROM_ROW. - r_from_row = me->from_loc-row. -endmethod. - - - - method GET_GUID. - - ep_guid = me->guid. - -endmethod. - - - - method GET_HEIGHT_EMU_STR. - r_height = pixel2emu( size-height ). - CONDENSE r_height NO-GAPS. -endmethod. - - - - method GET_INDEX. - rp_index = me->index. -endmethod. - - - - method GET_MEDIA. - CASE media_source. - WHEN c_media_source_xstring. - r_media = media. - WHEN c_media_source_www. - DATA: lt_mime TYPE tsfmime, - lv_filesize TYPE i, - lv_filesizec(10). - - CALL FUNCTION 'WWWDATA_IMPORT' - EXPORTING - key = media_key_www - TABLES - mime = lt_mime - EXCEPTIONS - OTHERS = 1. - - CALL FUNCTION 'WWWPARAMS_READ' - EXPORTING - relid = media_key_www-relid - objid = media_key_www-objid - name = 'filesize' - IMPORTING - value = lv_filesizec. - - lv_filesize = lv_filesizec. - CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' - EXPORTING - input_length = lv_filesize - IMPORTING - buffer = r_media - TABLES - binary_tab = lt_mime - EXCEPTIONS - failed = 1 - OTHERS = 2. - WHEN c_media_source_mime. - DATA: lt_bin_mime TYPE sdokcntbins. - cl_wb_mime_repository=>load_mime( EXPORTING - io = me->io - IMPORTING - filesize = lv_filesize - bin_data = lt_bin_mime - CHANGING - language = sy-langu ). - - CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' - EXPORTING - input_length = lv_filesize - IMPORTING - buffer = r_media - TABLES - binary_tab = lt_bin_mime - EXCEPTIONS - failed = 1 - OTHERS = 2. - ENDCASE. -endmethod. - - - - method GET_MEDIA_NAME. - CONCATENATE media_name `.` media_type INTO r_name. -endmethod. - - - - method GET_MEDIA_TYPE. - r_type = media_type. -endmethod. - - - - method GET_NAME. - r_name = title. -endmethod. - - - - method GET_POSITION. - rp_position-anchor = anchor. - rp_position-from = from_loc. - rp_position-to = to_loc. - rp_position-size = size. -endmethod. - - - - method GET_TO_COL. - r_to_col = me->to_loc-col. -endmethod. - - - - method GET_TO_ROW. - r_to_row = me->to_loc-row. -endmethod. - - - - method GET_TYPE. - rp_type = me->type. -endmethod. - - - - method GET_WIDTH_EMU_STR. - r_width = pixel2emu( size-width ). - CONDENSE r_width NO-GAPS. -endmethod. - - - - METHOD load_chart_attributes. - DATA: node TYPE REF TO if_ixml_element. - DATA: node2 TYPE REF TO if_ixml_element. - DATA: node3 TYPE REF TO if_ixml_element. - DATA: node4 TYPE REF TO if_ixml_element. - DATA: iterator TYPE REF TO if_ixml_node_iterator. - - DATA: chartspace TYPE REF TO if_ixml_node_collection. - DATA: coll_length TYPE i. - DATA: chartelem TYPE REF TO if_ixml_element. - - DATA lo_barchart TYPE REF TO zcl_excel_graph_bars. - DATA lo_piechart TYPE REF TO zcl_excel_graph_pie. - DATA lo_linechart TYPE REF TO zcl_excel_graph_line. - - TYPES: BEGIN OF t_prop, - val TYPE string, - rtl TYPE string, - lang TYPE string, - formatcode TYPE string, - sourcelinked TYPE string, - END OF t_prop. - - TYPES: BEGIN OF t_pagemargins, - b TYPE string, - l TYPE string, - r TYPE string, - t TYPE string, - header TYPE string, - footer TYPE string, - END OF t_pagemargins. - - DATA ls_prop TYPE t_prop. - DATA ls_pagemargins TYPE t_pagemargins. - - DATA lo_collection TYPE REF TO if_ixml_node_collection. - DATA lo_node TYPE REF TO if_ixml_node. - DATA lo_iterator TYPE REF TO if_ixml_node_iterator. - DATA lv_idx TYPE i. - DATA lv_order TYPE i. - DATA lv_invertifnegative TYPE string. - DATA lv_symbol TYPE string. - DATA lv_smooth TYPE c. - DATA lv_sername TYPE string. - DATA lv_label TYPE string. - DATA lv_value TYPE string. - DATA lv_axid TYPE string. - DATA lv_orientation TYPE string. - DATA lv_delete TYPE string. - DATA lv_axpos TYPE string. - DATA lv_formatcode TYPE string. - DATA lv_sourcelinked TYPE string. - DATA lv_majortickmark TYPE string. - DATA lv_minortickmark TYPE string. - DATA lv_ticklblpos TYPE string. - DATA lv_crossax TYPE string. - DATA lv_crosses TYPE string. - DATA lv_auto TYPE string. - DATA lv_lblalgn TYPE string. - DATA lv_lbloffset TYPE string. - DATA lv_nomultilvllbl TYPE string. - DATA lv_crossbetween TYPE string. - - node ?= ip_chart->if_ixml_node~get_first_child( ). - CHECK node IS NOT INITIAL. - - CASE me->graph_type. - WHEN c_graph_bars. - CREATE OBJECT lo_barchart. - me->graph = lo_barchart. - WHEN c_graph_pie. - CREATE OBJECT lo_piechart. - me->graph = lo_piechart. - WHEN c_graph_line. - CREATE OBJECT lo_linechart. - me->graph = lo_linechart. - WHEN OTHERS. - ENDCASE. - - "Fill properties - node2 ?= node->find_from_name( name = 'date1904' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_1904val = ls_prop-val. - node2 ?= node->find_from_name( name = 'lang' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_langval = ls_prop-val. - node2 ?= node->find_from_name( name = 'roundedCorners' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_roundedcornersval = ls_prop-val. - - "style - node2 ?= node->find_from_name( name = 'style' namespace = 'c14' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_c14styleval = ls_prop-val. - node2 ?= node->find_from_name( name = 'style' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_styleval = ls_prop-val. - "---------------------------Read graph properties - node2 ?= node->find_from_name( name = 'autoTitleDeleted' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_autotitledeletedval = ls_prop-val. - - "plotArea - CASE me->graph_type. - WHEN c_graph_bars. - node2 ?= node->find_from_name( name = 'barDir' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_bardirval = ls_prop-val. - node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_groupingval = ls_prop-val. - node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_varycolorsval = ls_prop-val. - - "Load series - CALL METHOD node->get_elements_by_tag_name - EXPORTING -* depth = 0 - name = 'ser' -* namespace = '' - RECEIVING - rval = lo_collection. - CALL METHOD lo_collection->create_iterator - RECEIVING - rval = lo_iterator. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - WHILE lo_node IS BOUND. - node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_idx = ls_prop-val. - node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_order = ls_prop-val. - node3 ?= node2->find_from_name( name = 'invertIfNegative' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_invertifnegative = ls_prop-val. - node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). - IF node3 IS BOUND. - lv_sername = node3->get_value( ). - ENDIF. - node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). - IF node3 IS BOUND. - node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). - lv_label = node4->get_value( ). - ENDIF. - node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). - IF node3 IS BOUND. - node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). - lv_value = node4->get_value( ). - ENDIF. - CALL METHOD lo_barchart->create_serie - EXPORTING - ip_idx = lv_idx - ip_order = lv_order - ip_invertifnegative = lv_invertifnegative - ip_lbl = lv_label - ip_ref = lv_value - ip_sername = lv_sername. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - ENDWHILE. - "note: numCache avoided - node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_showlegendkeyval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_showvalval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_showcatnameval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_showsernameval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_showpercentval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_showbubblesizeval = ls_prop-val. - node2 ?= node->find_from_name( name = 'gapWidth' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_gapwidthval = ls_prop-val. - - "Load axes - node2 ?= node->find_from_name( name = 'barChart' namespace = 'c' ). - CALL METHOD node2->get_elements_by_tag_name - EXPORTING -* depth = 0 - name = 'axId' -* namespace = '' - RECEIVING - rval = lo_collection. - CALL METHOD lo_collection->create_iterator - RECEIVING - rval = lo_iterator. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - WHILE lo_node IS BOUND. - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lv_axid = ls_prop-val. - IF sy-index EQ 1. "catAx - node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). - node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_orientation = ls_prop-val. - node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_delete = ls_prop-val. - node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_axpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_formatcode = ls_prop-formatcode. - lv_sourcelinked = ls_prop-sourcelinked. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_majortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_minortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_ticklblpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crossax = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crosses = ls_prop-val. - node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_auto = ls_prop-val. - node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_lblalgn = ls_prop-val. - node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_lbloffset = ls_prop-val. - node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_nomultilvllbl = ls_prop-val. - CALL METHOD lo_barchart->create_ax - EXPORTING - ip_axid = lv_axid - ip_type = zcl_excel_graph_bars=>c_catax - ip_orientation = lv_orientation - ip_delete = lv_delete - ip_axpos = lv_axpos - ip_formatcode = lv_formatcode - ip_sourcelinked = lv_sourcelinked - ip_majortickmark = lv_majortickmark - ip_minortickmark = lv_minortickmark - ip_ticklblpos = lv_ticklblpos - ip_crossax = lv_crossax - ip_crosses = lv_crosses - ip_auto = lv_auto - ip_lblalgn = lv_lblalgn - ip_lbloffset = lv_lbloffset - ip_nomultilvllbl = lv_nomultilvllbl. - ELSEIF sy-index EQ 2. "valAx - node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). - node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_orientation = ls_prop-val. - node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_delete = ls_prop-val. - node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_axpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_formatcode = ls_prop-formatcode. - lv_sourcelinked = ls_prop-sourcelinked. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_majortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_minortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_ticklblpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crossax = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crosses = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crossbetween = ls_prop-val. - CALL METHOD lo_barchart->create_ax - EXPORTING - ip_axid = lv_axid - ip_type = zcl_excel_graph_bars=>c_valax - ip_orientation = lv_orientation - ip_delete = lv_delete - ip_axpos = lv_axpos - ip_formatcode = lv_formatcode - ip_sourcelinked = lv_sourcelinked - ip_majortickmark = lv_majortickmark - ip_minortickmark = lv_minortickmark - ip_ticklblpos = lv_ticklblpos - ip_crossax = lv_crossax - ip_crosses = lv_crosses - ip_crossbetween = lv_crossbetween. - ENDIF. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - ENDWHILE. - - WHEN c_graph_pie. - node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_varycolorsval = ls_prop-val. - - "Load series - CALL METHOD node->get_elements_by_tag_name - EXPORTING -* depth = 0 - name = 'ser' -* namespace = '' - RECEIVING - rval = lo_collection. - CALL METHOD lo_collection->create_iterator - RECEIVING - rval = lo_iterator. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - WHILE lo_node IS BOUND. - node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_idx = ls_prop-val. - node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_order = ls_prop-val. - node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). - IF node3 IS BOUND. - lv_sername = node3->get_value( ). - ENDIF. - node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). - IF node3 IS BOUND. - node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). - lv_label = node4->get_value( ). - ENDIF. - node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). - IF node3 IS BOUND. - node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). - lv_value = node4->get_value( ). - ENDIF. - CALL METHOD lo_piechart->create_serie - EXPORTING - ip_idx = lv_idx - ip_order = lv_order - ip_lbl = lv_label - ip_ref = lv_value - ip_sername = lv_sername. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - ENDWHILE. - - "note: numCache avoided - node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showlegendkeyval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showvalval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showcatnameval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showsernameval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showpercentval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showbubblesizeval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showLeaderLines' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_showleaderlinesval = ls_prop-val. - node2 ?= node->find_from_name( name = 'firstSliceAng' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_firstsliceangval = ls_prop-val. - WHEN c_graph_line. - node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_groupingval = ls_prop-val. - node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_varycolorsval = ls_prop-val. - - "Load series - CALL METHOD node->get_elements_by_tag_name - EXPORTING -* depth = 0 - name = 'ser' -* namespace = '' - RECEIVING - rval = lo_collection. - CALL METHOD lo_collection->create_iterator - RECEIVING - rval = lo_iterator. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - WHILE lo_node IS BOUND. - node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_idx = ls_prop-val. - node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_order = ls_prop-val. - node3 ?= node2->find_from_name( name = 'symbol' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_symbol = ls_prop-val. - node3 ?= node2->find_from_name( name = 'smooth' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_smooth = ls_prop-val. - node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). - IF node3 IS BOUND. - lv_sername = node3->get_value( ). - ENDIF. - node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). - IF node3 IS BOUND. - node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). - lv_label = node4->get_value( ). - ENDIF. - node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). - IF node3 IS BOUND. - node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). - lv_value = node4->get_value( ). - ENDIF. - CALL METHOD lo_linechart->create_serie - EXPORTING - ip_idx = lv_idx - ip_order = lv_order - ip_symbol = lv_symbol - ip_smooth = lv_smooth - ip_lbl = lv_label - ip_ref = lv_value - ip_sername = lv_sername. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - ENDWHILE. - "note: numCache avoided - node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_showlegendkeyval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_showvalval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_showcatnameval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_showsernameval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_showpercentval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_showbubblesizeval = ls_prop-val. - - node ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). - node2 ?= node->find_from_name( name = 'marker' namespace = 'c' DEPTH = '1' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->NS_MARKERVAL = ls_prop-val. - node2 ?= node->find_from_name( name = 'smooth' namespace = 'c' DEPTH = '1' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->NS_SMOOTHVAL = ls_prop-val. - node ?= ip_chart->if_ixml_node~get_first_child( ). - CHECK node IS NOT INITIAL. - - "Load axes - node2 ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). - CALL METHOD node2->get_elements_by_tag_name - EXPORTING -* depth = 0 - name = 'axId' -* namespace = '' - RECEIVING - rval = lo_collection. - CALL METHOD lo_collection->create_iterator - RECEIVING - rval = lo_iterator. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - WHILE lo_node IS BOUND. - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lv_axid = ls_prop-val. - IF sy-index EQ 1. "catAx - node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). - node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_orientation = ls_prop-val. - node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_delete = ls_prop-val. - node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_axpos = ls_prop-val. -* node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). -* zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). -* lv_formatcode = ls_prop-formatcode. -* lv_sourcelinked = ls_prop-sourcelinked. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_majortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_minortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_ticklblpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crossax = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crosses = ls_prop-val. - node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_auto = ls_prop-val. - node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_lblalgn = ls_prop-val. - node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_lbloffset = ls_prop-val. - node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_nomultilvllbl = ls_prop-val. - CALL METHOD lo_linechart->create_ax - EXPORTING - ip_axid = lv_axid - ip_type = zcl_excel_graph_line=>c_catax - ip_orientation = lv_orientation - ip_delete = lv_delete - ip_axpos = lv_axpos - ip_formatcode = lv_formatcode - ip_sourcelinked = lv_sourcelinked - ip_majortickmark = lv_majortickmark - ip_minortickmark = lv_minortickmark - ip_ticklblpos = lv_ticklblpos - ip_crossax = lv_crossax - ip_crosses = lv_crosses - ip_auto = lv_auto - ip_lblalgn = lv_lblalgn - ip_lbloffset = lv_lbloffset - ip_nomultilvllbl = lv_nomultilvllbl. - ELSEIF sy-index EQ 2. "valAx - node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). - node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_orientation = ls_prop-val. - node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_delete = ls_prop-val. - node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_axpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_formatcode = ls_prop-formatcode. - lv_sourcelinked = ls_prop-sourcelinked. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_majortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_minortickmark = ls_prop-val. - node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_ticklblpos = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crossax = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crosses = ls_prop-val. - node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). - lv_crossbetween = ls_prop-val. - CALL METHOD lo_linechart->create_ax - EXPORTING - ip_axid = lv_axid - ip_type = zcl_excel_graph_line=>c_valax - ip_orientation = lv_orientation - ip_delete = lv_delete - ip_axpos = lv_axpos - ip_formatcode = lv_formatcode - ip_sourcelinked = lv_sourcelinked - ip_majortickmark = lv_majortickmark - ip_minortickmark = lv_minortickmark - ip_ticklblpos = lv_ticklblpos - ip_crossax = lv_crossax - ip_crosses = lv_crosses - ip_crossbetween = lv_crossbetween. - ENDIF. - lo_node = lo_iterator->get_next( ). - IF lo_node IS BOUND. - node2 ?= lo_node->query_interface( ixml_iid_element ). - ENDIF. - ENDWHILE. - WHEN OTHERS. - ENDCASE. - - "legend - CASE me->graph_type. - WHEN c_graph_bars. - node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_legendposval = ls_prop-val. - node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_barchart->ns_overlayval = ls_prop-val. - WHEN c_graph_line. - node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_legendposval = ls_prop-val. - node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_linechart->ns_overlayval = ls_prop-val. - WHEN c_graph_pie. - node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_legendposval = ls_prop-val. - node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_overlayval = ls_prop-val. - node2 ?= node->find_from_name( name = 'pPr' namespace = 'a' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_pprrtl = ls_prop-rtl. - node2 ?= node->find_from_name( name = 'endParaRPr' namespace = 'a' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - lo_piechart->ns_endpararprlang = ls_prop-lang. - - WHEN OTHERS. - ENDCASE. - - node2 ?= node->find_from_name( name = 'plotVisOnly' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_plotvisonlyval = ls_prop-val. - node2 ?= node->find_from_name( name = 'dispBlanksAs' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_dispblanksasval = ls_prop-val. - node2 ?= node->find_from_name( name = 'showDLblsOverMax' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). - me->graph->ns_showdlblsovermaxval = ls_prop-val. - "--------------------- - - node2 ?= node->find_from_name( name = 'pageMargins' namespace = 'c' ). - zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_pagemargins ). - me->graph->pagemargins = ls_pagemargins. - - -ENDMETHOD. - - - - - - method PIXEL2EMU. -* suppose 96 DPI - IF ip_dpi IS SUPPLIED. - r_emu = ip_pixel * 914400 / ip_dpi. - ELSE. -* suppose 96 DPI - r_emu = ip_pixel * 914400 / 96. - ENDIF. -endmethod. - - - - - - - METHOD set_media. - IF ip_media IS SUPPLIED. - media = ip_media. - ENDIF. - media_type = ip_media_type. - media_source = c_media_source_xstring. - IF ip_width IS SUPPLIED. - size-width = ip_width. - ENDIF. - IF ip_height IS SUPPLIED. - size-height = ip_height. - ENDIF. -ENDMETHOD. - - - - - - method SET_MEDIA_MIME. - - io = ip_io. - media_source = c_media_source_mime. - size-width = ip_width. - size-height = ip_height. - - cl_wb_mime_repository=>load_mime( EXPORTING - io = ip_io - IMPORTING - filename = media_name - "mimetype = media_type - CHANGING - language = sy-langu ). - - SPLIT media_name AT '.' INTO media_name media_type. - - - -endmethod. - - - - - - method SET_MEDIA_WWW. - DATA: lv_value(20). - - media_key_www = ip_key. - media_source = c_media_source_www. - - CALL FUNCTION 'WWWPARAMS_READ' - EXPORTING - relid = media_key_www-relid - objid = media_key_www-objid - name = 'fileextension' - IMPORTING - value = lv_value. - media_type = lv_value. - SHIFT media_type LEFT DELETING LEADING '.'. - - size-width = ip_width. - size-height = ip_height. -endmethod. - - - - - - - METHOD set_position. - from_loc-col = zcl_excel_common=>convert_column2int( ip_from_col ) - 1. - IF ip_coloff IS SUPPLIED. - from_loc-col_offset = ip_coloff. - ENDIF. - from_loc-row = ip_from_row - 1. - IF ip_rowoff IS SUPPLIED. - from_loc-row_offset = ip_rowoff. - ENDIF. - anchor = anchor_one_cell. -ENDMETHOD. - - - - - - method SET_POSITION2. - - data: lv_anchor type zexcel_drawing_anchor. - lv_anchor = ip_anchor. - - IF lv_anchor IS INITIAL. - IF ip_to IS NOT INITIAL. - lv_anchor = anchor_two_cell. - ELSE. - lv_anchor = anchor_one_cell. - ENDIF. - ENDIF. - - CASE lv_anchor. - WHEN anchor_absolute OR anchor_one_cell. - CLEAR: me->to_loc. - WHEN anchor_two_cell. - CLEAR: me->size. - ENDCASE. - - me->from_loc = ip_from. - me->to_loc = ip_to. - me->anchor = lv_anchor. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - method ADD. - DATA: lv_index TYPE i. - - drawings->add( ip_drawing ). - lv_index = drawings->if_object_collection~size( ). - ip_drawing->create_media_name( - ip_index = lv_index ). -endmethod. - - - method CLEAR. - - drawings->clear( ). -endmethod. - - - - method CONSTRUCTOR. - - CREATE OBJECT drawings. - type = ip_type. - -endmethod. - - - - - method GET. - - DATA lv_index TYPE i. - lv_index = ip_index. - eo_drawing ?= drawings->if_object_collection~get( lv_index ). -endmethod. - - - - method GET_ITERATOR. - - eo_iterator ?= drawings->if_object_collection~get_iterator( ). -endmethod. - - - - method GET_TYPE. - rp_type = me->type. -endmethod. - - - - method INCLUDE. - drawings->add( ip_drawing ). -endmethod. - - - - method IS_EMPTY. - - is_empty = drawings->if_object_collection~is_empty( ). -endmethod. - - - - method REMOVE. - - drawings->remove( ip_drawing ). -endmethod. - - - - method SIZE. - - ep_size = drawings->if_object_collection~size( ). -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - method CREATE. - data: lo_hyperlink type REF TO zcl_excel_hyperlink. - - create OBJECT lo_hyperlink. - - lo_hyperlink->location = iv_url. - lo_hyperlink->internal = iv_internal. - - ov_link = lo_hyperlink. -endmethod. - - - - - method CREATE_EXTERNAL_LINK. - - ov_link = zcl_excel_hyperlink=>create( iv_url = iv_url - iv_internal = abap_false ). -endmethod. - - - - - method CREATE_INTERNAL_LINK. - ov_link = zcl_excel_hyperlink=>create( iv_url = iv_location - iv_internal = abap_true ). -endmethod. - - - - method GET_REF. - ev_ref = row. - CONDENSE ev_ref. - CONCATENATE column ev_ref INTO ev_ref. -endmethod. - - - - method GET_URL. - ev_url = me->location. -endmethod. - - - - method IS_INTERNAL. - ev_ret = me->internal. -endmethod. - - - - - - method SET_CELL_REFERENCE. - me->column = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column - me->row = ip_row. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - method CONSTRUCTOR. -endmethod. - - - - method GET_GUID. - - ep_guid = me->guid. - -endmethod. - - - - method GET_VALUE. - - ep_value = me->value. - -endmethod. - - - - method SET_RANGE_VALUE. - me->value = ip_value. -endmethod. - - - - - - - - method SET_VALUE. - DATA: lv_start_row_c TYPE char7, - lv_stop_row_c TYPE char7, - lv_value TYPE string. - lv_stop_row_c = ip_stop_row. - SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. - SHIFT lv_stop_row_c LEFT DELETING LEADING space. - lv_start_row_c = ip_start_row. - SHIFT lv_start_row_c RIGHT DELETING TRAILING space. - SHIFT lv_start_row_c LEFT DELETING LEADING space. - lv_value = ip_sheet_name. - me->value = zcl_excel_common=>escape_string( ip_value = lv_value ). - - CONCATENATE me->value '!$' ip_start_column '$' lv_start_row_c ':$' ip_stop_column '$' lv_stop_row_c INTO me->value. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - method ADD. - ranges->add( ip_range ). -endmethod. - - - method CLEAR. - ranges->clear( ). -endmethod. - - - method CONSTRUCTOR. - - - CREATE OBJECT ranges. - -endmethod. - - - - - method GET. - eo_range ?= ranges->if_object_collection~get( ip_index ). -endmethod. - - - - method GET_ITERATOR. - eo_iterator ?= ranges->if_object_collection~get_iterator( ). -endmethod. - - - - method IS_EMPTY. - is_empty = ranges->if_object_collection~is_empty( ). -endmethod. - - - - method REMOVE. - ranges->remove( ip_range ). -endmethod. - - - - method SIZE. - ep_size = ranges->if_object_collection~size( ). -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - method CONSTRUCTOR. -endmethod. - - - - method IS_SECURITY_ENABLED. - IF lockrevision EQ abap_true OR lockstructure EQ abap_true OR lockwindows EQ abap_true. - ep_security_enabled = abap_true. - ENDIF. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - orientation = me->c_orientation_default. - -* default margins - margin_bottom = '0.75'. - margin_footer = '0.3'. - margin_header = '0.3'. - margin_left = '0.7'. - margin_right = '0.7'. - margin_top = '0.75'. - -* clear page settings - CLEAR: black_and_white, - cell_comments, - copies, - draft, - errors, - first_page_number, - fit_to_page, - fit_to_height, - fit_to_width, - horizontal_dpi, - orientation, - page_order, - paper_height, - paper_size, - paper_width, - scale, - use_first_page_num, - use_printer_defaults, - vertical_dpi. -endmethod. - - - - - - - method GET_HEADER_FOOTER_STRING. -* ---------------------------------------------------------------------- - DATA: lc_marker_left(2) TYPE c VALUE '&L' - , lc_marker_right(2) TYPE c VALUE '&R' - , lc_marker_center(2) TYPE c VALUE '&C' - , lv_value TYPE string - . -* ---------------------------------------------------------------------- - IF ep_odd_header IS SUPPLIED. - - IF me->odd_header-left_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'LEFT' ). - CONCATENATE lc_marker_left lv_value INTO ep_odd_header. - ENDIF. - - IF me->odd_header-center_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'CENTER' ). - CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_header. - ENDIF. - - IF me->odd_header-right_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'RIGHT' ). - CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_header. - ENDIF. - - ENDIF. -* ---------------------------------------------------------------------- - IF ep_odd_footer IS SUPPLIED. - - IF me->odd_footer-left_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'LEFT' ). - CONCATENATE lc_marker_left lv_value INTO ep_odd_footer. - ENDIF. - - IF me->odd_footer-center_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'CENTER' ). - CONCATENATE ep_odd_footer lc_marker_center lv_value INTO ep_odd_footer. - ENDIF. - - IF me->odd_footer-right_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'RIGHT' ). - CONCATENATE ep_odd_footer lc_marker_right lv_value INTO ep_odd_footer. - ENDIF. - - ENDIF. -* ---------------------------------------------------------------------- - IF ep_even_header IS SUPPLIED. - - IF me->even_header-left_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'LEFT' ). - CONCATENATE lc_marker_left lv_value INTO ep_even_header. - ENDIF. - - IF me->even_header-center_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'CENTER' ). - CONCATENATE ep_even_header lc_marker_center lv_value INTO ep_even_header. - ENDIF. - - IF me->even_header-right_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'RIGHT' ). - CONCATENATE ep_even_header lc_marker_right lv_value INTO ep_even_header. - ENDIF. - - ENDIF. -* ---------------------------------------------------------------------- - IF ep_even_footer IS SUPPLIED. - - IF me->even_footer-left_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'LEFT' ). - CONCATENATE lc_marker_left lv_value INTO ep_even_footer. - ENDIF. - - IF me->even_footer-center_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'CENTER' ). - CONCATENATE ep_even_footer lc_marker_center lv_value INTO ep_even_footer. - ENDIF. - - IF me->even_footer-right_value IS NOT INITIAL. - lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'RIGHT' ). - CONCATENATE ep_even_footer lc_marker_right lv_value INTO ep_even_footer. - ENDIF. - - ENDIF. -* ---------------------------------------------------------------------- -endmethod. - - - - - - METHOD process_header_footer. - -* ---------------------------------------------------------------------- -* Only Basic font/text formatting possible: -* Bold (yes / no), Font Type, Font Size - - DATA: lv_fname(12) TYPE c - , lv_string TYPE string - . - - FIELD-SYMBOLS: <lv_value> TYPE string - , <ls_font> TYPE zexcel_s_style_font - . - -* ---------------------------------------------------------------------- - CONCATENATE ip_side '_VALUE' INTO lv_fname. - ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <lv_value>. - - CONCATENATE ip_side '_FONT' INTO lv_fname. - ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <ls_font>. - - IF <ls_font> IS ASSIGNED AND <lv_value> IS ASSIGNED. - - IF <ls_font>-name IS NOT INITIAL. - CONCATENATE '&"' <ls_font>-name ',' INTO rv_processed_string. - ELSE. - rv_processed_string = '&"-,'. - ENDIF. - - IF <ls_font>-bold = abap_true. - CONCATENATE rv_processed_string 'Bold"' INTO rv_processed_string. - ELSE. - CONCATENATE rv_processed_string 'Standard"' INTO rv_processed_string. - ENDIF. - - IF <ls_font>-size IS NOT INITIAL. - lv_string = <ls_font>-size. - CONCATENATE rv_processed_string '&' lv_string INTO rv_processed_string. - ENDIF. - - CONCATENATE rv_processed_string <lv_value> INTO rv_processed_string. - - ENDIF. -* ---------------------------------------------------------------------- - -ENDMETHOD. - - - - - - - method SET_HEADER_FOOTER. - -* Only Basic font/text formatting possible: -* Bold (yes / no), Font Type, Font Size -* -* usefull placeholders, which can be used in header/footer value strings -* '&P' - page number -* '&N' - total number of pages -* '&D' - Date -* '&T' - Time -* '&F' - File Name -* '&Z' - Path -* '&A' - Sheet name -* new line via class constant CL_ABAP_CHAR_UTILITIES=>newline -* -* Example Value String 'page &P of &N' -* -* DO NOT USE &L , &C or &R which automatically created as position markers - - me->odd_header = ip_odd_header. - me->odd_footer = ip_odd_footer. - me->even_header = ip_even_header. - me->even_footer = ip_even_footer. - - IF me->even_header IS NOT INITIAL OR me->even_footer IS NOT INITIAL. - me->diff_oddeven_headerfooter = abap_true. - ENDIF. - - -endmethod. - - - - - - - - - - method SET_PAGE_MARGINS. - DATA: lv_coef TYPE f, - lv_unit TYPE string. - - lv_unit = ip_unit. - TRANSLATE lv_unit TO UPPER CASE. - - CASE lv_unit. - WHEN 'IN'. lv_coef = 1. - WHEN 'CM'. lv_coef = '0.393700787'. - WHEN 'MM'. lv_coef = '0.0393700787'. - ENDCASE. - - IF ip_bottom IS SUPPLIED. margin_bottom = lv_coef * ip_bottom. ENDIF. - IF ip_footer IS SUPPLIED. margin_footer = lv_coef * ip_footer. ENDIF. - IF ip_header IS SUPPLIED. margin_header = lv_coef * ip_header. ENDIF. - IF ip_left IS SUPPLIED. margin_left = lv_coef * ip_left. ENDIF. - IF ip_right IS SUPPLIED. margin_right = lv_coef * ip_right. ENDIF. - IF ip_top IS SUPPLIED. margin_top = lv_coef * ip_top. ENDIF. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - method CONSTRUCTOR. - - - CREATE OBJECT font. - CREATE OBJECT fill. - CREATE OBJECT borders. - CREATE OBJECT alignment. - CREATE OBJECT number_format. - CREATE OBJECT protection. - -* Start of insertion # issue 139 - Dateretention of cellstyles - IF ip_guid IS NOT INITIAL. - me->guid = ip_guid. - ELSE. -* End of insertion # issue 139 - Dateretention of cellstyles - CALL FUNCTION 'GUID_CREATE' - IMPORTING - ev_guid_16 = me->guid. -* Start of insertion # issue 139 - Dateretention of cellstyles - ENDIF. -* End of insertion # issue 139 - Dateretention of cellstyles - -endmethod. - - - - method GET_GUID. - - - ep_guid = me->guid. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - method ADD. - - - styles->add( ip_style ). -endmethod. - - - method CLEAR. - - - styles->clear( ). -endmethod. - - - method CONSTRUCTOR. - - - CREATE OBJECT styles. -endmethod. - - - - - method GET. - - - eo_style ?= styles->if_object_collection~get( ip_index ). -endmethod. - - - - method GET_ITERATOR. - - - eo_iterator ?= styles->if_object_collection~get_iterator( ). -endmethod. - - - - method IS_EMPTY. - - - is_empty = styles->if_object_collection~is_empty( ). -endmethod. - - - - - method REGISTER_NEW_STYLE. - - - me->add( io_style ). - ep_style_code = me->size( ) - 1. "style count starts from 0 -endmethod. - - - - method REMOVE. - - - styles->remove( ip_style ). -endmethod. - - - - method SIZE. - - - ep_size = styles->if_object_collection~size( ). -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - method ADD. - styles_conditional->add( ip_style_conditional ). -endmethod. - - - method CLEAR. - styles_conditional->clear( ). -endmethod. - - - method CONSTRUCTOR. - - CREATE OBJECT styles_conditional. - -endmethod. - - - - - method GET. - DATA lv_index TYPE i. - lv_index = ip_index. - eo_style_conditional ?= styles_conditional->if_object_collection~get( lv_index ). -endmethod. - - - - method GET_ITERATOR. - eo_iterator ?= styles_conditional->if_object_collection~get_iterator( ). -endmethod. - - - - method IS_EMPTY. - is_empty = styles_conditional->if_object_collection~is_empty( ). -endmethod. - - - - method REMOVE. - styles_conditional->remove( ip_style_conditional ). -endmethod. - - - - method SIZE. - ep_size = styles_conditional->if_object_collection~size( ). -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - horizontal = me->c_horizontal_general. - vertical = me->c_vertical_bottom. - wrapText = abap_false. - shrinkToFit = abap_false. -endmethod. - - - - method GET_STRUCTURE. - - es_alignment-horizontal = me->horizontal. - es_alignment-vertical = me->vertical. - es_alignment-textrotation = me->textrotation. - es_alignment-wraptext = me->wraptext. - es_alignment-shrinktofit = me->shrinktofit. - es_alignment-indent = me->indent. - -endmethod. - - - - *"* use this source file for the definition and implementation of -*"* local helper classes, interface definitions and type -*"* declarations - *"* use this source file for any type of declarations (class -*"* definitions, interfaces or type declarations) you need for -*"* components in the private section - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - method CREATE. - - -* Office 2007 file format is a cab of several xml files with extension .xlsx - - DATA: lo_zip TYPE REF TO cl_abap_zip, - lo_worksheet TYPE REF TO zcl_excel_worksheet, - lo_active_worksheet TYPE REF TO zcl_excel_worksheet, - lo_iterator TYPE REF TO cl_object_collection_iterator, - lo_nested_iterator TYPE REF TO cl_object_collection_iterator, - lo_table TYPE REF TO zcl_excel_table, - lo_drawing TYPE REF TO zcl_excel_drawing, - lo_drawings TYPE REF TO zcl_excel_drawings. - - DATA: lv_content TYPE xstring, - lv_active TYPE flag, - lv_xl_sheet TYPE string, - lv_xl_sheet_rels TYPE string, - lv_xl_drawing TYPE string, - lv_xl_drawing_rels TYPE string, - lv_syindex TYPE string, - lv_value TYPE string, - lv_drawing_index TYPE i. - -********************************************************************** -* Start of insertion # issue 139 - Dateretention of cellstyles - me->excel->add_static_styles( ). -* End of insertion # issue 139 - Dateretention of cellstyles - -********************************************************************** -* STEP 1: Create archive object file (ZIP) - CREATE OBJECT lo_zip. - -********************************************************************** -* STEP 2: Add [Content_Types].xml to zip - lv_content = me->create_content_types( ). - lo_zip->add( name = me->c_content_types - content = lv_content ). - -********************************************************************** -* STEP 3: Add _rels/.rels to zip - lv_content = me->create_relationships( ). - lo_zip->add( name = me->c_relationships - content = lv_content ). - -********************************************************************** -* STEP 4: Add docProps/app.xml to zip - lv_content = me->create_docprops_app( ). - lo_zip->add( name = me->c_docprops_app - content = lv_content ). - -********************************************************************** -* STEP 5: Add docProps/core.xml to zip - lv_content = me->create_docprops_core( ). - lo_zip->add( name = me->c_docprops_core - content = lv_content ). - -********************************************************************** -* STEP 6: Add xl/_rels/workbook.xml.rels to zip - lv_content = me->create_xl_relationships( ). - lo_zip->add( name = me->c_xl_relationships - content = lv_content ). - -********************************************************************** -* STEP 6: Add xl/_rels/workbook.xml.rels to zip - lv_content = me->create_xl_theme( ). - lo_zip->add( name = me->c_xl_theme - content = lv_content ). - -********************************************************************** -* STEP 7: Add xl/workbook.xml to zip - lv_content = me->create_xl_workbook( ). - lo_zip->add( name = me->c_xl_workbook - content = lv_content ). - -********************************************************************** -* STEP 8: Add xl/workbook.xml to zip -* lv_content = me->create_xl_styles_static( ). - lv_content = me->create_xl_styles( ). - lo_zip->add( name = me->c_xl_styles - content = lv_content ). - -********************************************************************** -* STEP 9: Add sharedStrings.xml to zip - lv_content = me->create_xl_sharedstrings( ). - lo_zip->add( name = me->c_xl_sharedstrings - content = lv_content ). - -********************************************************************** -* STEP 10: Add sheet#.xml and drawing#.xml to zip - lo_iterator = me->excel->get_worksheets_iterator( ). - lo_active_worksheet = me->excel->get_active_worksheet( ). - lv_drawing_index = 1. - - WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). - IF lo_active_worksheet->get_guid( ) EQ lo_worksheet->get_guid( ). - lv_active = abap_true. - ELSE. - lv_active = abap_false. - ENDIF. - - lv_content = me->create_xl_sheet( io_worksheet = lo_worksheet - iv_active = lv_active ). - lv_xl_sheet = me->c_xl_sheet. - MOVE sy-index TO lv_syindex. - SHIFT lv_syindex RIGHT DELETING TRAILING space. - SHIFT lv_syindex LEFT DELETING LEADING space. - REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet WITH lv_syindex. - lo_zip->add( name = lv_xl_sheet - content = lv_content ). - - lv_xl_sheet_rels = me->c_xl_sheet_rels. - lv_content = me->create_xl_sheet_rels( io_worksheet = lo_worksheet - iv_drawing_index = lv_drawing_index ). - REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet_rels WITH lv_syindex. - lo_zip->add( name = lv_xl_sheet_rels - content = lv_content ). - - lo_nested_iterator = lo_worksheet->get_tables_iterator( ). - - WHILE lo_nested_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_table ?= lo_nested_iterator->if_object_collection_iterator~get_next( ). - lv_content = me->create_xl_table( lo_table ). - - lv_value = lo_table->get_name( ). - CONCATENATE 'xl/tables/' lv_value '.xml' INTO lv_value. - lo_zip->add( name = lv_value - content = lv_content ). - ENDWHILE. - -* Add drawings ********************************** - lo_drawings = lo_worksheet->get_drawings( ). - IF lo_drawings->is_empty( ) = abap_false. - MOVE lv_drawing_index TO lv_syindex. - SHIFT lv_syindex RIGHT DELETING TRAILING space. - SHIFT lv_syindex LEFT DELETING LEADING space. - - lv_content = me->create_xl_drawings( lo_worksheet ). - lv_xl_drawing = me->c_xl_drawings. - REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing WITH lv_syindex. - lo_zip->add( name = lv_xl_drawing - content = lv_content ). - - lv_content = me->create_xl_drawings_rels( lo_worksheet ). - lv_xl_drawing_rels = me->c_xl_drawings_rels. - REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing_rels WITH lv_syindex. - lo_zip->add( name = lv_xl_drawing_rels - content = lv_content ). - ADD 1 TO lv_drawing_index. - ENDIF. - ENDWHILE. - -********************************************************************** -* STEP 11: Add media - lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_image ). - WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). - - lv_content = lo_drawing->get_media( ). - lv_value = lo_drawing->get_media_name( ). - CONCATENATE 'xl/media/' lv_value INTO lv_value. - lo_zip->add( name = lv_value - content = lv_content ). - ENDWHILE. - -********************************************************************** -* STEP 12: Add charts - lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_chart ). - WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). - - lv_content = lo_drawing->get_media( ). - lv_value = lo_drawing->get_media_name( ). - CONCATENATE 'xl/charts/' lv_value INTO lv_value. - lo_zip->add( name = lv_value - content = lv_content ). - ENDWHILE. - -********************************************************************** -* STEP 9: Add vbaProject.bin to zip - lo_zip->add( name = me->c_xl_vbaproject - content = me->excel->zif_excel_book_vba_project~vbaproject ). - -********************************************************************** -* STEP 12: Create the final zip - ep_excel = lo_zip->save( ). - -endmethod. - - - method CREATE_CONTENT_TYPES. -** Constant node name - DATA: lc_xml_node_workb_ct TYPE string VALUE 'application/vnd.ms-excel.sheet.macroEnabled.main+xml', - lc_xml_node_default TYPE string VALUE 'Default', - " Node attributes - lc_xml_attr_partname TYPE string VALUE 'PartName', - lc_xml_attr_extension TYPE string VALUE 'Extension', - lc_xml_attr_contenttype TYPE string VALUE 'ContentType', - lc_xml_attr_codename TYPE string VALUE 'codeName', - lc_xml_node_workb_pn TYPE string VALUE '/xl/workbook.xml', - lc_xml_node_bin_ext TYPE string VALUE 'bin', - lc_xml_node_bin_ct TYPE string VALUE 'application/vnd.ms-office.vbaProject'. - - - DATA: lo_ixml TYPE REF TO if_ixml, - lo_document TYPE REF TO if_ixml_document, - lo_document_xml TYPE REF TO cl_xml_document, - lo_element_root TYPE REF TO if_ixml_node, - lo_element TYPE REF TO if_ixml_element, - lo_collection TYPE REF TO if_ixml_node_collection, - lo_iterator TYPE REF TO if_ixml_node_iterator, - lo_node TYPE REF TO if_ixml_node, - lo_encoding TYPE REF TO if_ixml_encoding, - lo_streamfactory TYPE REF TO if_ixml_stream_factory, - lo_ostream TYPE REF TO if_ixml_ostream, - lo_renderer TYPE REF TO if_ixml_renderer. - - DATA: lv_subrc TYPE sysubrc, - lv_contenttype TYPE string, - lv_syindex(2) TYPE c. - -********************************************************************** -* STEP 3: Create standard contentType - ep_content = super->create_content_types( ). - -********************************************************************** -* STEP 2: modify XML adding the extension bin definition - - CREATE OBJECT lo_document_xml. - lv_subrc = lo_document_xml->parse_xstring( ep_content ). - - lo_document ?= lo_document_xml->m_document. - lo_element_root = lo_document->if_ixml_node~get_first_child( ). - - " extension node - lo_element = lo_document->create_simple_element( name = lc_xml_node_default - parent = lo_document ). - lo_element->set_attribute_ns( name = lc_xml_attr_extension - value = lc_xml_node_bin_ext ). - lo_element->set_attribute_ns( name = lc_xml_attr_contenttype - value = lc_xml_node_bin_ct ). - lo_element_root->append_child( new_child = lo_element ). - -********************************************************************** -* STEP 3: modify XML changing the contentType of node Override /xl/workbook.xml - - lo_collection = lo_document->get_elements_by_tag_name( 'Override' ). - lo_iterator = lo_collection->create_iterator( ). - lo_element ?= lo_iterator->get_next( ). - WHILE lo_element IS BOUND. - lv_contenttype = lo_element->get_attribute_ns( lc_xml_attr_partname ). - IF lv_contenttype EQ lc_xml_node_workb_pn. - lo_element->remove_attribute_ns( lc_xml_attr_contenttype ). - lo_element->set_attribute_ns( name = lc_xml_attr_contenttype - value = lc_xml_node_workb_ct ). - EXIT. - ENDIF. - lo_element ?= lo_iterator->get_next( ). - ENDWHILE. - -********************************************************************** -* STEP 3: Create xstring stream - CLEAR ep_content. - lo_ixml = cl_ixml=>create( ). - lo_streamfactory = lo_ixml->create_stream_factory( ). - lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). - lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). - lo_renderer->render( ). - -endmethod. - - - method CREATE_XL_RELATIONSHIPS. - -** Constant node name - DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', - lc_xml_node_relationship TYPE string VALUE 'Relationship', - " Node attributes - lc_xml_attr_id TYPE string VALUE 'Id', - lc_xml_attr_type TYPE string VALUE 'Type', - lc_xml_attr_target TYPE string VALUE 'Target', - " Node id - lc_xml_node_ridx_id TYPE string VALUE 'rId#', - " Node type - lc_xml_node_rid_vba_tp TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', - " Node target - lc_xml_node_rid_vba_tg TYPE string VALUE 'vbaProject.bin'. - - DATA: lo_ixml TYPE REF TO if_ixml, - lo_document TYPE REF TO if_ixml_document, - lo_document_xml TYPE REF TO cl_xml_document, - lo_element_root TYPE REF TO if_ixml_node, - lo_element TYPE REF TO if_ixml_element, - lo_node TYPE REF TO if_ixml_node, - lo_encoding TYPE REF TO if_ixml_encoding, - lo_streamfactory TYPE REF TO if_ixml_stream_factory, - lo_ostream TYPE REF TO if_ixml_ostream, - lo_renderer TYPE REF TO if_ixml_renderer. - - DATA: lv_xml_node_ridx_tg TYPE string, - lv_xml_node_ridx_id TYPE string, - lv_size TYPE i, - lv_subrc TYPE sysubrc, - lv_syindex(2) TYPE c. - -********************************************************************** -* STEP 3: Create standard relationship - ep_content = super->create_xl_relationships( ). - -********************************************************************** -* STEP 2: modify XML adding the vbaProject relation - - CREATE OBJECT lo_document_xml. - lv_subrc = lo_document_xml->parse_xstring( ep_content ). - - lo_document ?= lo_document_xml->m_document. - lo_element_root = lo_document->if_ixml_node~get_first_child( ). - - - lv_size = excel->get_worksheets_size( ). - - " Relationship node - lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship - parent = lo_document ). - ADD 4 TO lv_size. - lv_syindex = lv_size. - SHIFT lv_syindex RIGHT DELETING TRAILING space. - SHIFT lv_syindex LEFT DELETING LEADING space. - lv_xml_node_ridx_id = lc_xml_node_ridx_id. - REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. - lo_element->set_attribute_ns( name = lc_xml_attr_id - value = lv_xml_node_ridx_id ). - lo_element->set_attribute_ns( name = lc_xml_attr_type - value = lc_xml_node_rid_vba_tp ). - lo_element->set_attribute_ns( name = lc_xml_attr_target - value = lc_xml_node_rid_vba_tg ). - lo_element_root->append_child( new_child = lo_element ). - -********************************************************************** -* STEP 3: Create xstring stream - CLEAR ep_content. - lo_ixml = cl_ixml=>create( ). - lo_streamfactory = lo_ixml->create_stream_factory( ). - lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). - lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). - lo_renderer->render( ). - -endmethod. - - - method CREATE_XL_SHEET. - -** Constant node name - DATA: lc_xml_attr_codename TYPE string VALUE 'codeName'. - - DATA: lo_ixml TYPE REF TO if_ixml, - lo_document TYPE REF TO if_ixml_document, - lo_document_xml TYPE REF TO cl_xml_document, - lo_element_root TYPE REF TO if_ixml_node, - lo_element TYPE REF TO if_ixml_element, - lo_collection TYPE REF TO if_ixml_node_collection, - lo_iterator TYPE REF TO if_ixml_node_iterator, - lo_node TYPE REF TO if_ixml_node, - lo_encoding TYPE REF TO if_ixml_encoding, - lo_streamfactory TYPE REF TO if_ixml_stream_factory, - lo_ostream TYPE REF TO if_ixml_ostream, - lo_renderer TYPE REF TO if_ixml_renderer. - - DATA: lv_subrc TYPE sysubrc, - lv_syindex(2) TYPE c. - -********************************************************************** -* STEP 3: Create standard relationship - ep_content = super->create_xl_sheet( io_worksheet = io_worksheet - iv_active = iv_active ). - -********************************************************************** -* STEP 2: modify XML adding the vbaProject relation - - CREATE OBJECT lo_document_xml. - lv_subrc = lo_document_xml->parse_xstring( ep_content ). - - lo_document ?= lo_document_xml->m_document. - lo_element_root = lo_document->if_ixml_node~get_first_child( ). - -* lo_collection = lo_document->get_elements_by_tag_name( 'fileVersion' ). -* lo_iterator = lo_collection->create_iterator( ). -* lo_element ?= lo_iterator->get_next( ). -* WHILE lo_element IS BOUND. -* lo_element->set_attribute_ns( name = lc_xml_attr_codename -* value = me->excel->zif_excel_book_vba_project~codename ). -* lo_element ?= lo_iterator->get_next( ). -* ENDWHILE. - - lo_collection = lo_document->get_elements_by_tag_name( 'sheetPr' ). - lo_iterator = lo_collection->create_iterator( ). - lo_element ?= lo_iterator->get_next( ). - WHILE lo_element IS BOUND. - lo_element->set_attribute_ns( name = lc_xml_attr_codename - value = io_worksheet->zif_excel_sheet_vba_project~codename_pr ). - lo_element ?= lo_iterator->get_next( ). - ENDWHILE. - -********************************************************************** -* STEP 3: Create xstring stream - CLEAR ep_content. - lo_ixml = cl_ixml=>create( ). - lo_streamfactory = lo_ixml->create_stream_factory( ). - lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). - lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). - lo_renderer->render( ). -endmethod. - - - method CREATE_XL_WORKBOOK. - -** Constant node name - DATA: lc_xml_attr_codename TYPE string VALUE 'codeName'. - - DATA: lo_ixml TYPE REF TO if_ixml, - lo_document TYPE REF TO if_ixml_document, - lo_document_xml TYPE REF TO cl_xml_document, - lo_element_root TYPE REF TO if_ixml_node, - lo_element TYPE REF TO if_ixml_element, - lo_collection TYPE REF TO if_ixml_node_collection, - lo_iterator TYPE REF TO if_ixml_node_iterator, - lo_node TYPE REF TO if_ixml_node, - lo_encoding TYPE REF TO if_ixml_encoding, - lo_streamfactory TYPE REF TO if_ixml_stream_factory, - lo_ostream TYPE REF TO if_ixml_ostream, - lo_renderer TYPE REF TO if_ixml_renderer. - - DATA: lv_subrc TYPE sysubrc, - lv_syindex(2) TYPE c. - -********************************************************************** -* STEP 3: Create standard relationship - ep_content = super->create_xl_workbook( ). - -********************************************************************** -* STEP 2: modify XML adding the vbaProject relation - - CREATE OBJECT lo_document_xml. - lv_subrc = lo_document_xml->parse_xstring( ep_content ). - - lo_document ?= lo_document_xml->m_document. - lo_element_root = lo_document->if_ixml_node~get_first_child( ). - - lo_collection = lo_document->get_elements_by_tag_name( 'fileVersion' ). - lo_iterator = lo_collection->create_iterator( ). - lo_element ?= lo_iterator->get_next( ). - WHILE lo_element IS BOUND. - lo_element->set_attribute_ns( name = lc_xml_attr_codename - value = me->excel->zif_excel_book_vba_project~codename ). - lo_element ?= lo_iterator->get_next( ). - ENDWHILE. - - lo_collection = lo_document->get_elements_by_tag_name( 'workbookPr' ). - lo_iterator = lo_collection->create_iterator( ). - lo_element ?= lo_iterator->get_next( ). - WHILE lo_element IS BOUND. - lo_element->set_attribute_ns( name = lc_xml_attr_codename - value = me->excel->zif_excel_book_vba_project~codename_pr ). - lo_element ?= lo_iterator->get_next( ). - ENDWHILE. - -********************************************************************** -* STEP 3: Create xstring stream - CLEAR ep_content. - lo_ixml = cl_ixml=>create( ). - lo_streamfactory = lo_ixml->create_stream_factory( ). - lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). - lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). - lo_renderer->render( ). -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - METHOD zif_excel_converter~can_convert_object. - - DATA: lo_salv TYPE REF TO cl_salv_table. - - TRY. - lo_salv ?= io_object. - CATCH cx_sy_move_cast_error . - RAISE EXCEPTION TYPE zcx_excel. - ENDTRY. - -ENDMETHOD. - - - METHOD zif_excel_converter~create_fieldcatalog. - DATA: lo_salv TYPE REF TO cl_salv_table. - - TRY. - zif_excel_converter~can_convert_object( io_object = io_object ). - ENDTRY. - - ws_option = is_option. - - lo_salv ?= io_object. - - CLEAR: es_layout, - et_fieldcatalog, - et_colors . - - IF lo_salv IS BOUND. - load_data( EXPORTING io_salv = lo_salv - it_table = it_table ). - apply_sort( EXPORTING it_table = it_table - IMPORTING eo_table = eo_table ) . - - get_color( EXPORTING io_table = eo_table - IMPORTING et_colors = et_colors ) . - - get_filter( IMPORTING et_filter = et_filter - CHANGING xo_table = eo_table ) . - - update_catalog( CHANGING cs_layout = es_layout - ct_fieldcatalog = et_fieldcatalog ). - ENDIF. -ENDMETHOD. - - - - - METHOD load_data. - DATA: lo_columns TYPE REF TO cl_salv_columns_table, - lo_aggregations TYPE REF TO cl_salv_aggregations, - lo_sorts TYPE REF TO cl_salv_sorts, - lo_filters TYPE REF TO cl_salv_filters, - lo_functional TYPE REF TO cl_salv_functional_settings, - lo_display TYPE REF TO cl_salv_display_settings, - lo_selections TYPE REF TO cl_salv_selections. - - DATA: ls_vari TYPE disvariant, - lo_layout TYPE REF TO cl_salv_layout. - - DATA: lr_form_tol TYPE REF TO cl_salv_form, - lr_form_eol TYPE REF TO cl_salv_form. - - DATA lt_kkblo_fieldcat TYPE kkblo_t_fieldcat. - DATA ls_kkblo_layout TYPE kkblo_layout. - DATA lt_kkblo_filter TYPE kkblo_t_filter. - DATA lt_kkblo_sort TYPE kkblo_t_sortinfo. - - lo_layout = io_salv->get_layout( ) . - lo_columns = io_salv->get_columns( ). - lo_aggregations = io_salv->get_aggregations( ) . - lo_sorts = io_salv->get_sorts( ) . - lo_filters = io_salv->get_filters( ) . - lo_display = io_salv->get_display_settings( ) . - lo_functional = io_salv->get_functional_settings( ) . - - REFRESH: wt_fcat, - wt_sort, - wt_filt. - -* First update metadata if we can. - IF io_salv->is_offline( ) = abap_false. - io_salv->get_metadata( ) . - ELSE. -* If we are offline we need to build this. - cl_salv_controller_metadata=>get_variant( - EXPORTING - r_layout = lo_layout - CHANGING - s_variant = ls_vari ). - ENDIF. - -*... get the column information - wt_fcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog( - r_columns = lo_columns - r_aggregations = lo_aggregations ). - -*... get the layout information - cl_salv_controller_metadata=>get_lvc_layout( - EXPORTING - r_functional_settings = lo_functional - r_display_settings = lo_display - r_columns = lo_columns - r_aggregations = lo_aggregations - CHANGING - s_layout = ws_layo ). - -* the fieldcatalog is not complete yet! - CALL FUNCTION 'LVC_FIELDCAT_COMPLETE' - EXPORTING - i_complete = 'X' - i_refresh_buffer = space - i_buffer_active = space - is_layout = ws_layo - i_test = '1' - i_fcat_complete = 'X' - IMPORTING -* E_EDIT = - es_layout = ws_layo - CHANGING - ct_fieldcat = wt_fcat. - - IF ls_vari IS NOT INITIAL AND io_salv->is_offline( ) = abap_true. - CALL FUNCTION 'LVC_TRANSFER_TO_KKBLO' - EXPORTING - it_fieldcat_lvc = wt_fcat - is_layout_lvc = ws_layo - IMPORTING - et_fieldcat_kkblo = lt_kkblo_fieldcat - es_layout_kkblo = ls_kkblo_layout - TABLES - it_data = it_table - EXCEPTIONS - it_data_missing = 1 - it_fieldcat_lvc_missing = 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. - - CALL FUNCTION 'LT_VARIANT_LOAD' - EXPORTING -* I_TOOL = 'LT' - i_tabname = '1' -* I_TABNAME_SLAVE = - i_dialog = ' ' -* I_USER_SPECIFIC = ' ' -* I_DEFAULT = 'X' -* I_NO_REPTEXT_OPTIMIZE = -* I_VIA_GRID = - i_fcat_complete = 'X' - IMPORTING -* E_EXIT = - et_fieldcat = lt_kkblo_fieldcat - et_sort = lt_kkblo_sort - et_filter = lt_kkblo_filter - CHANGING - cs_layout = ls_kkblo_layout - ct_default_fieldcat = lt_kkblo_fieldcat - cs_variant = ls_vari - EXCEPTIONS - wrong_input = 1 - fc_not_complete = 2 - not_found = 3 - OTHERS = 4 - . - IF sy-subrc <> 0. -* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO -* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. - ENDIF. - - CALL FUNCTION 'LVC_TRANSFER_FROM_KKBLO' - EXPORTING -* I_TECH_COMPLETE = -* I_STRUCTURE_NAME = - it_fieldcat_kkblo = lt_kkblo_fieldcat - it_sort_kkblo = lt_kkblo_sort - it_filter_kkblo = lt_kkblo_filter -* IT_SPECIAL_GROUPS_KKBLO = -* IT_FILTERED_ENTRIES_KKBLO = -* IT_GROUPLEVELS_KKBLO = -* IS_SUBTOT_OPTIONS_KKBLO = - is_layout_kkblo = ls_kkblo_layout -* IS_REPREP_ID_KKBLO = -* I_CALLBACK_PROGRAM_KKBLO = -* IT_ADD_FIELDCAT = -* IT_EXCLUDING_KKBLO = -* IT_EXCEPT_QINFO_KKBLO = - IMPORTING - et_fieldcat_lvc = wt_fcat - et_sort_lvc = wt_sort - et_filter_lvc = wt_filt -* ET_SPECIAL_GROUPS_LVC = -* ET_FILTER_INDEX_LVC = -* ET_GROUPLEVELS_LVC = -* ES_TOTAL_OPTIONS_LVC = - es_layout_lvc = ws_layo -* ES_VARIANT_LVC = -* E_VARIANT_SAVE_LVC = -* ES_PRINT_INFO_LVC = -* ES_REPREP_LVC = -* E_REPREP_ACTIVE_LVC = -* ET_EXCLUDING_LVC = -* ET_EXCEPT_QINFO_LVC = - TABLES - it_data = it_table - EXCEPTIONS - it_data_missing = 1 - OTHERS = 2 - . - IF sy-subrc <> 0. -* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO -* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. - ENDIF. - - ELSE. -* ... get the sort information - wt_sort = cl_salv_controller_metadata=>get_lvc_sort( lo_sorts ). - -* ... get the filter information - wt_filt = cl_salv_controller_metadata=>get_lvc_filter( lo_filters ). - ENDIF. - -ENDMETHOD. - - - - - - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - -TYPES: BEGIN OF ts_alv_types, - seoclass TYPE seoclsname, - clsname TYPE seoclsname, - END OF ts_alv_types, - tt_alv_types TYPE HASHED TABLE OF ts_alv_types WITH UNIQUE KEY seoclass. - -TYPES: BEGIN OF ts_sort_values, - fieldname TYPE fieldname, - row_int TYPE zexcel_cell_row, - value TYPE REF TO data, - new TYPE flag, - sort_level TYPE int4, - is_collapsed type flag, - END OF ts_sort_values, - - tt_sort_values TYPE HASHED TABLE OF ts_sort_values WITH UNIQUE KEY fieldname. -TYPES: BEGIN OF ts_subtotal_rows, - row_int TYPE zexcel_cell_row, - row_int_start TYPE zexcel_cell_row, - columnname TYPE fieldname, - END OF ts_subtotal_rows, - - tt_subtotal_rows TYPE HASHED TABLE OF ts_subtotal_rows WITH UNIQUE KEY row_int. - -TYPES: BEGIN OF ts_styles, - type TYPE char1, - alignment TYPE zexcel_alignment, - inttype TYPE inttype, - decimals TYPE int1, - style TYPE REF TO zcl_excel_style, - guid TYPE zexcel_cell_style, - END OF ts_styles, - - tt_styles TYPE HASHED TABLE OF ts_styles WITH UNIQUE KEY type alignment inttype decimals. - -TYPES: BEGIN OF ts_color_styles, - guid_old TYPE zexcel_cell_style, - fontcolor TYPE zexcel_style_color_argb, - fillcolor TYPE zexcel_style_color_argb, - style_new TYPE REF TO zcl_excel_style, - END OF ts_color_styles, - - tt_color_styles TYPE HASHED TABLE OF ts_color_styles WITH UNIQUE KEY guid_old fontcolor fillcolor. - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - ABAP - SLIS - SOI - - - - - - - - - - - - - - - - - - - - - - - - - - - - METHOD ask_option. - DATA: ls_sval TYPE sval, - lt_sval TYPE STANDARD TABLE OF sval, - l_returncode TYPE string, - lt_fields TYPE ddfields, - ls_fields TYPE dfies. - - FIELD-SYMBOLS: <fs> TYPE ANY. - - rs_option = ws_option. - - CALL FUNCTION 'DDIF_FIELDINFO_GET' - EXPORTING - tabname = 'ZEXCEL_S_CONVERTER_OPTION' -* FIELDNAME = ' ' -* LANGU = sy-langu -* LFIELDNAME = ' ' -* ALL_TYPES = ' ' -* GROUP_NAMES = ' ' -* UCLEN = -* IMPORTING -* X030L_WA = -* DDOBJTYPE = -* DFIES_WA = -* LINES_DESCR = - TABLES - dfies_tab = lt_fields -* FIXED_VALUES = - EXCEPTIONS - not_found = 1 - internal_error = 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. - - LOOP AT lt_fields INTO ls_fields. - ASSIGN COMPONENT ls_fields-fieldname OF STRUCTURE ws_option TO <fs>. - IF sy-subrc = 0. - CLEAR ls_sval. - ls_sval-tabname = ls_fields-tabname. - ls_sval-fieldname = ls_fields-fieldname. - ls_sval-value = <fs>. - ls_sval-field_attr = space. - ls_sval-field_obl = space. - ls_sval-comp_code = space. - ls_sval-fieldtext = ls_fields-scrtext_m. - ls_sval-comp_tab = space. - ls_sval-comp_field = space. - ls_sval-novaluehlp = space. - INSERT ls_sval INTO TABLE lt_sval. - ENDIF. - ENDLOOP. - - CALL FUNCTION 'POPUP_GET_VALUES' - EXPORTING -* NO_VALUE_CHECK = space - popup_title = 'Excel creation options'(008) -* START_COLUMN = '5' -* START_ROW = '5' - IMPORTING - returncode = l_returncode - TABLES - fields = lt_sval - EXCEPTIONS - error_in_fields = 1 - OTHERS = 2 - . - IF sy-subrc <> 0. -* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO -* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. - ELSE. - IF l_returncode = 'A'. - RAISE EXCEPTION TYPE zcx_excel. - ELSE. - LOOP AT lt_sval INTO ls_sval. - ASSIGN COMPONENT ls_sval-fieldname OF STRUCTURE ws_option TO <fs>. - IF sy-subrc = 0. - <fs> = ls_sval-value. - ENDIF. - ENDLOOP. - set_option( is_option = ws_option ) . - rs_option = ws_option. - ENDIF. - ENDIF. -ENDMETHOD. - - - - - method BIND_CELLS. - -* Do we need subtotals with grouping - READ TABLE wt_fieldcatalog TRANSPORTING NO FIELDS WITH KEY is_subtotalled = abap_true. - IF sy-subrc = 0 . - r_freeze_col = loop_subtotal( i_row_int = w_row_int - i_col_int = w_col_int ) . - ELSE. - r_freeze_col = loop_normal( i_row_int = w_row_int - i_col_int = w_col_int ) . - ENDIF. - -endmethod. - - - - - - method BIND_TABLE. - data: lt_field_catalog type zexcel_t_fieldcatalog, - ls_field_catalog type zexcel_s_fieldcatalog, - ls_fcat type zexcel_s_converter_fcat, - lo_col_dim type ref to zcl_excel_worksheet_columndime, - lo_row_dim type ref to zcl_excel_worksheet_rowdimensi, - l_col_int type zexcel_cell_column, - l_col_alpha type zexcel_cell_column_alpha, - ls_settings type zexcel_s_table_settings, - l_line type i. - - field-symbols: <fs_tab> type any table. - - assign wo_data->* to <fs_tab> . - - ls_settings-table_style = i_style_table. - ls_settings-top_left_column = zcl_excel_common=>convert_column2alpha( ip_column = w_col_int ). - ls_settings-top_left_row = w_row_int. - ls_settings-show_row_stripes = ws_layout-is_stripped. - - describe table wt_fieldcatalog lines l_line. - l_line = l_line + 1 + w_col_int. - ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( ip_column = l_line ). - - describe table <fs_tab> lines l_line. - ls_settings-bottom_right_row = l_line + 1 + w_row_int. - sort wt_fieldcatalog by position. - loop at wt_fieldcatalog into ls_fcat. - move-corresponding ls_fcat to ls_field_catalog. - ls_field_catalog-dynpfld = abap_true. - insert ls_field_catalog into table lt_field_catalog. - endloop. - - wo_worksheet->bind_table( - exporting - ip_table = <fs_tab> - it_field_catalog = lt_field_catalog - is_table_settings = ls_settings - importing - es_table_settings = ls_settings - ). - loop at wt_fieldcatalog into ls_fcat. - l_col_int = w_col_int + ls_fcat-position - 1. - l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). -* Freeze panes - if ls_fcat-fix_column = abap_true. - add 1 to r_freeze_col. - endif. -* Now let's check for optimized - if ls_fcat-is_optimized = abap_true. - lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). - lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . - endif. -* Now let's check for visible - if ls_fcat-is_hidden = abap_true. - lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). - lo_col_dim->set_visible( ip_visible = abap_false ) . - endif. - endloop. - -endmethod. - - - METHOD class_constructor. - DATA: ls_objects TYPE ts_alv_types. - DATA: ls_option TYPE zexcel_s_converter_option, - l_uname TYPE sy-uname. - - GET PARAMETER ID 'ZUS' FIELD l_uname. - IF l_uname IS INITIAL OR l_uname = space. - l_uname = sy-uname. - ENDIF. - -* Object CL_GUI_ALV_GRID - ls_objects-seoclass = 'CL_GUI_ALV_GRID'. - ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_ALV_GRID'. - INSERT ls_objects INTO TABLE wt_objects. - -* Object CL_SALV_TABLE - ls_objects-seoclass = 'CL_SALV_TABLE'. - ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_SALV_TABLE'. - INSERT ls_objects INTO TABLE wt_objects. - -* Object CL_SALV_RESULT - ls_objects-seoclass = 'CL_SALV_EX_RESULT_DATA_TABLE '. - ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_RESULT_EX'. - INSERT ls_objects INTO TABLE wt_objects. -* Object CL_SALV_WD_RESULT - ls_objects-seoclass = 'CL_SALV_WD_RESULT_DATA_TABLE '. - ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_RESULT_WD'. - INSERT ls_objects INTO TABLE wt_objects. - - CONCATENATE 'EXCEL_' sy-uname INTO ws_indx-srtfd. - - IMPORT p1 = ls_option FROM DATABASE indx(xl) TO ws_indx ID ws_indx-srtfd. - - IF sy-subrc = 0. - ws_option = ls_option. - ELSE. - init_option( ) . - ENDIF. - -ENDMETHOD. - - - method CLEAN_FIELDCATALOG. - DATA: l_position TYPE int1. - - FIELD-SYMBOLS: <fs_sfcat> TYPE zexcel_s_converter_fcat. - - SORT wt_fieldcatalog BY position col_id. - - CLEAR l_position. - LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. - ADD 1 TO l_position. - <fs_sfcat>-position = l_position. -* Default stype with alignment and format - <fs_sfcat>-style_hdr = get_style( i_type = c_type_hdr - i_alignment = <fs_sfcat>-alignment ). - IF ws_layout-is_stripped = abap_true. - <fs_sfcat>-style_stripped = get_style( i_type = c_type_str - i_alignment = <fs_sfcat>-alignment - i_inttype = <fs_sfcat>-inttype - i_decimals = <fs_sfcat>-decimals ). - ENDIF. - <fs_sfcat>-style_normal = get_style( i_type = c_type_nor - i_alignment = <fs_sfcat>-alignment - i_inttype = <fs_sfcat>-inttype - i_decimals = <fs_sfcat>-decimals ). - <fs_sfcat>-style_subtotal = get_style( i_type = c_type_sub - i_alignment = <fs_sfcat>-alignment - i_inttype = <fs_sfcat>-inttype - i_decimals = <fs_sfcat>-decimals ). - <fs_sfcat>-style_total = get_style( i_type = c_type_tot - i_alignment = <fs_sfcat>-alignment - i_inttype = <fs_sfcat>-inttype - i_decimals = <fs_sfcat>-decimals ). - ENDLOOP. - -endmethod. - - - - - - - - - - - - - METHOD convert. - - IF is_option IS SUPPLIED. - ws_option = is_option. - ENDIF. - - TRY. - execute_converter( EXPORTING io_object = io_alv - it_table = it_table ) . - ENDTRY. - - IF io_worksheet IS SUPPLIED AND io_worksheet IS BOUND. - wo_worksheet = io_worksheet. - ENDIF. - IF co_excel IS SUPPLIED. - IF co_excel IS NOT BOUND. - CREATE OBJECT co_excel. - co_excel->zif_excel_book_properties~creator = sy-uname. - ENDIF. - wo_excel = co_excel. - ENDIF. - -* Move table to data object and clean it up - IF wt_fieldcatalog IS NOT INITIAL. - create_table( ). - ELSE. - wo_data = wo_table . - ENDIF. - - IF wo_excel IS NOT BOUND. - CREATE OBJECT wo_excel. - wo_excel->zif_excel_book_properties~creator = sy-uname. - ENDIF. - IF wo_worksheet IS NOT BOUND. - " Get active sheet - wo_worksheet = wo_excel->get_active_worksheet( ). - wo_worksheet->set_title( ip_title = 'Sheet1'(001) ). - ENDIF. - - IF i_row_int <= 0. - w_row_int = 1. - ELSE. - w_row_int = i_row_int. - ENDIF. - IF i_column_int <= 0. - w_col_int = 1. - ELSE. - w_col_int = i_column_int. - ENDIF. - - create_worksheet( i_table = i_table - i_style_table = i_style_table ) . - -ENDMETHOD. - - - - - - method CREATE_COLOR_STYLE. - DATA: ls_styles TYPE ts_styles. - DATA: lo_style TYPE REF TO zcl_excel_style. - - READ TABLE wt_styles INTO ls_styles WITH KEY guid = i_style. - IF sy-subrc = 0. - lo_style = wo_excel->add_new_style( ). -* lo_style->borders = ls_styles-style->borders. -* lo_style->protection = ls_styles-style->protection. - lo_style->font->bold = ls_styles-style->font->bold. - lo_style->alignment->horizontal = ls_styles-style->alignment->horizontal. - lo_style->number_format->format_code = ls_styles-style->number_format->format_code. - - lo_style->font->color-rgb = is_colors-fontcolor. - lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. - lo_style->fill->fgcolor-rgb = is_colors-fillcolor. - - ro_style = lo_style. - ENDIF. -endmethod. - - - - - - - - method CREATE_FORMULAR_SUBTOTAL. - data: l_row_alpha_start type string, - l_row_alpha_end type string, - l_func_num type string. - - l_row_alpha_start = i_row_int_start. - l_row_alpha_end = i_row_int_end. - - l_func_num = get_function_number( i_totals_function = i_totals_function ). - concatenate 'SUBTOTAL(' l_func_num ',' i_column l_row_alpha_start ':' i_column l_row_alpha_end ')' into r_formula. -endmethod. - - - - - - - method CREATE_FORMULAR_TOTAL. - data: l_row_alpha type string, - l_row_e_alpha type string. - - l_row_alpha = w_row_int + 1. - l_row_e_alpha = i_row_int. - - concatenate i_totals_function '(' i_column l_row_alpha ':' i_column l_row_e_alpha ')' into r_formula. -endmethod. - - - - method CREATE_PATH. - DATA: l_sep TYPE c , - l_path TYPE string, - l_return TYPE i . - - CLEAR r_path. - - " Save the file - cl_gui_frontend_services=>get_sapgui_workdir( - CHANGING - sapworkdir = l_path - EXCEPTIONS - get_sapworkdir_failed = 1 - cntl_error = 2 - error_no_gui = 3 - not_supported_by_gui = 4 - ). - IF sy-subrc <> 0. -* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO -* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. - CONCATENATE 'Excel_' w_fcount '.xlsx' INTO r_path. - ELSE. - DO. - ADD 1 TO w_fcount. -*-obtain file separator character--------------------------------------- - CALL METHOD cl_gui_frontend_services=>get_file_separator - CHANGING - file_separator = l_sep - EXCEPTIONS - cntl_error = 1 - error_no_gui = 2 - not_supported_by_gui = 3 - OTHERS = 4. - - IF sy-subrc <> 0. - l_sep = ''. - ENDIF. - - CONCATENATE l_path l_sep 'Excel_' w_fcount '.xlsx' INTO r_path. - - IF cl_gui_frontend_services=>file_exist( file = r_path ) = abap_true. - cl_gui_frontend_services=>file_delete( EXPORTING filename = r_path - CHANGING rc = l_return - EXCEPTIONS OTHERS = 1 ). - IF sy-subrc = 0 . - RETURN. - ENDIF. - ELSE. - RETURN. - ENDIF. - ENDDO. - ENDIF. - -endmethod. - - - - - method CREATE_STYLE_HDR. - data: lo_style type ref to zcl_excel_style. - - lo_style = wo_excel->add_new_style( ). - lo_style->font->bold = abap_true. - lo_style->font->color-rgb = zcl_excel_style_color=>c_white. - lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. - lo_style->fill->fgcolor-rgb = 'FF4F81BD'. - if i_alignment is supplied and i_alignment is not initial. - lo_style->alignment->horizontal = i_alignment. - endif. - ro_style = lo_style . -endmethod. - - - - - - - method CREATE_STYLE_NORMAL. - DATA: lo_style TYPE REF TO zcl_excel_style, - l_format TYPE zexcel_number_format. - - IF i_inttype IS SUPPLIED AND i_inttype IS NOT INITIAL. - l_format = set_cell_format( i_inttype = i_inttype - i_decimals = i_decimals ) . - ENDIF. - IF l_format IS NOT INITIAL OR - ( i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL ) . - - lo_style = wo_excel->add_new_style( ). - - IF i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL. - lo_style->alignment->horizontal = i_alignment. - ENDIF. - - IF l_format IS NOT INITIAL. - lo_style->number_format->format_code = l_format. - ENDIF. - - ro_style = lo_style . - - ENDIF. -endmethod. - - - - - - - method CREATE_STYLE_STRIPPED. - data: lo_style type ref to zcl_excel_style. - data: l_format type zexcel_number_format. - - lo_style = wo_excel->add_new_style( ). - lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. - lo_style->fill->fgcolor-rgb = 'FFDBE5F1'. - if i_alignment is supplied and i_alignment is not initial. - lo_style->alignment->horizontal = i_alignment. - endif. - if i_inttype is supplied and i_inttype is not initial. - l_format = set_cell_format( i_inttype = i_inttype - i_decimals = i_decimals ) . - if l_format is not initial. - lo_style->number_format->format_code = l_format. - endif. - endif. - ro_style = lo_style. - -endmethod. - - - - - - - method CREATE_STYLE_SUBTOTAL. - data: lo_style type ref to zcl_excel_style. - data: l_format type zexcel_number_format. - - lo_style = wo_excel->add_new_style( ). - lo_style->font->bold = abap_true. - - if i_alignment is supplied and i_alignment is not initial. - lo_style->alignment->horizontal = i_alignment. - endif. - if i_inttype is supplied and i_inttype is not initial. - l_format = set_cell_format( i_inttype = i_inttype - i_decimals = i_decimals ) . - if l_format is not initial. - lo_style->number_format->format_code = l_format. - endif. - endif. - - ro_style = lo_style . - -endmethod. - - - - - - - method CREATE_STYLE_TOTAL. - DATA: lo_style TYPE REF TO zcl_excel_style. - DATA: l_format TYPE zexcel_number_format. - - lo_style = wo_excel->add_new_style( ). - lo_style->font->bold = abap_true. - - CREATE OBJECT lo_style->borders->top. - lo_style->borders->top->border_style = zcl_excel_style_border=>c_border_thin. - lo_style->borders->top->border_color-rgb = zcl_excel_style_color=>c_black. - - CREATE OBJECT lo_style->borders->right. - lo_style->borders->right->border_style = zcl_excel_style_border=>c_border_none. - lo_style->borders->right->border_color-rgb = zcl_excel_style_color=>c_black. - - CREATE OBJECT lo_style->borders->down. - lo_style->borders->down->border_style = zcl_excel_style_border=>c_border_double. - lo_style->borders->down->border_color-rgb = zcl_excel_style_color=>c_black. - - CREATE OBJECT lo_style->borders->left. - lo_style->borders->left->border_style = zcl_excel_style_border=>c_border_none. - lo_style->borders->left->border_color-rgb = zcl_excel_style_color=>c_black. - - IF i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL. - lo_style->alignment->horizontal = i_alignment. - ENDIF. - IF i_inttype IS SUPPLIED AND i_inttype IS NOT INITIAL. - l_format = set_cell_format( i_inttype = i_inttype - i_decimals = i_decimals ) . - IF l_format IS NOT INITIAL. - lo_style->number_format->format_code = l_format. - ENDIF. - ENDIF. - - ro_style = lo_style . - -endmethod. - - - method CREATE_TABLE. - TYPES: BEGIN OF ts_output, - fieldname TYPE fieldname, - function TYPE funcname, - END OF ts_output. - - DATA: lo_data TYPE REF TO data. - DATA: lo_addit TYPE REF TO cl_abap_elemdescr, - lt_components_tab TYPE cl_abap_structdescr=>component_table, - ls_components TYPE abap_componentdescr, - lo_table TYPE REF TO cl_abap_tabledescr, - lo_struc TYPE REF TO cl_abap_structdescr, - lt_fieldcatalog TYPE zexcel_t_converter_fcat. - - FIELD-SYMBOLS: <fs_scat> TYPE zexcel_s_converter_fcat, - <fs_stab> TYPE ANY, - <fs_ttab> TYPE STANDARD TABLE, - <fs> TYPE ANY, - <fs_table> TYPE STANDARD TABLE. - - SORT wt_fieldcatalog BY position. - ASSIGN wo_table->* TO <fs_table>. - - READ TABLE <fs_table> ASSIGNING <fs_stab> INDEX 1. - IF sy-subrc EQ 0 . - LOOP AT wt_fieldcatalog ASSIGNING <fs_scat>. - ASSIGN COMPONENT <fs_scat>-columnname OF STRUCTURE <fs_stab> TO <fs>. - IF sy-subrc = 0. - ls_components-name = <fs_scat>-columnname. - TRY. - lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). - CATCH cx_sy_move_cast_error. - CLEAR lo_addit. - DELETE TABLE wt_fieldcatalog FROM <fs_scat>. - ENDTRY. - IF lo_addit IS BOUND. - ls_components-type = lo_addit . - INSERT ls_components INTO TABLE lt_components_tab. - ENDIF. - ENDIF. - ENDLOOP. - IF lt_components_tab IS NOT INITIAL. - "create new line type - TRY. - lo_struc = cl_abap_structdescr=>create( P_COMPONENTS = lt_components_tab - P_STRICT = abap_false ). - CATCH cx_sy_struct_creation. - RETURN. " We can not do anything in this case. - ENDTRY. - - lo_table = cl_abap_tabledescr=>create( lo_struc ). - - CREATE DATA wo_data TYPE HANDLE lo_table. - CREATE DATA lo_data TYPE HANDLE lo_struc. - - ASSIGN wo_data->* TO <fs_ttab>. - ASSIGN lo_data->* TO <fs_stab>. - LOOP AT <fs_table> ASSIGNING <fs>. - CLEAR <fs_stab>. - MOVE-CORRESPONDING <fs> TO <fs_stab>. - APPEND <fs_stab> TO <fs_ttab>. - ENDLOOP. - ENDIF. - ENDIF. - -endmethod. - - - - - - METHOD create_text_subtotal. - DATA: l_string(256) TYPE c, - l_func TYPE string. - - CASE i_totals_function. - WHEN zcl_excel_table=>totals_function_sum. " Total - l_func = 'Total'(003). - WHEN zcl_excel_table=>totals_function_min. " Minimum - l_func = 'Minimum'(004). - WHEN zcl_excel_table=>totals_function_max. " Maximum - l_func = 'Maximum'(005). - WHEN zcl_excel_table=>totals_function_average. " Mean Value - l_func = 'Average'(006). - WHEN zcl_excel_table=>totals_function_count. " Count - l_func = 'Count'(007). - WHEN OTHERS. - CLEAR l_func. - ENDCASE. - - WRITE i_value TO l_string. - - CONCATENATE l_string l_func INTO r_text SEPARATED BY space. - -ENDMETHOD. - - - - - - method CREATE_WORKSHEET. - DATA: l_freeze_col TYPE i. - DATA: l_guid TYPE oltpguid16. - - IF wo_data IS BOUND AND wo_worksheet IS BOUND. - - wo_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. " By default is on - - IF wt_fieldcatalog IS INITIAL. - set_fieldcatalog( ) . - ELSE. - clean_fieldcatalog( ) . - ENDIF. - - IF i_table = abap_true. - l_freeze_col = bind_table( i_style_table = i_style_table ) . - ELSE. -* Let's check for filter. - IF wt_filter IS NOT INITIAL. - wo_autofilter = wo_excel->add_new_autofilter( io_sheet = wo_worksheet ). - l_freeze_col = bind_cells( ) . - set_autofilter_area( ) . - ELSE. - l_freeze_col = bind_cells( ) . - ENDIF. - - ENDIF. - -* Check for freeze panes - IF ws_layout-is_fixed = abap_true. - IF l_freeze_col = 0. - l_freeze_col = w_col_int. - ENDIF. - wo_worksheet->freeze_panes( EXPORTING ip_num_columns = l_freeze_col - ip_num_rows = w_row_int ) . - ENDIF. - ENDIF. - -endmethod. - - - - - - method EXECUTE_CONVERTER. - DATA: lt_fieldcatalog TYPE zexcel_t_fieldcatalog, - ls_fieldcatalog TYPE zexcel_s_converter_fcat, - lo_if TYPE REF TO zif_excel_converter, - ls_types TYPE ts_alv_types, - lo_addit TYPE REF TO cl_abap_classdescr. - - IF io_object IS BOUND. - TRY. - lo_addit ?= cl_abap_typedescr=>describe_by_object_ref( io_object ). - CATCH cx_sy_move_cast_error. - RAISE EXCEPTION TYPE zcx_excel. - ENDTRY. - ls_types-seoclass = lo_addit->get_relative_name( ). - READ TABLE wt_objects INTO ls_types WITH TABLE KEY seoclass = ls_types-seoclass. - IF sy-subrc = 0. - CREATE OBJECT lo_if TYPE (ls_types-clsname). - - TRY. - lo_if->create_fieldcatalog( - EXPORTING - is_option = ws_option - io_object = io_object - it_table = it_table - IMPORTING - es_layout = ws_layout - et_fieldcatalog = wt_fieldcatalog - eo_table = wo_table - et_colors = wt_colors - et_filter = wt_filter - ). - ENDTRY. -* data lines of highest level. - IF ws_layout-max_subtotal_level > 0. - ADD 1 TO ws_layout-max_subtotal_level. - ENDIF. - ELSE. - RAISE EXCEPTION TYPE zcx_excel. - ENDIF. - ELSE. - REFRESH wt_fieldcatalog. - GET REFERENCE OF it_table INTO wo_table. - ENDIF. - -endmethod. - - - - - - - method GET_COLOR_STYLE. - DATA: ls_colors TYPE zexcel_s_converter_col, - ls_color_styles TYPE ts_color_styles, - lo_style TYPE REF TO zcl_excel_style. - - r_style = i_style. " Default we change nothing - - IF wt_colors IS NOT INITIAL. -* Full line has color - READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row - columnname = space. - IF sy-subrc = 0. - READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style - fontcolor = ls_colors-fontcolor - fillcolor = ls_colors-fillcolor. - IF sy-subrc = 0. - r_style = ls_color_styles-style_new->get_guid( ). - ELSE. - lo_style = create_color_style( i_style = i_style - is_colors = ls_colors ) . - r_style = lo_style->get_guid( ) . - ls_color_styles-guid_old = i_style. - ls_color_styles-fontcolor = ls_colors-fontcolor. - ls_color_styles-fillcolor = ls_colors-fillcolor. - ls_color_styles-style_new = lo_style. - INSERT ls_color_styles INTO TABLE wt_color_styles. - ENDIF. - ELSE. -* Only field has color - READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row - columnname = i_fieldname. - IF sy-subrc = 0. - READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style - fontcolor = ls_colors-fontcolor - fillcolor = ls_colors-fillcolor. - IF sy-subrc = 0. - r_style = ls_color_styles-style_new->get_guid( ). - ELSE. - lo_style = create_color_style( i_style = i_style - is_colors = ls_colors ) . - ls_color_styles-guid_old = i_style. - ls_color_styles-fontcolor = ls_colors-fontcolor. - ls_color_styles-fillcolor = ls_colors-fillcolor. - ls_color_styles-style_new = lo_style. - INSERT ls_color_styles INTO TABLE wt_color_styles. - r_style = ls_color_styles-style_new->get_guid( ). - ENDIF. - ELSE. - r_style = i_style. - ENDIF. - ENDIF. - ELSE. - r_style = i_style. - ENDIF. - -endmethod. - - - - - - method GET_FILE. - data: lo_excel_writer type ref to zif_excel_writer, - lo_excel type ref to zcl_excel. - - data: ls_seoclass type seoclass. - - - if wo_excel is bound. - create object lo_excel_writer type zcl_excel_writer_2007. - e_file = lo_excel_writer->write_file( wo_excel ). - - select single * into ls_seoclass - from seoclass - where clsname = 'CL_BCS_CONVERT'. - - if sy-subrc = 0. - call method (ls_seoclass-clsname)=>xstring_to_solix - exporting - iv_xstring = e_file - receiving - et_solix = et_file. - e_bytecount = xstrlen( e_file ). - else. - " Convert to binary - call function 'SCMS_XSTRING_TO_BINARY' - exporting - buffer = e_file - importing - output_length = e_bytecount - tables - binary_tab = et_file. - endif. - endif. - -endmethod. - - - - - method GET_FUNCTION_NUMBER. -*Number Function -*1 AVERAGE -*2 COUNT -*3 COUNTA -*4 MAX -*5 MIN -*6 PRODUCT -*7 STDEV -*8 STDEVP -*9 SUM -*10 VAR -*11 VARP - - case i_totals_function. - when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_SUM. " Total - r_function_number = 9. - when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MIN. " Minimum - r_function_number = 5. - when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MAX. " Maximum - r_function_number = 4. - when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_AVERAGE. " Mean Value - r_function_number = 1. - when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_count. " Count - r_function_number = 2. - when others. - clear r_function_number. - endcase. -endmethod. - - - - METHOD get_option. - - rs_option = ws_option. - -ENDMETHOD. - - - - - - - - method GET_STYLE. - DATA: ls_styles TYPE ts_styles, - lo_style TYPE REF TO zcl_excel_style. - - CLEAR r_style. - - READ TABLE wt_styles INTO ls_styles WITH TABLE KEY type = i_type - alignment = i_alignment - inttype = i_inttype - decimals = i_decimals. - IF sy-subrc = 0. - r_style = ls_styles-guid. - ELSE. - CASE i_type. - WHEN c_type_hdr. " Header - lo_style = create_style_hdr( i_alignment = i_alignment ). - WHEN c_type_str. "Stripped - lo_style = create_style_stripped( i_alignment = i_alignment - i_inttype = i_inttype - i_decimals = i_decimals ). - WHEN c_type_nor. "Normal - lo_style = create_style_normal( i_alignment = i_alignment - i_inttype = i_inttype - i_decimals = i_decimals ). - WHEN c_type_sub. "Subtotals - lo_style = create_style_subtotal( i_alignment = i_alignment - i_inttype = i_inttype - i_decimals = i_decimals ). - WHEN c_type_tot. "Totals - lo_style = create_style_total( i_alignment = i_alignment - i_inttype = i_inttype - i_decimals = i_decimals ). - ENDCASE. - IF lo_style IS NOT INITIAL. - r_style = lo_style->get_guid( ). - ls_styles-type = i_type. - ls_styles-alignment = i_alignment. - ls_styles-inttype = i_inttype. - ls_styles-decimals = i_decimals. - ls_styles-guid = r_style. - ls_styles-style = lo_style. - INSERT ls_styles INTO TABLE wt_styles. - ENDIF. - ENDIF. -endmethod. - - - METHOD init_option. - - ws_option-filter = abap_true. - ws_option-hidenc = abap_true. - ws_option-subtot = abap_true. - -ENDMETHOD. - - - - - - - METHOD loop_normal. - DATA: lo_data TYPE REF TO data, - l_row_header TYPE zexcel_cell_row VALUE '2', - l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', - l_row_int_start TYPE zexcel_cell_row, - l_row_int_end TYPE zexcel_cell_row, - l_row_int TYPE zexcel_cell_row, - l_col_int TYPE zexcel_cell_column, - l_col_alpha TYPE zexcel_cell_column_alpha, - l_col_alpha_start TYPE zexcel_cell_column_alpha, - l_cell_value TYPE zexcel_cell_value, - l_s_color TYPE abap_bool, - lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, - lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, - l_formula TYPE zexcel_cell_formula, - l_style TYPE zexcel_cell_style, - l_cells TYPE i, - l_count TYPE i, - l_table_row TYPE i. - - FIELD-SYMBOLS: <fs_stab> TYPE ANY, - <fs_tab> TYPE STANDARD TABLE, - <fs_sfcat> TYPE zexcel_s_converter_fcat, - <fs_fldval> TYPE ANY, - <fs_cell_value> TYPE zexcel_cell_value. - - ASSIGN wo_data->* TO <fs_tab> . - - DESCRIBE TABLE wt_fieldcatalog LINES l_cells. - DESCRIBE TABLE <fs_tab> LINES l_count. - l_cells = l_cells * l_count. - -* It is better to loop column by column - LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. - l_row_int = i_row_int. - l_col_int = i_col_int + <fs_sfcat>-position - 1. - -* Freeze panes - IF <fs_sfcat>-fix_column = abap_true. - ADD 1 TO r_freeze_col. - ENDIF. - l_s_color = abap_true. - - l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). - -* Only if the Header is required create it. - IF ws_option-hidehd IS INITIAL. - " First of all write column header - l_cell_value = <fs_sfcat>-scrtext_m. - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = l_cell_value - ip_style = <fs_sfcat>-style_hdr ). - ADD 1 TO l_row_int. - ENDIF. - LOOP AT <fs_tab> ASSIGNING <fs_stab>. - l_table_row = sy-tabix. -* Now the cell values - ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. -* Now let's write the cell values - IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. - l_style = get_color_style( i_row = l_table_row - i_fieldname = <fs_sfcat>-columnname - i_style = <fs_sfcat>-style_stripped ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = <fs_fldval> - ip_style = l_style ). - CLEAR l_s_color. - ELSE. - l_style = get_color_style( i_row = l_table_row - i_fieldname = <fs_sfcat>-columnname - i_style = <fs_sfcat>-style_normal ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = <fs_fldval> - ip_style = l_style ). - l_s_color = abap_true. - ENDIF. - READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row - columnname = <fs_sfcat>-columnname. - IF sy-subrc = 0. - wo_worksheet->get_cell( EXPORTING - ip_column = l_col_alpha - ip_row = l_row_int - IMPORTING - ep_value = l_cell_value ). - wo_autofilter->set_value( i_column = l_col_int - i_value = l_cell_value ). - ENDIF. - ADD 1 TO l_row_int. - ENDLOOP. -* Now let's check for optimized - IF <fs_sfcat>-is_optimized = abap_true . - lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). - lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . - ENDIF. -* Now let's check for visible - IF <fs_sfcat>-is_hidden = abap_true. - lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). - lo_col_dim->set_visible( ip_visible = abap_false ) . - ENDIF. -* Now let's check for total versus subtotal. - IF <fs_sfcat>-totals_function IS NOT INITIAL. - l_row_int_end = l_row_int - 1. - - l_formula = create_formular_total( i_row_int = l_row_int_end - i_column = l_col_alpha - i_totals_function = <fs_sfcat>-totals_function ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_formula = l_formula - ip_style = <fs_sfcat>-style_total ). - ENDIF. - ENDLOOP. -ENDMETHOD. - - - - - - - method LOOP_SUBTOTAL. - - DATA: lo_data TYPE REF TO data, - l_row_header TYPE zexcel_cell_row VALUE '2', - l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', - l_row_int_start TYPE zexcel_cell_row, - l_row_int_end TYPE zexcel_cell_row, - l_row_int TYPE zexcel_cell_row, - l_col_int TYPE zexcel_cell_column, - l_col_alpha TYPE zexcel_cell_column_alpha, - l_col_alpha_start TYPE zexcel_cell_column_alpha, - l_cell_value TYPE zexcel_cell_value, - l_s_color TYPE abap_bool, - lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, - lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, - l_formula TYPE zexcel_cell_formula, - l_style TYPE zexcel_cell_style, - l_subtotalled TYPE flag, - l_text TYPE string, - ls_sort_values TYPE ts_sort_values, - ls_subtotal_rows TYPE ts_subtotal_rows, - l_sort_level TYPE int4, - l_hidden TYPE int4, - l_line TYPE i, - l_guid TYPE guid_22, - l_tabix TYPE sy-tabix, - l_cells TYPE i, - l_count TYPE i, - l_table_row TYPE i, - lt_fcat TYPE zexcel_t_converter_fcat. - - FIELD-SYMBOLS: <fs_stab> TYPE ANY, - <fs_tab> TYPE STANDARD TABLE, - <fs_sfcat> TYPE zexcel_s_converter_fcat, - <fs_fldval> TYPE ANY, - <fs_sortval> TYPE ANY, - <fs_sortv> TYPE ts_sort_values, - <fs_cell_value> TYPE zexcel_cell_value. - - ASSIGN wo_data->* TO <fs_tab> . - - REFRESH: wt_sort_values, - wt_subtotal_rows. - - DESCRIBE TABLE wt_fieldcatalog LINES l_cells. - DESCRIBE TABLE <fs_tab> LINES l_count. - l_cells = l_cells * l_count. - - READ TABLE <fs_tab> ASSIGNING <fs_stab> INDEX 1. - IF sy-subrc = 0. - l_row_int = i_row_int + 1. - lt_fcat = wt_fieldcatalog. - SORT lt_fcat BY sort_level DESCENDING. - LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. - ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. - ls_sort_values-fieldname = <fs_sfcat>-columnname. - ls_sort_values-row_int = l_row_int. - ls_sort_values-sort_level = <fs_sfcat>-sort_level. - ls_sort_values-is_collapsed = <fs_sfcat>-is_collapsed. - CREATE DATA ls_sort_values-value LIKE <fs_fldval>. - ASSIGN ls_sort_values-value->* TO <fs_sortval>. - <fs_sortval> = <fs_fldval>. - INSERT ls_sort_values INTO TABLE wt_sort_values. - ENDLOOP. - ENDIF. - l_row_int = i_row_int. -* Let's check if we need to hide a sort level. - DESCRIBE TABLE wt_sort_values LINES l_line. - IF l_line <= 1. - CLEAR l_hidden. - ELSE. - LOOP AT wt_sort_values INTO ls_sort_values WHERE is_collapsed = abap_false. - IF l_hidden < ls_sort_values-sort_level. - l_hidden = ls_sort_values-sort_level. - ENDIF. - ENDLOOP. - ENDIF. - ADD 1 TO l_hidden. " As this is the first level we show. -* First loop without formular only addtional rows with subtotal text. - LOOP AT <fs_tab> ASSIGNING <fs_stab>. - ADD 1 TO l_row_int. " 1 is for header row. - l_row_int_start = l_row_int. - SORT lt_fcat BY sort_level DESCENDING. - LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. - l_col_int = i_col_int + <fs_sfcat>-position - 1. - l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). -* Now the cell values - ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. - IF sy-subrc = 0. - READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. - IF sy-subrc = 0. - ASSIGN <fs_sortv>-value->* TO <fs_sortval>. - IF <fs_sortval> <> <fs_fldval> OR <fs_sortv>-new = abap_true. -* First let's remmember the subtotal values as it has to appear later. - ls_subtotal_rows-row_int = l_row_int. - ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. - ls_subtotal_rows-columnname = <fs_sfcat>-columnname. - INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. -* Now let's write the subtotal line - l_cell_value = create_text_subtotal( i_value = <fs_sortval> - i_totals_function = <fs_sfcat>-totals_function ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = l_cell_value - ip_abap_type = cl_abap_typedescr=>typekind_string - ip_style = <fs_sfcat>-style_subtotal ). - lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). - lo_row_dim->set_outline_level( ip_outline_level = <fs_sfcat>-sort_level ) . - IF <fs_sfcat>-is_collapsed = abap_true. - IF <fs_sfcat>-sort_level > l_hidden. - lo_row_dim->set_visible( ip_visible = abap_false ) . - ENDIF. - lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . - ENDIF. -* Now let's change the key - ADD 1 TO l_row_int. - <fs_sortval> = <fs_fldval>. - <fs_sortv>-new = abap_false. - l_line = <fs_sortv>-sort_level. - LOOP AT wt_sort_values ASSIGNING <fs_sortv> WHERE sort_level >= l_line. - <fs_sortv>-row_int = l_row_int. - ENDLOOP. - ENDIF. - ENDIF. - ENDIF. - ENDLOOP. - ENDLOOP. - ADD 1 TO l_row_int. - l_row_int_start = l_row_int. - SORT lt_fcat BY sort_level DESCENDING. - LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. - l_col_int = i_col_int + <fs_sfcat>-position - 1. - l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). - READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. - IF sy-subrc = 0. - ASSIGN <fs_sortv>-value->* TO <fs_sortval>. - ls_subtotal_rows-row_int = l_row_int. - ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. - ls_subtotal_rows-columnname = <fs_sfcat>-columnname. - INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. -* First let's write the value as it has to appear. - l_cell_value = create_text_subtotal( i_value = <fs_sortval> - i_totals_function = <fs_sfcat>-totals_function ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = l_cell_value - ip_abap_type = cl_abap_typedescr=>typekind_string - ip_style = <fs_sfcat>-style_subtotal ). - - l_sort_level = <fs_sfcat>-sort_level. - lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). - lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . - IF <fs_sfcat>-is_collapsed = abap_true. - IF <fs_sfcat>-sort_level > l_hidden. - lo_row_dim->set_visible( ip_visible = abap_false ) . - ENDIF. - lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . - ENDIF. - ADD 1 TO l_row_int. - ENDIF. - ENDLOOP. -* Let's write the Grand total - l_sort_level = 0. - lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). - lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . -* lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . Not on grand total - - l_text = create_text_subtotal( i_value = 'Grand'(002) - i_totals_function = <fs_sfcat>-totals_function ). - - l_col_alpha_start = zcl_excel_common=>convert_column2alpha( i_col_int ). - wo_worksheet->set_cell( ip_column = l_col_alpha_start - ip_row = l_row_int - ip_value = l_text - ip_abap_type = cl_abap_typedescr=>typekind_string - ip_style = <fs_sfcat>-style_subtotal ). - -* It is better to loop column by column second time around -* Second loop with formular and data. - LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. - l_row_int = i_row_int. - l_col_int = i_col_int + <fs_sfcat>-position - 1. -* Freeze panes - IF <fs_sfcat>-fix_column = abap_true. - ADD 1 TO r_freeze_col. - ENDIF. - l_s_color = abap_true. - l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). - " First of all write column header - l_cell_value = <fs_sfcat>-scrtext_m. - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = l_cell_value - ip_abap_type = cl_abap_typedescr=>typekind_string - ip_style = <fs_sfcat>-style_hdr ). - ADD 1 TO l_row_int. - LOOP AT <fs_tab> ASSIGNING <fs_stab>. - l_table_row = sy-tabix. -* Now the cell values - ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. -* Let's check for subtotal lines - DO. - READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. - IF sy-subrc = 0. - IF <fs_sfcat>-is_subtotalled = abap_false AND - <fs_sfcat>-totals_function IS NOT INITIAL. - DO. - READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. - IF sy-subrc = 0. - l_row_int_start = ls_subtotal_rows-row_int_start. - l_row_int_end = l_row_int - 1. - - l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start - i_row_int_end = l_row_int_end - i_column = l_col_alpha - i_totals_function = <fs_sfcat>-totals_function ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_formula = l_formula - ip_style = <fs_sfcat>-style_subtotal ). - IF <fs_sfcat>-is_collapsed = abap_true. - lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). - lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). - IF <fs_sfcat>-sort_level > l_hidden. - lo_row_dim->set_visible( ip_visible = abap_false ) . - ENDIF. - ENDIF. - ADD 1 TO l_row_int. - ELSE. - EXIT. - ENDIF. - ENDDO. - ELSE. - ADD 1 TO l_row_int. - ENDIF. - ELSE. - EXIT. - ENDIF. - ENDDO. -* Let's set the row dimension values - lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). - lo_row_dim->set_outline_level( ip_outline_level = ws_layout-max_subtotal_level ) . - IF <fs_sfcat>-is_collapsed = abap_true. - lo_row_dim->set_visible( ip_visible = abap_false ) . - lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . - ENDIF. -* Now let's write the cell values - IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. - l_style = get_color_style( i_row = l_table_row - i_fieldname = <fs_sfcat>-columnname - i_style = <fs_sfcat>-style_stripped ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = <fs_fldval> - ip_style = l_style ). - CLEAR l_s_color. - ELSE. - l_style = get_color_style( i_row = l_table_row - i_fieldname = <fs_sfcat>-columnname - i_style = <fs_sfcat>-style_normal ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_value = <fs_fldval> - ip_style = l_style ). - l_s_color = abap_true. - ENDIF. - READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row - columnname = <fs_sfcat>-columnname. - IF sy-subrc = 0. - wo_worksheet->get_cell( EXPORTING - ip_column = l_col_alpha - ip_row = l_row_int - IMPORTING - ep_value = l_cell_value ). - wo_autofilter->set_value( i_column = l_col_int - i_value = l_cell_value ). - ENDIF. - ADD 1 TO l_row_int. - ENDLOOP. -* Let's check for subtotal lines - DO. - READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. - IF sy-subrc = 0. - IF <fs_sfcat>-is_subtotalled = abap_false AND - <fs_sfcat>-totals_function IS NOT INITIAL. - DO. - READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. - IF sy-subrc = 0. - l_row_int_start = ls_subtotal_rows-row_int_start. - l_row_int_end = l_row_int - 1. - - l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start - i_row_int_end = l_row_int_end - i_column = l_col_alpha - i_totals_function = <fs_sfcat>-totals_function ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_formula = l_formula - ip_style = <fs_sfcat>-style_subtotal ). - IF <fs_sfcat>-is_collapsed = abap_true. - lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). - lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). - ENDIF. - ADD 1 TO l_row_int. - ELSE. - EXIT. - ENDIF. - ENDDO. - ELSE. - ADD 1 TO l_row_int. - ENDIF. - ELSE. - EXIT. - ENDIF. - ENDDO. -* Now let's check for Grand total - IF <fs_sfcat>-is_subtotalled = abap_false AND - <fs_sfcat>-totals_function IS NOT INITIAL. - l_row_int_start = i_row_int + 1. - l_row_int_end = l_row_int - 1. - - l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start - i_row_int_end = l_row_int_end - i_column = l_col_alpha - i_totals_function = <fs_sfcat>-totals_function ). - wo_worksheet->set_cell( ip_column = l_col_alpha - ip_row = l_row_int - ip_formula = l_formula - ip_style = <fs_sfcat>-style_subtotal ). - ENDIF. -* Now let's check for optimized - IF <fs_sfcat>-is_optimized = abap_true. - lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). - lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . - ENDIF. -* Now let's check for visible - IF <fs_sfcat>-is_hidden = abap_true. - lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). - lo_col_dim->set_visible( ip_visible = abap_false ) . - ENDIF. - ENDLOOP. - -endmethod. - - - method OPEN_FILE. - data: l_bytecount type i, - lt_file type solix_tab, - l_dir type string, - l_sep type c. - - field-symbols: <fs_data> type any table. - - assign wo_data->* to <fs_data>. - -* catch zcx_excel . -*endtry. - if wo_excel is bound. - get_file( importing e_bytecount = l_bytecount - et_file = lt_file ) . - - l_dir = create_path( ) . - - cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount - filename = l_dir - filetype = 'BIN' - changing data_tab = lt_file ). - cl_gui_frontend_services=>execute( - exporting - document = l_dir -* application = -* parameter = -* default_directory = -* maximized = -* minimized = -* synchronous = -* operation = 'OPEN' - exceptions - cntl_error = 1 - error_no_gui = 2 - bad_parameter = 3 - file_not_found = 4 - path_not_found = 5 - file_extension_unknown = 6 - error_execute_failed = 7 - synchronous_failed = 8 - not_supported_by_gui = 9 - ). - if sy-subrc <> 0. - message id sy-msgid type sy-msgty number sy-msgno - with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. - endif. - - endif. - - -endmethod. - - - method SET_AUTOFILTER_AREA. - DATA: ls_area TYPE zexcel_s_autofilter_area, - l_lines TYPE i, - lt_values TYPE zexcel_t_autofilter_values, - ls_values TYPE zexcel_s_autofilter_values. - -* Let's check for filter. - IF wo_autofilter IS BOUND. - ls_area-row_start = 1. - lt_values = wo_autofilter->get_values( ) . - SORT lt_values BY column ASCENDING. - DESCRIBE TABLE lt_values LINES l_lines. - READ TABLE lt_values INTO ls_values INDEX 1. - IF sy-subrc = 0. - ls_area-col_start = ls_values-column. - ENDIF. - READ TABLE lt_values INTO ls_values INDEX l_lines. - IF sy-subrc = 0. - ls_area-col_end = ls_values-column. - ENDIF. - wo_autofilter->set_filter_area( is_area = ls_area ) . - ENDIF. - -endmethod. - - - - - - method SET_CELL_FORMAT. - DATA: l_format TYPE zexcel_number_format. - - CLEAR r_format. - CASE i_inttype. - WHEN cl_abap_typedescr=>typekind_date. - r_format = wo_worksheet->get_default_excel_date_format( ). - WHEN cl_abap_typedescr=>typekind_time. - r_format = wo_worksheet->get_default_excel_time_format( ). - WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. - IF i_decimals > 0 . - l_format = '#,##0.'. - DO i_decimals TIMES. - CONCATENATE l_format '0' INTO l_format. - ENDDO. - r_format = l_format. - ENDIF. - WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. - r_format = '#,##0'. - ENDCASE. - -endmethod. - - - METHOD set_fieldcatalog. - - DATA: lr_data TYPE REF TO data, - lo_structdescr TYPE REF TO cl_abap_structdescr, - lt_dfies TYPE ddfields, - ls_dfies TYPE dfies, - ls_fieldcatalog TYPE zexcel_s_fieldcatalog. - DATA: ls_fcat TYPE zexcel_s_converter_fcat. - - FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. - - ASSIGN wo_data->* TO <fs_tab> . - - CREATE DATA lr_data LIKE LINE OF <fs_tab>. - - lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). - - lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). - - LOOP AT lt_dfies INTO ls_dfies. - MOVE-CORRESPONDING ls_dfies TO ls_fcat. - ls_fcat-columnname = ls_dfies-fieldname. - INSERT ls_fcat INTO TABLE wt_fieldcatalog. - ENDLOOP. - - clean_fieldcatalog( ). - -ENDMETHOD. - - - - METHOD set_option. - - IF ws_indx-begdt IS INITIAL. - ws_indx-begdt = sy-datum. - ENDIF. - - ws_indx-aedat = sy-datum. - ws_indx-usera = sy-uname. - ws_indx-pgmid = sy-cprog. - - EXPORT p1 = is_option TO DATABASE indx(xl) FROM ws_indx ID ws_indx-srtfd. - - IF sy-subrc = 0. - ws_option = is_option. - ENDIF. - -ENDMETHOD. - - - - method WRITE_FILE. - data: l_bytecount type i, - lt_file type solix_tab, - l_dir type string. - - field-symbols: <fs_data> type any table. - - assign wo_data->* to <fs_data>. - -* catch zcx_excel . -*endtry. - if wo_excel is bound. - get_file( importing e_bytecount = l_bytecount - et_file = lt_file ) . - if i_path is initial. - l_dir = create_path( ) . - else. - l_dir = i_path. - endif. - cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount - filename = l_dir - filetype = 'BIN' - changing data_tab = lt_file ). - endif. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - method ZIF_EXCEL_CONVERTER~CAN_CONVERT_OBJECT. - data: lo_alv type REF TO cl_gui_alv_grid. - - try. - lo_alv ?= io_object. - catch cx_sy_move_cast_error . - raise exception type zcx_excel. - endtry. - -endmethod. - - - METHOD zif_excel_converter~create_fieldcatalog. - DATA: lo_alv TYPE REF TO cl_gui_alv_grid. - - TRY. - zif_excel_converter~can_convert_object( io_object = io_object ). - ENDTRY. - - ws_option = is_option. - - lo_alv ?= io_object. - - CLEAR: es_layout, - et_fieldcatalog. - - IF lo_alv IS BOUND. - lo_alv->get_frontend_fieldcatalog( IMPORTING et_fieldcatalog = wt_fcat ). - lo_alv->get_frontend_layout( IMPORTING es_layout = ws_layo ). - lo_alv->get_sort_criteria( IMPORTING et_sort = wt_sort ) . - lo_alv->get_filter_criteria( IMPORTING et_filter = wt_filt ) . - - apply_sort( EXPORTING it_table = it_table - IMPORTING eo_table = eo_table ) . - - get_color( EXPORTING io_table = eo_table - IMPORTING et_colors = et_colors ) . - - get_filter( IMPORTING et_filter = et_filter - CHANGING xo_table = eo_table ) . - - update_catalog( CHANGING cs_layout = es_layout - ct_fieldcatalog = et_fieldcatalog ). - ENDIF. -ENDMETHOD. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - method CONSTRUCTOR. - worksheet = io_sheet. -endmethod. - - - - method GET_FILTER_AREA. - - validate_area( ). - - rs_area = filter_area. - -endmethod. - - - - method GET_FILTER_RANGE. - DATA: l_row_start_c TYPE string, - l_row_end_c TYPE string, - l_col_start_c TYPE string, - l_col_end_c TYPE string, - l_value TYPE string. - - validate_area( ). - - l_row_end_c = filter_area-row_end. - CONDENSE l_row_end_c NO-GAPS. - - l_row_start_c = filter_area-row_start. - CONDENSE l_row_start_c NO-GAPS. - - l_col_start_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_start ) . - l_col_end_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_end ) . - - CONCATENATE l_col_start_c l_row_start_c ':' l_col_end_c l_row_end_c INTO r_range. - -endmethod. - - - - method GET_FILTER_REFERENCE. - DATA: l_row_start_c TYPE string, - l_row_end_c TYPE string, - l_col_start_c TYPE string, - l_col_end_c TYPE string, - l_value TYPE string. - - validate_area( ). - - l_row_end_c = filter_area-row_end. - CONDENSE l_row_end_c NO-GAPS. - - l_row_start_c = filter_area-row_start. - CONDENSE l_row_start_c NO-GAPS. - - l_col_start_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_start ) . - l_col_end_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_end ) . - l_value = worksheet->get_title( ) . - - r_ref = zcl_excel_common=>escape_string( ip_value = l_value ). - - CONCATENATE r_ref '!$' l_col_start_c '$' l_row_start_c ':$' l_col_end_c '$' l_row_end_c INTO r_ref. - -endmethod. - - - - method GET_VALUES. - - rt_filter = values. - -endmethod. - - - - method SET_FILTER_AREA. - - filter_area = is_area. - -endmethod. - - - - - method SET_VALUE. - DATA: ls_values TYPE zexcel_s_autofilter_values. - -* Checks a re missing. - ls_values-column = i_column. - ls_values-value = i_value. - - INSERT ls_values INTO TABLE values. -* Now we need to be sure we don't get the same value again. - DELETE ADJACENT DUPLICATES FROM values COMPARING column value. - -endmethod. - - - - method SET_VALUES. - -* Checks are missing. - values = it_values. - DELETE ADJACENT DUPLICATES FROM values COMPARING column value. - -endmethod. - - - method VALIDATE_AREA. - DATA: l_col TYPE zexcel_cell_column, - l_row TYPE zexcel_cell_row. - - l_row = worksheet->get_highest_row( ) . - l_col = worksheet->get_highest_column( ) . - - IF filter_area IS INITIAL. - filter_area-row_start = 1. - filter_area-col_start = 1. - filter_area-row_end = l_row . - filter_area-col_end = l_col . - ENDIF. - - IF filter_area-row_start < 1. - filter_area-row_start = 1. - ENDIF. - IF filter_area-col_start < 1. - filter_area-col_start = 1. - ENDIF. - IF filter_area-row_end > l_row OR - filter_area-row_end < 1. - filter_area-row_end = l_row. - ENDIF. - IF filter_area-col_end > l_col OR - filter_area-col_end < 1. - filter_area-col_end = l_col. - ENDIF. - IF filter_area-row_start >= filter_area-row_end. - filter_area-row_start = filter_area-row_end - 1. - IF filter_area-row_start < 1. - filter_area-row_start = 1. - filter_area-row_end = 2. - ENDIF. - ENDIF. - IF filter_area-col_start > filter_area-col_end. - filter_area-col_start = filter_area-col_end. - ENDIF. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature -TYPES: BEGIN OF ts_objects, - sheet_guid TYPE uuid, - autofilter TYPE REF TO zcl_excel_autofilter, - END OF ts_objects, - - tt_objects TYPE HASHED TABLE OF ts_objects WITH UNIQUE KEY sheet_guid. - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - METHOD add. - DATA: ls_autofilters TYPE ts_objects, - l_guid TYPE uuid. - l_guid = io_sheet->get_guid( ) . - READ TABLE autofilters INTO ls_autofilters WITH TABLE KEY sheet_guid = l_guid. - IF sy-subrc = 0. - ro_autofilter = ls_autofilters-autofilter. - ELSE. - CREATE OBJECT ro_autofilter - EXPORTING - io_sheet = io_sheet. - ls_autofilters-autofilter = ro_autofilter. - ls_autofilters-sheet_guid = l_guid. - INSERT ls_autofilters INTO TABLE autofilters . - ENDIF. -ENDMETHOD. - - - method CLEAR. - - REFRESH autofilters. - -endmethod. - - - - - method GET. - - DATA: ls_autofilters TYPE ts_objects. - - READ TABLE autofilters INTO ls_autofilters WITH TABLE KEY sheet_guid = i_sheet_guid. - IF sy-subrc = 0. - ro_autofilter = ls_autofilters-autofilter. - ELSE. - CLEAR ro_autofilter. - ENDIF. - -endmethod. - - - - method IS_EMPTY. - IF autofilters IS INITIAL. - r_empty = abap_true. - ENDIF. -endmethod. - - - - method REMOVE. - DATA: ls_autofilters TYPE ts_objects. - - DELETE autofilters WHERE sheet_guid = i_sheet_guid. - -endmethod. - - - - method SIZE. - DESCRIBE TABLE autofilters LINES r_size. -endmethod. - - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature -TYPES: BEGIN OF ts_col_converter, - col TYPE lvc_col, - int TYPE lvc_int, - inv TYPE lvc_inv, - fontcolor TYPE zexcel_style_color_argb, - fillcolor TYPE zexcel_style_color_argb, - END OF ts_col_converter, - - tt_col_converter TYPE HASHED TABLE OF ts_col_converter WITH UNIQUE KEY col int inv. - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - ABAP - KKBLO - - - - - - - - - - METHOD apply_sort. - DATA: lt_otab TYPE abap_sortorder_tab, - ls_otab TYPE abap_sortorder. - - FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE, - <fs_sort> TYPE lvc_s_sort. - - CREATE DATA eo_table LIKE it_table. - ASSIGN eo_table->* TO <fs_table>. - - <fs_table> = it_table. - - SORT wt_sort BY spos. - LOOP AT wt_sort ASSIGNING <fs_sort>. - IF <fs_sort>-up = abap_true. - ls_otab-name = <fs_sort>-fieldname. - ls_otab-descending = abap_false. -* ls_otab-astext = abap_true. " not only text fields - INSERT ls_otab INTO TABLE lt_otab. - ENDIF. - IF <fs_sort>-down = abap_true. - ls_otab-name = <fs_sort>-fieldname. - ls_otab-descending = abap_true. -* ls_otab-astext = abap_true. " not only text fields - INSERT ls_otab INTO TABLE lt_otab. - ENDIF. - ENDLOOP. - IF lt_otab IS NOT INITIAL. - SORT <fs_table> BY (lt_otab). - ENDIF. - -ENDMETHOD. - - - method CLASS_CONSTRUCTOR. -* let's fill the color conversion routines. - DATA: ls_color TYPE ts_col_converter. -* 0 all combination the same - ls_color-col = 0. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 0. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 0. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 0. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - -* Blue - ls_color-col = 1. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFB0E4FC'. " 176 228 252 blue - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 1. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FFB0E4FC'. " 176 228 252 blue - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 1. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FF5FCBFE'. " 095 203 254 Int blue - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 1. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FF5FCBFE'. " 095 203 254 - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 - INSERT ls_color INTO TABLE wt_colors. - -* Gray - ls_color-col = 2. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. - ls_color-fillcolor = 'FFE5EAF0'. " 229 234 240 gray - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 2. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FFE5EAF0'. " 229 234 240 gray - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 2. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFD8E8F4'. " 216 234 244 int gray - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 2. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FFD8E8F4'. " 216 234 244 int gray - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - -*Yellow - ls_color-col = 3. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFEFEB8'. " 254 254 184 yellow - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 3. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FFFEFEB8'. " 254 254 184 yellow - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 3. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFF9ED5D'. " 249 237 093 int yellow - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 3. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FFF9ED5D'. " 249 237 093 int yellow - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - -* light blue - ls_color-col = 4. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFCEE7FB'. " 206 231 251 light blue - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 4. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FFCEE7FB'. " 206 231 251 light blue - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 4. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FF9ACCEF'. " 154 204 239 int light blue - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 4. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FF9ACCEF'. " 154 204 239 int light blue - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - -* Green - ls_color-col = 5. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFCEF8AE'. " 206 248 174 Green - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 5. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FFCEF8AE'. " 206 248 174 Green - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 5. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FF7AC769'. " 122 199 105 int Green - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 5. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FF7AC769'. " 122 199 105 int Green - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - -* Red - ls_color-col = 6. - ls_color-int = 0. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFDBBBC'. " 253 187 188 Red - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 6. - ls_color-int = 0. - ls_color-inv = 1. - ls_color-fontcolor = 'FFFDBBBC'. " 253 187 188 Red - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 6. - ls_color-int = 1. - ls_color-inv = 0. - ls_color-fontcolor = 'FF000000'. " 000 000 000 Black - ls_color-fillcolor = 'FFFB6B6B'. " 251 107 107 int Red - INSERT ls_color INTO TABLE wt_colors. - - ls_color-col = 6. - ls_color-int = 1. - ls_color-inv = 1. - ls_color-fontcolor = 'FFFB6B6B'. " 251 107 107 int Red - ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White - INSERT ls_color INTO TABLE wt_colors. - -endmethod. - - - - - METHOD get_color. - DATA: ls_con_col TYPE zexcel_s_converter_col, - ls_color TYPE ts_col_converter, - l_line TYPE i, - l_color(4) TYPE c. - FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE, - <fs_stab> TYPE ANY, - <fs> TYPE ANY, - <fs_tcol> TYPE lvc_t_scol, - <fs_scol> TYPE lvc_s_scol. - -* Loop trough the table to set the color properties of each line. The color properties field is -* Char 4 and the characters is set as follows: -* Char 1 = C = This is a color property -* Char 2 = 6 = Color code (1 - 7) -* Char 3 = Intensified on/of = 1 = on -* Char 4 = Inverse display = 0 = of - - ASSIGN io_table->* TO <fs_tab>. - - IF ws_layo-info_fname IS NOT INITIAL OR - ws_layo-ctab_fname IS NOT INITIAL. - LOOP AT <fs_tab> ASSIGNING <fs_stab>. - l_line = sy-tabix. - IF ws_layo-info_fname IS NOT INITIAL. - ASSIGN COMPONENT ws_layo-info_fname OF STRUCTURE <fs_stab> TO <fs>. - IF sy-subrc = 0. - IF <fs> IS NOT INITIAL. - l_color = <fs>. - IF l_color(1) = 'C'. - READ TABLE wt_colors INTO ls_color WITH TABLE KEY col = l_color+1(1) - int = l_color+2(1) - inv = l_color+3(1). - IF sy-subrc = 0. - ls_con_col-rownumber = l_line. - ls_con_col-columnname = space. - ls_con_col-fontcolor = ls_color-fontcolor. - ls_con_col-fillcolor = ls_color-fillcolor. - INSERT ls_con_col INTO TABLE et_colors. - ENDIF. - ENDIF. - ENDIF. - ENDIF. - ENDIF. - IF ws_layo-ctab_fname IS NOT INITIAL. - ASSIGN COMPONENT ws_layo-ctab_fname OF STRUCTURE <fs_stab> TO <fs_tcol>. - IF sy-subrc = 0. - LOOP AT <fs_tcol> ASSIGNING <fs_scol>. - READ TABLE wt_colors INTO ls_color WITH TABLE KEY col = <fs_scol>-color-col - int = <fs_scol>-color-int - inv = <fs_scol>-color-inv. - IF sy-subrc = 0. - ls_con_col-rownumber = l_line. - ls_con_col-columnname = <fs_scol>-fname. - ls_con_col-fontcolor = ls_color-fontcolor. - ls_con_col-fillcolor = ls_color-fillcolor. - ls_con_col-nokeycol = <fs_scol>-nokeycol. - INSERT ls_con_col INTO TABLE et_colors. - ENDIF. - ENDLOOP. - ENDIF. - ENDIF. - ENDLOOP. - ENDIF. -ENDMETHOD. - - - - - METHOD get_filter. - DATA: ls_filt TYPE lvc_s_filt, - l_line TYPE i, - ls_filter TYPE zexcel_s_converter_fil. - DATA: lo_addit TYPE REF TO cl_abap_elemdescr, - lt_components_tab TYPE cl_abap_structdescr=>component_table, - ls_components TYPE abap_componentdescr, - lo_table TYPE REF TO cl_abap_tabledescr, - lo_struc TYPE REF TO cl_abap_structdescr, - lo_trange TYPE REF TO data, - lo_srange TYPE REF TO data, - lo_ltabdata TYPE REF TO data. - - FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE, - <fs_ltab> TYPE STANDARD TABLE, - <fs_stab> TYPE ANY, - <fs> TYPE ANY, - <fs1> TYPE ANY, - <fs_srange> TYPE ANY, - <fs_trange> TYPE STANDARD TABLE. - - IF ws_option-filter = abap_false. - REFRESH et_filter. - RETURN. - ENDIF. - - ASSIGN xo_table->* TO <fs_tab>. - - CREATE DATA lo_ltabdata LIKE <fs_tab>. - ASSIGN lo_ltabdata->* TO <fs_ltab>. - - LOOP AT wt_filt INTO ls_filt. - LOOP AT <fs_tab> ASSIGNING <fs_stab>. - l_line = sy-tabix. - ASSIGN COMPONENT ls_filt-fieldname OF STRUCTURE <fs_stab> TO <fs>. - IF sy-subrc = 0. - IF l_line = 1. - REFRESH lt_components_tab. - ls_components-name = 'SIGN'. - lo_addit ?= cl_abap_typedescr=>describe_by_data( ls_filt-sign ). - ls_components-type = lo_addit . - INSERT ls_components INTO TABLE lt_components_tab. - ls_components-name = 'OPTION'. - lo_addit ?= cl_abap_typedescr=>describe_by_data( ls_filt-option ). - ls_components-type = lo_addit . - INSERT ls_components INTO TABLE lt_components_tab. - ls_components-name = 'LOW'. - lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). - ls_components-type = lo_addit . - INSERT ls_components INTO TABLE lt_components_tab. - ls_components-name = 'HIGH'. - lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). - ls_components-type = lo_addit . - INSERT ls_components INTO TABLE lt_components_tab. - "create new line type - TRY. - lo_struc = cl_abap_structdescr=>create( p_components = lt_components_tab - p_strict = abap_false ). - CATCH cx_sy_struct_creation. - CONTINUE. - ENDTRY. - lo_table = cl_abap_tabledescr=>create( lo_struc ). - - CREATE DATA lo_trange TYPE HANDLE lo_table. - CREATE DATA lo_srange TYPE HANDLE lo_struc. - - ASSIGN lo_trange->* TO <fs_trange>. - ASSIGN lo_srange->* TO <fs_srange>. - ENDIF. - REFRESH <fs_trange>. - ASSIGN COMPONENT 'SIGN' OF STRUCTURE <fs_srange> TO <fs1>. - <fs1> = ls_filt-sign. - ASSIGN COMPONENT 'OPTION' OF STRUCTURE <fs_srange> TO <fs1>. - <fs1> = ls_filt-option. - ASSIGN COMPONENT 'LOW' OF STRUCTURE <fs_srange> TO <fs1>. - <fs1> = ls_filt-low. - ASSIGN COMPONENT 'HIGH' OF STRUCTURE <fs_srange> TO <fs1>. - <fs1> = ls_filt-high. - INSERT <fs_srange> INTO TABLE <fs_trange>. - IF <fs> IN <fs_trange>. - IF ws_option-filter = abap_true. - ls_filter-rownumber = l_line. - ls_filter-columnname = ls_filt-fieldname. - INSERT ls_filter INTO TABLE et_filter. - ELSE. - INSERT <fs_stab> INTO TABLE <fs_ltab>. - ENDIF. - ENDIF. - ENDIF. - ENDLOOP. - IF ws_option-filter = abap_undefined. - <fs_tab> = <fs_ltab>. - REFRESH <fs_ltab>. - ENDIF. - ENDLOOP. - -ENDMETHOD. - - - - - METHOD update_catalog. - DATA: ls_fieldcatalog TYPE zexcel_s_converter_fcat, - ls_ref TYPE salv_s_ddic_reference, - ls_fcat TYPE lvc_s_fcat, - ls_sort TYPE lvc_s_sort, - l_decimals TYPE lvc_decmls. - - FIELD-SYMBOLS: <fs_scat> TYPE zexcel_s_converter_fcat. - - IF ws_layo-zebra IS NOT INITIAL. - cs_layout-is_stripped = abap_true. - ENDIF. - IF ws_layo-no_keyfix IS INITIAL OR - ws_layo-no_keyfix = '0'. - cs_layout-is_fixed = abap_true. - ENDIF. - - LOOP AT wt_fcat INTO ls_fcat. - CLEAR: ls_fieldcatalog, - l_decimals. - CASE ws_option-hidenc. - WHEN abap_false. " We make hiden columns visible - CLEAR ls_fcat-no_out. - WHEN abap_true. -* We convert column and hide it. - WHEN abap_undefined. "We don't convert hiden columns - IF ls_fcat-no_out = abap_true. - ls_fcat-tech = abap_true. - ENDIF. - ENDCASE. - IF ls_fcat-tech = abap_false. - ls_fieldcatalog-tabname = ls_fcat-tabname. - ls_fieldcatalog-fieldname = ls_fcat-fieldname . - ls_fieldcatalog-columnname = ls_fcat-fieldname . - ls_fieldcatalog-position = ls_fcat-col_pos. - ls_fieldcatalog-col_id = ls_fcat-col_id. - ls_fieldcatalog-convexit = ls_fcat-convexit. - ls_fieldcatalog-inttype = ls_fcat-inttype. - ls_fieldcatalog-scrtext_s = ls_fcat-scrtext_s . - ls_fieldcatalog-scrtext_m = ls_fcat-scrtext_m . - ls_fieldcatalog-scrtext_l = ls_fcat-scrtext_l. - l_decimals = ls_fcat-decimals_o. - IF l_decimals IS NOT INITIAL. - ls_fieldcatalog-decimals = l_decimals. - ELSE. - ls_fieldcatalog-decimals = ls_fcat-decimals . - ENDIF. - CASE ws_option-subtot. - WHEN abap_false. " We ignore subtotals - CLEAR ls_fcat-do_sum. - WHEN abap_true. " We convert subtotals and detail - - WHEN abap_undefined. " We should only take subtotals and displayed detail -* for now abap_true - ENDCASE. - CASE ls_fcat-do_sum. - WHEN abap_true. - ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_sum. - WHEN 'A'. - ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_min. - WHEN 'B' . - ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_max. - WHEN 'C' . - ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_average. - WHEN OTHERS. - CLEAR ls_fieldcatalog-totals_function . - ENDCASE. - ls_fieldcatalog-fix_column = ls_fcat-fix_column. - IF ws_layo-cwidth_opt IS INITIAL. - IF ls_fcat-col_opt IS NOT INITIAL. - ls_fieldcatalog-is_optimized = abap_true. - ENDIF. - ELSE. - ls_fieldcatalog-is_optimized = abap_true. - ENDIF. - IF ls_fcat-no_out IS NOT INITIAL. - ls_fieldcatalog-is_hidden = abap_true. - ls_fieldcatalog-position = ls_fieldcatalog-col_id. " We hide based on orginal data structure - ENDIF. -* Alignment in each cell - CASE ls_fcat-just. - WHEN 'R'. - ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_right. - WHEN 'L'. - ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_left. - WHEN 'C'. - ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_center. - WHEN OTHERS. - CLEAR ls_fieldcatalog-alignment. - ENDCASE. -* Check for subtotals. - READ TABLE wt_sort INTO ls_sort WITH KEY fieldname = ls_fcat-fieldname. - IF sy-subrc = 0 AND ws_option-subtot <> abap_false. - ls_fieldcatalog-sort_level = 0 . -* IF ls_fieldcatalog-totals_function IS INITIAL. " Not clear why not -* CLEAR ls_fieldcatalog-is_subtotalled. -* ELSE. - ls_fieldcatalog-is_subtotalled = ls_sort-subtot. -* ENDIF. - ls_fieldcatalog-is_collapsed = ls_sort-expa. - IF ls_fieldcatalog-is_subtotalled = abap_true. - ls_fieldcatalog-sort_level = ls_sort-spos. - ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_sum. " we need function for text - ENDIF. - ENDIF. - APPEND ls_fieldcatalog TO ct_fieldcatalog. - ENDIF. - ENDLOOP. - - SORT ct_fieldcatalog BY sort_level ASCENDING. - cs_layout-max_subtotal_level = 0. - LOOP AT ct_fieldcatalog ASSIGNING <fs_scat> WHERE sort_level > 0. - cs_layout-max_subtotal_level = cs_layout-max_subtotal_level + 1. - <fs_scat>-sort_level = cs_layout-max_subtotal_level. - ENDLOOP. - -ENDMETHOD. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - METHOD ZIF_EXCEL_CONVERTER~CAN_CONVERT_OBJECT. - - DATA: lo_result TYPE REF TO cl_salv_ex_result_data_table. - - TRY. - lo_result ?= io_object. - CATCH cx_sy_move_cast_error . - RAISE EXCEPTION TYPE zcx_excel. - ENDTRY. - -ENDMETHOD. - - - METHOD zif_excel_converter~create_fieldcatalog. - DATA: lo_result TYPE REF TO cl_salv_ex_result_data_table, - lo_ex_cm TYPE REF TO cl_salv_ex_cm, - lo_data TYPE REF TO data. - - FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. - - TRY. - zif_excel_converter~can_convert_object( io_object = io_object ). - ENDTRY. - - ws_option = is_option. - - lo_result ?= io_object. - - CLEAR: es_layout, - et_fieldcatalog. - - IF lo_result IS BOUND. - lo_data = get_table( io_object = lo_result->r_model->r_data ). - IF lo_data IS BOUND. - ASSIGN lo_data->* TO <fs_table> . - - lo_ex_cm ?= lo_result->r_model->r_model. - ws_layo = lo_ex_cm->s_layo. -* T_DRDN Instance Attribute Public Type LVC_T_DROP - wt_fcat = lo_ex_cm->t_fcat. - wt_filt = lo_ex_cm->t_filt. -* T_HYPE Instance Attribute Public Type LVC_T_HYPE -* T_SELECTED_CELLS Instance Attribute Public Type LVC_T_CELL -* T_SELECTED_COLUMNS Instance Attribute Public Type LVC_T_COL - wt_sort = lo_ex_cm->t_sort. - - apply_sort( EXPORTING it_table = <fs_table> - IMPORTING eo_table = eo_table ) . - - get_color( EXPORTING io_table = eo_table - IMPORTING et_colors = et_colors ) . - - get_filter( IMPORTING et_filter = et_filter - CHANGING xo_table = eo_table ) . - - update_catalog( CHANGING cs_layout = es_layout - ct_fieldcatalog = et_fieldcatalog ). - else. -* We have a problem and should stop here. - ENDIF. - ENDIF. -ENDMETHOD. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - method GET_TABLE. - DATA: lo_object TYPE REF TO object, - ls_seoclass TYPE seoclass, - l_method TYPE string. - - SELECT SINGLE * INTO ls_seoclass - FROM seoclass - WHERE clsname = 'IF_SALV_BS_DATA_SOURCE'. - - IF sy-subrc = 0. - l_method = 'GET_TABLE_REF'. - lo_object ?= io_object. - CALL METHOD lo_object->(l_method) - RECEIVING - value = ro_data. - ELSE. - l_method = 'GET_REF_TO_TABLE'. - lo_object ?= io_object. - CALL METHOD lo_object->(l_method) - RECEIVING - value = ro_data. - ENDIF. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - METHOD ZIF_EXCEL_CONVERTER~CAN_CONVERT_OBJECT. - - DATA: lo_result TYPE REF TO cl_salv_wd_result_data_table. - - TRY. - lo_result ?= io_object. - CATCH cx_sy_move_cast_error . - RAISE EXCEPTION TYPE zcx_excel. - ENDTRY. - -ENDMETHOD. - - - METHOD zif_excel_converter~create_fieldcatalog. - DATA: lo_result TYPE REF TO cl_salv_wd_result_data_table, - lo_data TYPE REF TO data. - - FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. - - TRY. - zif_excel_converter~can_convert_object( io_object = io_object ). - ENDTRY. - - ws_option = is_option. - - lo_result ?= io_object. - - CLEAR: es_layout, - et_fieldcatalog. - - break rturnheim. - - IF lo_result IS BOUND. - lo_data = get_table( io_object = lo_result->r_model->r_data ). - IF lo_data IS BOUND. - ASSIGN lo_data->* TO <fs_table> . - - wo_config ?= lo_result->r_model->r_model. - - IF wo_config IS BOUND. - wt_fields = wo_config->if_salv_wd_field_settings~get_fields( ) . - wt_columns = wo_config->if_salv_wd_column_settings~get_columns( ) . - ENDIF. - - create_wt_fcat( io_table = lo_data ). - create_wt_sort( ). - create_wt_filt( ). - - apply_sort( EXPORTING it_table = <fs_table> - IMPORTING eo_table = eo_table ) . - -* get_color( EXPORTING io_table = eo_table -* IMPORTING et_colors = et_colors ) . - - get_filter( IMPORTING et_filter = et_filter - CHANGING xo_table = eo_table ) . - - update_catalog( CHANGING cs_layout = es_layout - ct_fieldcatalog = et_fieldcatalog ). - ELSE. -* We have a problem and should stop here - ENDIF. - ENDIF. -ENDMETHOD. - - - - METHOD create_wt_fcat. - DATA: lr_data TYPE REF TO data, - lo_structdescr TYPE REF TO cl_abap_structdescr, - lt_dfies TYPE ddfields, - ls_dfies TYPE dfies, - lv_sytabix TYPE sytabix. - - DATA: ls_fcat TYPE lvc_s_fcat. - - FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. - - ASSIGN io_table->* TO <fs_tab> . - CREATE DATA lr_data LIKE LINE OF <fs_tab>. - - lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). - - lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). - - loop at lt_dfies into ls_dfies. - MOVE-CORRESPONDING ls_dfies TO ls_fcat. -* ls_fcat-columnname = ls_dfies-fieldname. - ls_fcat-col_pos = ls_dfies-position. - ls_fcat-key = ls_dfies-keyflag. - get_fields_info( CHANGING xs_fcat = ls_fcat ) . - - ls_fcat-col_opt = abap_true. - - get_columns_info( CHANGING xs_fcat = ls_fcat ) . - - INSERT ls_fcat INTO TABLE wt_fcat. - endloop. - -ENDMETHOD. - - - METHOD create_wt_filt. -* No neeed for superclass. -* Only for WD - DATA: lt_otab TYPE abap_sortorder_tab, - ls_otab TYPE abap_sortorder. - DATA: lt_filters TYPE salv_wd_t_filter_rule_ref, - ls_filt TYPE lvc_s_filt. - - FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref, - <fs_filter> TYPE salv_wd_s_filter_rule_ref. - - LOOP AT wt_fields ASSIGNING <fs_fields>. - REFRESH lt_filters. - lt_filters = <fs_fields>-r_field->if_salv_wd_filter~get_filter_rules( ) . - LOOP AT lt_filters ASSIGNING <fs_filter>. - ls_filt-fieldname = <fs_fields>-fieldname. - IF <fs_filter>-r_filter_rule->get_included( ) = abap_true. - ls_filt-sign = 'I'. - ELSE. - ls_filt-sign = 'E'. - ENDIF. - ls_filt-option = <fs_filter>-r_filter_rule->get_operator( ). - ls_filt-high = <fs_filter>-r_filter_rule->get_high_value( ) . - ls_filt-low = <fs_filter>-r_filter_rule->get_low_value( ) . - INSERT ls_filt INTO TABLE wt_filt. - ENDLOOP. - ENDLOOP. - -ENDMETHOD. - - - METHOD create_wt_sort. - DATA: lo_sort TYPE REF TO cl_salv_wd_sort_rule, - l_sort_order TYPE salv_wd_constant, - ls_sort TYPE lvc_s_sort. - - FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. - - LOOP AT wt_fields ASSIGNING <fs_fields>. - lo_sort = <fs_fields>-r_field->if_salv_wd_sort~get_sort_rule( ) . - IF lo_sort IS BOUND. - l_sort_order = lo_sort->get_sort_order( ). - IF l_sort_order <> if_salv_wd_c_sort=>sort_order. - CLEAR ls_sort. - ls_sort-spos = lo_sort->get_sort_position( ). - ls_sort-fieldname = <fs_fields>-fieldname. -* ls_sort-GROUP - ls_sort-subtot = lo_sort->get_group_aggregation( ). -* ls_sort-COMP -* ls_sort-EXPA -* ls_sort-SELTEXT -* ls_sort-OBLIGATORY -* ls_sort-LEVEL -* ls_sort-NO_OUT - IF l_sort_order = if_salv_wd_c_sort=>sort_order_ascending. - ls_sort-up = abap_true. - ELSE. - ls_sort-down = abap_true. - ENDIF. - INSERT ls_sort INTO TABLE wt_sort. - ENDIF. - ENDIF. - ENDLOOP. - -ENDMETHOD. - - - - METHOD get_columns_info. - DATA: l_numc2 TYPE salv_wd_constant. - - - FIELD-SYMBOLS: <fs_column> TYPE salv_wd_s_column_ref. - - READ TABLE wt_columns ASSIGNING <fs_column> WITH KEY id = xs_fcat-fieldname . - IF sy-subrc = 0. - xs_fcat-col_pos = <fs_column>-r_column->get_position( ) . - l_numc2 = <fs_column>-r_column->get_fixed_position( ). - IF l_numc2 = '02'. - xs_fcat-fix_column = abap_true . - ENDIF. - l_numc2 = <fs_column>-r_column->get_visible( ). - IF l_numc2 = '01'. - xs_fcat-no_out = abap_true . - ENDIF. - ENDIF. - -ENDMETHOD. - - - - METHOD get_fields_info. - DATA: lo_aggr TYPE REF TO cl_salv_wd_aggr_rule, - l_aggrtype TYPE salv_wd_constant. - - FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. - - READ TABLE wt_fields ASSIGNING <fs_fields> WITH KEY fieldname = xs_fcat-fieldname. - IF sy-subrc = 0. - lo_aggr = <fs_fields>-r_field->if_salv_wd_aggr~get_aggr_rule( ) . - IF lo_aggr IS BOUND. - l_aggrtype = lo_aggr->get_aggregation_type( ) . - CASE l_aggrtype. - WHEN if_salv_wd_c_aggregation=>aggrtype_total. - xs_fcat-do_sum = abap_true. - WHEN if_salv_wd_c_aggregation=>aggrtype_minimum. - xs_fcat-do_sum = 'A'. - WHEN if_salv_wd_c_aggregation=>aggrtype_maximum . - xs_fcat-do_sum = 'B'. - WHEN if_salv_wd_c_aggregation=>aggrtype_average . - xs_fcat-do_sum = 'C'. - WHEN OTHERS. - CLEAR xs_fcat-do_sum . - ENDCASE. - ENDIF. - ENDIF. - -ENDMETHOD. - - - - *"* use this source file for the definition and implementation of -*"* local helper classes, interface definitions and type -*"* declarations - *"* use this source file for any type of declarations (class -*"* definitions, interfaces or type declarations) you need for -*"* components in the private section - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - method LOAD_VBAPROJECT. - - DATA lv_content TYPE xstring. - - lv_content = me->get_from_zip_archive( ip_path ). - - ip_excel->zif_excel_book_vba_project~set_vbaproject( lv_content ). - -endmethod. - - - method LOAD_WORKBOOK. - super->load_workbook( EXPORTING iv_workbook_full_filename = iv_workbook_full_filename - io_excel = io_excel ). - - CONSTANTS: lc_vba_project TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject'. - - DATA: rels_workbook_path TYPE string, - rels_workbook TYPE REF TO if_ixml_document, - path TYPE string, - node TYPE REF TO if_ixml_element, - workbook TYPE REF TO if_ixml_document, - stripped_name TYPE chkfile, - dirname TYPE string, - relationship TYPE t_relationship, - fileversion TYPE t_fileversion, - workbookpr TYPE t_workbookpr. - - FIELD-SYMBOLS: <worksheet> TYPE t_relationship. - - CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' - EXPORTING - full_name = iv_workbook_full_filename - IMPORTING - stripped_name = stripped_name - file_path = dirname. - - " Read Workbook Relationships - CONCATENATE dirname '_rels/' stripped_name '.rels' - INTO rels_workbook_path. - - rels_workbook = me->get_ixml_from_zip_archive( rels_workbook_path ). - - node ?= rels_workbook->find_from_name( 'Relationship' ). - WHILE node IS BOUND. - me->fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). - - CASE relationship-type. - WHEN lc_vba_project. - " Read VBA binary - CONCATENATE dirname relationship-target INTO path. - me->load_vbaproject( ip_path = path - ip_excel = io_excel ). - WHEN OTHERS. - ENDCASE. - - node ?= node->get_next( ). - ENDWHILE. - - " Read Workbook codeName - workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). - node ?= workbook->find_from_name( 'fileVersion' ). - IF node IS BOUND. - - fill_struct_from_attributes( EXPORTING ip_element = node - CHANGING cp_structure = fileversion ). - - io_excel->zif_excel_book_vba_project~set_codename( fileversion-codename ). - ENDIF. - - " Read Workbook codeName - workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). - node ?= workbook->find_from_name( 'workbookPr' ). - IF node IS BOUND. - - fill_struct_from_attributes( EXPORTING ip_element = node - CHANGING cp_structure = workbookpr ). - - io_excel->zif_excel_book_vba_project~set_codename_pr( workbookpr-codename ). - ENDIF. - -endmethod. - - - method LOAD_WORKSHEET. - - super->load_worksheet( EXPORTING ip_path = ip_path - io_worksheet = io_worksheet ). - - DATA: path TYPE string, - node TYPE REF TO if_ixml_element, - worksheet TYPE REF TO if_ixml_document, - sheetpr TYPE t_sheetpr. - - -* " Read Workbook codeName -* workbook = me->get_ixml_from_zip_archive( ip_path ). -* node ?= workbook->find_from_name( 'fileVersion' ). -* IF node IS BOUND. -* -* fill_struct_from_attributes( EXPORTING ip_element = node -* CHANGING cp_structure = fileversion ). -* -* IO_WORKSHEET->zif_excel_book_vba_project~set_codename( fileversion-codename ). -* ENDIF. - - " Read Workbook codeName - worksheet = me->get_ixml_from_zip_archive( ip_path ). - node ?= worksheet->find_from_name( 'sheetPr' ). - IF node IS BOUND. - - fill_struct_from_attributes( EXPORTING ip_element = node - CHANGING cp_structure = sheetpr ). - - io_worksheet->zif_excel_sheet_vba_project~set_codename_pr( sheetpr-codename ). - ENDIF. -endmethod. - - - - *"* use this source file for the definition and implementation of -*"* local helper classes, interface definitions and type -*"* declarations - *"* use this source file for any type of declarations (class -*"* definitions, interfaces or type declarations) you need for -*"* components in the private section - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - *"* use this source file for the definition and implementation of -*"* local helper classes, interface definitions and type -*"* declarations - *"* use this source file for any type of declarations (class -*"* definitions, interfaces or type declarations) you need for -*"* components in the private section - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - method CONSTRUCTOR. - " default Excel palette based on - " http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.indexedcolors.aspx - - APPEND '00000000' TO colors. - APPEND '00FFFFFF' TO colors. - APPEND '00FF0000' TO colors. - APPEND '0000FF00' TO colors. - APPEND '000000FF' TO colors. - APPEND '00FFFF00' TO colors. - APPEND '00FF00FF' TO colors. - APPEND '0000FFFF' TO colors. - APPEND '00000000' TO colors. - APPEND '00FFFFFF' TO colors. - - APPEND '00FF0000' TO colors. - APPEND '0000FF00' TO colors. - APPEND '000000FF' TO colors. - APPEND '00FFFF00' TO colors. - APPEND '00FF00FF' TO colors. - APPEND '0000FFFF' TO colors. - APPEND '00800000' TO colors. - APPEND '00008000' TO colors. - APPEND '00000080' TO colors. - APPEND '00808000' TO colors. - - APPEND '00800080' TO colors. - APPEND '00008080' TO colors. - APPEND '00C0C0C0' TO colors. - APPEND '00808080' TO colors. - APPEND '009999FF' TO colors. - APPEND '00993366' TO colors. - APPEND '00FFFFCC' TO colors. - APPEND '00CCFFFF' TO colors. - APPEND '00660066' TO colors. - APPEND '00FF8080' TO colors. - - APPEND '000066CC' TO colors. - APPEND '00CCCCFF' TO colors. - APPEND '00000080' TO colors. - APPEND '00FF00FF' TO colors. - APPEND '00FFFF00' TO colors. - APPEND '0000FFFF' TO colors. - APPEND '00800080' TO colors. - APPEND '00800000' TO colors. - APPEND '00008080' TO colors. - APPEND '000000FF' TO colors. - - APPEND '0000CCFF' TO colors. - APPEND '00CCFFFF' TO colors. - APPEND '00CCFFCC' TO colors. - APPEND '00FFFF99' TO colors. - APPEND '0099CCFF' TO colors. - APPEND '00FF99CC' TO colors. - APPEND '00CC99FF' TO colors. - APPEND '00FFCC99' TO colors. - APPEND '003366FF' TO colors. - APPEND '0033CCCC' TO colors. - - APPEND '0099CC00' TO colors. - APPEND '00FFCC00' TO colors. - APPEND '00FF9900' TO colors. - APPEND '00FF6600' TO colors. - APPEND '00666699' TO colors. - APPEND '00969696' TO colors. - APPEND '00003366' TO colors. - APPEND '00339966' TO colors. - APPEND '00003300' TO colors. - APPEND '00333300' TO colors. - - APPEND '00993300' TO colors. - APPEND '00993366' TO colors. - APPEND '00333399' TO colors. - APPEND '00333333' TO colors. - -endmethod. - - - - - - method GET_COLOR. - DATA: lv_index type i. - - lv_index = ip_index + 1. - READ TABLE colors INTO ep_color INDEX lv_index. - IF sy-subrc <> 0. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Invalid color index'. - ENDIF. -endmethod. - - - - method GET_COLORS. - ep_colors = colors. -endmethod. - - - - method IS_MODIFIED. - ep_modified = modified. -endmethod. - - - - - method SET_COLOR. - DATA: lv_index TYPE i. - - FIELD-SYMBOLS: <lv_color> LIKE LINE OF colors. - - lv_index = ip_index + 1. - READ TABLE colors ASSIGNING <lv_color> INDEX lv_index. - IF sy-subrc <> 0. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Invalid color index'. - ENDIF. - - IF <lv_color> <> ip_color. - modified = abap_true. - <lv_color> = ip_color. - ENDIF. - -endmethod. - - - - - *"* use this source file for the definition and implementation of -*"* local helper classes, interface definitions and type -*"* declarations - *"* use this source file for any type of declarations (class -*"* definitions, interfaces or type declarations) you need for -*"* components in the private section - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - METHOD if_message~get_longtext. - - IF me->error IS NOT INITIAL - OR me->syst_at_raise IS NOT INITIAL. -*--------------------------------------------------------------------* -* If message was supplied explicitly use this as longtext as well -*--------------------------------------------------------------------* - result = me->get_text( ). - ELSE. -*--------------------------------------------------------------------* -* otherwise use standard method to derive text -*--------------------------------------------------------------------* - super->if_message~get_longtext( EXPORTING - preserve_newlines = preserve_newlines - RECEIVING - result = result ). - ENDIF. -ENDMETHOD. - - - METHOD if_message~get_text. - - IF me->error IS NOT INITIAL. -*--------------------------------------------------------------------* -* If message was supplied explicitly use this -*--------------------------------------------------------------------* - result = me->error . - ELSEIF me->syst_at_raise IS NOT INITIAL. -*--------------------------------------------------------------------* -* If message was supplied by syst create messagetext now -*--------------------------------------------------------------------* - MESSAGE ID syst_at_raise-msgid TYPE syst_at_raise-msgty NUMBER syst_at_raise-msgno - WITH syst_at_raise-msgv1 syst_at_raise-msgv2 syst_at_raise-msgv3 syst_at_raise-msgv4 - INTO result. - ELSE. -*--------------------------------------------------------------------* -* otherwise use standard method to derive text -*--------------------------------------------------------------------* - CALL METHOD super->if_message~get_text - RECEIVING - result = result. - ENDIF. -ENDMETHOD. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - method CONSTRUCTOR. -endmethod. - - - - method GET_STRUCTURE. -*initialize colors to 'not set' - es_fill-left_color-indexed = zcl_excel_style_color=>c_indexed_not_set. - es_fill-left_color-theme = zcl_excel_style_color=>c_theme_not_set. - es_fill-right_color-indexed = zcl_excel_style_color=>c_indexed_not_set. - es_fill-right_color-theme = zcl_excel_style_color=>c_theme_not_set. - es_fill-top_color-indexed = zcl_excel_style_color=>c_indexed_not_set. - es_fill-top_color-theme = zcl_excel_style_color=>c_theme_not_set. - es_fill-bottom_color-indexed = zcl_excel_style_color=>c_indexed_not_set. - es_fill-bottom_color-theme = zcl_excel_style_color=>c_theme_not_set. - es_fill-diagonal_color-indexed = zcl_excel_style_color=>c_indexed_not_set. - es_fill-diagonal_color-theme = zcl_excel_style_color=>c_theme_not_set. - -* Check if all borders is set otherwise check single border - IF me->allborders IS BOUND. - es_fill-left_color = me->allborders->border_color. - es_fill-left_style = me->allborders->border_style. - es_fill-right_color = me->allborders->border_color. - es_fill-right_style = me->allborders->border_style. - es_fill-top_color = me->allborders->border_color. - es_fill-top_style = me->allborders->border_style. - es_fill-bottom_color = me->allborders->border_color. - es_fill-bottom_style = me->allborders->border_style. - ELSE. - IF me->left IS BOUND. - es_fill-left_color = me->left->border_color. - es_fill-left_style = me->left->border_style. - ENDIF. - IF me->right IS BOUND. - es_fill-right_color = me->right->border_color. - es_fill-right_style = me->right->border_style. - ENDIF. - IF me->top IS BOUND. - es_fill-top_color = me->top->border_color. - es_fill-top_style = me->top->border_style. - ENDIF. - IF me->down IS BOUND. - es_fill-bottom_color = me->down->border_color. - es_fill-bottom_style = me->down->border_style. - ENDIF. - ENDIF. - -* Check if diagonal is set - IF me->diagonal IS BOUND. - es_fill-diagonal_color = me->diagonal->border_color. - es_fill-diagonal_style = me->diagonal->border_style. - CASE me->diagonal_mode. - WHEN 1. - es_fill-diagonalup = 1. - es_fill-diagonaldown = 0. - WHEN 2. - es_fill-diagonalup = 0. - es_fill-diagonaldown = 1. - WHEN 3. - es_fill-diagonalup = 1. - es_fill-diagonaldown = 1. - WHEN OTHERS. - es_fill-diagonalup = 0. - es_fill-diagonaldown = 0. - ENDCASE. - ENDIF. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - - -endmethod. - - - - - - - method CREATE_NEW_ARGB. - - - CONCATENATE zcl_excel_style_color=>c_alpha ip_red ip_green ip_blu INTO ep_color_argb. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - - DATA: ls_iconset TYPE zexcel_conditional_iconset. - ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights. - ls_iconset-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. - ls_iconset-cfvo1_value = '0'. - ls_iconset-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. - ls_iconset-cfvo2_value = '20'. - ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. - ls_iconset-cfvo3_value = '40'. - ls_iconset-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. - ls_iconset-cfvo4_value = '60'. - ls_iconset-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. - ls_iconset-cfvo5_value = '80'. - - - me->rule = zcl_excel_style_conditional=>c_rule_none. -* me->iconset->operator = zcl_excel_style_conditional=>c_operator_none. - me->mode_iconset = ls_iconset. - me->priority = 1. - -* inizialize dimension range - me->stop_cell-cell_row = 1. - me->stop_cell-cell_column = 1. - me->start_cell-cell_row = 1. - me->start_cell-cell_column = 1. -endmethod. - - - - method GET_DIMENSION_RANGE. - IF stop_cell EQ start_cell. "only one cell - ep_dimension_range = start_cell-cell_coords. - ELSE. - CONCATENATE start_cell-cell_coords ':' stop_cell-cell_coords INTO ep_dimension_range. - ENDIF. -endmethod. - - - - - - - method SET_RANGE. - DATA: lv_column TYPE zexcel_cell_column, - lv_row_alpha TYPE string. - - lv_column = zcl_excel_common=>convert_column2int( ip_stop_column ). - stop_cell-cell_row = 1. - stop_cell-cell_column = lv_column. - lv_row_alpha = ip_stop_row. - SHIFT lv_row_alpha RIGHT DELETING TRAILING space. - SHIFT lv_row_alpha LEFT DELETING LEADING space. - CONCATENATE ip_stop_column lv_row_alpha INTO stop_cell-cell_coords. - - lv_column = zcl_excel_common=>convert_column2int( ip_start_column ). - start_cell-cell_row = 1. - start_cell-cell_column = lv_column. - lv_row_alpha = ip_start_row. - SHIFT lv_row_alpha RIGHT DELETING TRAILING space. - SHIFT lv_row_alpha LEFT DELETING LEADING space. - CONCATENATE ip_start_column lv_row_alpha INTO start_cell-cell_coords. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - filltype = zcl_excel_style_fill=>c_fill_none. - fgcolor-theme = zcl_excel_style_color=>c_theme_not_set. - fgcolor-indexed = zcl_excel_style_color=>c_indexed_not_set. - bgcolor-theme = zcl_excel_style_color=>c_theme_not_set. - bgcolor-indexed = zcl_excel_style_color=>c_indexed_sys_foreground. - rotation = 0. -endmethod. - - - - method GET_STRUCTURE. - es_fill-rotation = me->rotation. - es_fill-filltype = me->filltype. - es_fill-fgColor = me->fgColor. - es_fill-bgColor = me->bgColor. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CALCULATE_TEXT_WIDTH. - " Addition to solve issue #120, contribution by Stefan Schmöcker - r_width = strlen( i_text ). - " use scale factor based on default 11 - " ( don't know where defaultsetting is stored currently ) - r_width = r_width * me->size / 11. -endmethod. - - - method CONSTRUCTOR. - me->color-rgb = zcl_excel_style_color=>c_black. - me->color-theme = zcl_excel_style_color=>c_theme_not_set. - me->color-indexed = zcl_excel_style_color=>c_indexed_not_set. - me->scheme = zcl_excel_style_font=>c_scheme_minor. - me->underline_mode = zcl_excel_style_font=>c_underline_single. -endmethod. - - - - method GET_STRUCTURE. - - es_font-bold = me->bold. - es_font-italic = me->italic. - es_font-underline = me->underline. - es_font-underline_mode = me->underline_mode. - es_font-strikethrough = me->strikethrough. - es_font-size = me->size. - es_font-color = me->color. - es_font-name = me->name. - es_font-family = me->family. - es_font-scheme = me->scheme. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - format_code = me->c_format_general. -endmethod. - - - - method GET_STRUCTURE. - ep_number_format-numfmt = me->format_code. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - method CONSTRUCTOR. - locked = me->c_protection_locked. - hidden = me->c_protection_unhidden. -endmethod. - - - - method GET_STRUCTURE. - ep_protection-locked = me->locked. - ep_protection-hidden = me->hidden. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CONSTRUCTOR. - -endmethod. - - - - METHOD get_bottom_row_integer. - DATA: lv_table_lines TYPE i. - FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. - - IF settings-bottom_right_row IS NOT INITIAL. -* ev_row = zcl_excel_common=>convert_column2int( settings-bottom_right_row ). " del issue #246 - ev_row = settings-bottom_right_row . " ins issue #246 - EXIT. - ENDIF. - - ASSIGN table_data->* TO <fs_table>. - DESCRIBE TABLE <fs_table> LINES lv_table_lines. - IF lv_table_lines = 0. - lv_table_lines = 1. "table needs at least 1 data row - ENDIF. - - ev_row = settings-top_left_row + lv_table_lines. - - IF me->has_totals( ) = abap_true." ???? AND ip_include_totals_row = abap_true. - ADD 1 TO ev_row. - ENDIF. -ENDMETHOD. - - - - method GET_ID. - ov_id = id. -endmethod. - - - - method GET_NAME. - - IF me->name IS INITIAL. - me->name = zcl_excel_common=>number_to_excel_string( ip_value = me->id ). - CONCATENATE 'table' me->name INTO me->name. - ENDIF. - - ov_name = me->name. -endmethod. - - - - - method GET_REFERENCE. - DATA: lv_column TYPE zexcel_cell_column, - lv_table_lines TYPE i, - lv_right_column TYPE zexcel_cell_column_alpha, - ls_field_catalog TYPE zexcel_s_fieldcatalog, - lv_bottom_row TYPE zexcel_cell_row, - lv_top_row_string(10) TYPE c, - lv_bottom_row_string(10) TYPE c. - - FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. - -*column - lv_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). - lv_table_lines = 0. - LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. - ADD 1 TO lv_table_lines. - ENDLOOP. - lv_column = lv_column + lv_table_lines - 1. - lv_right_column = zcl_excel_common=>convert_column2alpha( lv_column ). - -*row - ASSIGN table_data->* TO <fs_table>. - DESCRIBE TABLE <fs_table> LINES lv_table_lines. - IF lv_table_lines = 0. - lv_table_lines = 1. "table needs at least 1 data row - ENDIF. - lv_bottom_row = settings-top_left_row + lv_table_lines . - - IF me->has_totals( ) = abap_true AND ip_include_totals_row = abap_true. - ADD 1 TO lv_bottom_row. - ENDIF. - - lv_top_row_string = zcl_excel_common=>number_to_excel_string( settings-top_left_row ). - lv_bottom_row_string = zcl_excel_common=>number_to_excel_string( lv_bottom_row ). - - CONCATENATE settings-top_left_column lv_top_row_string - ':' - lv_right_column lv_bottom_row_string INTO ov_reference. - -endmethod. - - - - - METHOD get_right_column_integer. - DATA: lv_column TYPE zexcel_cell_column, - lv_table_lines TYPE i, - ls_field_catalog TYPE zexcel_s_fieldcatalog. - - IF settings-bottom_right_column IS NOT INITIAL. - ev_column = zcl_excel_common=>convert_column2int( settings-bottom_right_column ). - EXIT. - ENDIF. - - ev_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). - LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. - ADD 1 TO ev_column. - ENDLOOP. - -ENDMETHOD. - - - - - - method GET_TOTALS_FORMULA. - CONSTANTS: lc_function_id_sum TYPE string VALUE '109', - lc_function_id_min TYPE string VALUE '105', - lc_function_id_max TYPE string VALUE '104', - lc_function_id_count TYPE string VALUE '103', - lc_function_id_average TYPE string VALUE '101'. - - DATA: lv_function_id TYPE string. - - CASE ip_function. - WHEN zcl_excel_table=>totals_function_sum. - lv_function_id = lc_function_id_sum. - - WHEN zcl_excel_table=>totals_function_min. - lv_function_id = lc_function_id_min. - - WHEN zcl_excel_table=>totals_function_max. - lv_function_id = lc_function_id_max. - - WHEN zcl_excel_table=>totals_function_count. - lv_function_id = lc_function_id_count. - - WHEN zcl_excel_table=>totals_function_average. - lv_function_id = lc_function_id_average. - - WHEN zcl_excel_table=>totals_function_custom. " issue #292 - RETURN. - - WHEN OTHERS. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Invalid totals formula. See ZCL_ for possible values'. - ENDCASE. - - CONCATENATE 'SUBTOTAL(' lv_function_id ',[' ip_column '])' INTO ep_formula. -endmethod. - - - - method HAS_TOTALS. - DATA: ls_field_catalog TYPE zexcel_s_fieldcatalog. - - ep_result = abap_false. - - LOOP AT fieldcat INTO ls_field_catalog. - IF ls_field_catalog-totals_function IS NOT INITIAL. - ep_result = abap_true. - EXIT. - ENDIF. - ENDLOOP. - -endmethod. - - - - method SET_DATA. - GET REFERENCE OF ir_data INTO me->table_data. -endmethod. - - - - method SET_ID. - id = iv_id. -endmethod. - - - - - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - -*&---------------------------------------------------------------------* -*& Class (Implementation) C_OI_PROXY_ERROR -*&---------------------------------------------------------------------* -CLASS c_oi_proxy_error IMPLEMENTATION. - METHOD constructor. -* IMPORTING object_name TYPE c -* method_name TYPE c. - error_nr = ret_call_not_flushed. - me->i_oi_error~error_code = c_oi_errors=>ret_call_not_flushed. - me->i_oi_error~is_flushed = ' '. - me->i_oi_error~has_failed = 'X'. - me->i_oi_error~has_succeeded = ' '. - me->message_id = 'SOFFICEINTEGRATION'. - me->message_nr = '899'. - me->param1 = object_name. - me->param2 = method_name. - ENDMETHOD. "constructor - - METHOD i_oi_error~flush_error. - IF error_nr EQ 0. - me->i_oi_error~error_code = c_oi_errors=>ret_ok. - me->i_oi_error~is_flushed = 'X'. - me->i_oi_error~has_failed = ' '. - me->i_oi_error~has_succeeded = 'X'. - me->message_id = ''. - me->message_nr = '000'. - CALL METHOD c_oi_errors=>translate_proxy_error_code - EXPORTING - errorcode = error_nr - IMPORTING - retcode = me->i_oi_error~error_code. - ELSEIF error_nr EQ ret_call_not_flushed. - "call still not flushed - CALL METHOD c_oi_errors=>translate_proxy_error_code - EXPORTING - errorcode = error_nr - errorstring = me->param2 "method name - objectname = me->param1 - IMPORTING - retcode = me->i_oi_error~error_code. - ELSE. - me->i_oi_error~is_flushed = 'X'. - me->i_oi_error~has_succeeded = ' '. - me->i_oi_error~has_failed = 'X'. - CALL METHOD c_oi_errors=>translate_proxy_error_code - EXPORTING - errorcode = error_nr - errorstring = error_string - IMPORTING - retcode = me->i_oi_error~error_code. - CALL METHOD c_oi_errors=>get_message - IMPORTING - message_id = me->message_id - message_number = me->message_nr - param1 = me->param1 - param2 = me->param2 - param3 = me->param3 - param4 = me->param4. - ENDIF. - ENDMETHOD. "i_oi_error~flush_error - - METHOD i_oi_error~raise_message. -* IMPORTING type TYPE c. -* EXCEPTIONS message_raised flush_failed. - IF me->i_oi_error~has_succeeded IS INITIAL. - IF NOT me->i_oi_error~is_flushed IS INITIAL. - MESSAGE ID message_id TYPE type - NUMBER message_nr WITH param1 param2 param3 param4 - RAISING message_raised. - ELSE. - RAISE flush_failed. - ENDIF. - ENDIF. - ENDMETHOD. "i_oi_error~raise_message - - METHOD i_oi_error~get_message. -* EXPORTING message_id TYPE c -* message_number TYPE c -* param1 TYPE c -* param2 TYPE c -* param3 TYPE c -* param4 TYPE c. - param1 = me->param1. param2 = me->param2. - param3 = me->param3. param4 = me->param4. - - message_id = me->message_id. - message_number = me->message_nr. - ENDMETHOD. "i_oi_error~get_message -ENDCLASS. "C_OI_PROXY_ERROR - -*&---------------------------------------------------------------------* -*& Class (Implementation) CL_GRID_ACCESSION -*&---------------------------------------------------------------------* -CLASS lcl_gui_alv_grid IMPLEMENTATION. - - METHOD get_alv_attributes. - CREATE DATA et_table LIKE io_grid->mt_outtab. - et_table = io_grid->mt_outtab. - ENDMETHOD. "get_data - -ENDCLASS. "CL_GRID_ACCESSION - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature -TYPE-POOLS: sydes. -TYPE-POOLS: slis. -*--------------------------------------------------------------------* -* CLASS c_oi_proxy_error -*--------------------------------------------------------------------* -* use for method bind_ALV -*--------------------------------------------------------------------* -CLASS c_oi_proxy_error DEFINITION. - PUBLIC SECTION. - INTERFACES: i_oi_error. - DATA: error_nr TYPE i. - DATA: error_string TYPE sy-msgv1. - - METHODS: constructor IMPORTING object_name TYPE c - method_name TYPE c. - PRIVATE SECTION. - CONSTANTS: - ret_call_not_flushed TYPE i VALUE -999999. - - DATA: message_id TYPE sy-msgid, - message_nr TYPE sy-msgno, - param1 TYPE sy-msgv1, - param2 TYPE sy-msgv2, - param3 TYPE sy-msgv3, - param4 TYPE sy-msgv4. -ENDCLASS. "c_oi_proxy_error DEFINITION - -*--------------------------------------------------------------------* -* CLASS lcl_gui_alv_grid -*--------------------------------------------------------------------* -* to get protected attribute and method of cl_gui_alv_grid -* use for method bind_ALV -*--------------------------------------------------------------------* -CLASS lcl_gui_alv_grid DEFINITION INHERITING FROM cl_gui_alv_grid. - - PUBLIC SECTION. -* get ALV grid data - METHODS: get_alv_attributes - IMPORTING - io_grid TYPE REF TO cl_gui_alv_grid " ALV grid - EXPORTING - et_table TYPE REF TO data. " dta table - -ENDCLASS. "lcl_gui_alv_grid DEFINITION - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - - - - - - - - - - - - - - - ABAP - SLIS - SOI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - METHOD zif_excel_sheet_printsettings~clear_print_repeat_columns. - -*--------------------------------------------------------------------* -* adjust internal representation -*--------------------------------------------------------------------* - CLEAR: me->print_title_col_from, - me->print_title_col_to . - - -*--------------------------------------------------------------------* -* adjust corresponding range -*--------------------------------------------------------------------* - me->print_title_set_range( ). - - -ENDMETHOD. - - - METHOD zif_excel_sheet_printsettings~clear_print_repeat_rows. - -*--------------------------------------------------------------------* -* adjust internal representation -*--------------------------------------------------------------------* - CLEAR: me->print_title_row_from, - me->print_title_row_to . - - -*--------------------------------------------------------------------* -* adjust corresponding range -*--------------------------------------------------------------------* - me->print_title_set_range( ). - - -ENDMETHOD. - - - METHOD zif_excel_sheet_printsettings~get_print_repeat_columns. - ev_columns_from = me->print_title_col_from. - ev_columns_to = me->print_title_col_to. -ENDMETHOD. - - - METHOD zif_excel_sheet_printsettings~get_print_repeat_rows. - ev_rows_from = me->print_title_row_from. - ev_rows_to = me->print_title_row_to. -ENDMETHOD. - - - METHOD zif_excel_sheet_printsettings~set_print_repeat_columns. -*--------------------------------------------------------------------* -* issue#235 - repeat rows/columns -* - Stefan Schmöcker, 2012-12-02 -*--------------------------------------------------------------------* - - DATA: lv_col_from_int TYPE i, - lv_col_to_int TYPE i, - lv_errormessage TYPE string. - - DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, - lo_range TYPE REF TO zcl_excel_range. - - - lv_col_from_int = zcl_excel_common=>convert_column2int( iv_columns_from ). - lv_col_to_int = zcl_excel_common=>convert_column2int( iv_columns_to ). - -*--------------------------------------------------------------------* -* Check if valid range is supplied -*--------------------------------------------------------------------* - IF lv_col_from_int < 1. - lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - IF lv_col_from_int > lv_col_to_int. - lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - -*--------------------------------------------------------------------* -* adjust internal representation -*--------------------------------------------------------------------* - me->print_title_col_from = iv_columns_from. - me->print_title_col_to = iv_columns_to. - - -*--------------------------------------------------------------------* -* adjust corresponding range -*--------------------------------------------------------------------* - me->print_title_set_range( ). - -ENDMETHOD. - - - METHOD zif_excel_sheet_printsettings~set_print_repeat_rows. -*--------------------------------------------------------------------* -* issue#235 - repeat rows/columns -* - Stefan Schmöcker, 2012-12-02 -*--------------------------------------------------------------------* - - DATA: lv_errormessage TYPE string. - - DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, - lo_range TYPE REF TO zcl_excel_range. - - - -*--------------------------------------------------------------------* -* Check if valid range is supplied -*--------------------------------------------------------------------* - IF iv_rows_from < 1. - lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - IF iv_rows_from > iv_rows_to. - lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - -*--------------------------------------------------------------------* -* adjust internal representation -*--------------------------------------------------------------------* - me->print_title_row_from = iv_rows_from. - me->print_title_row_to = iv_rows_to. - - -*--------------------------------------------------------------------* -* adjust corresponding range -*--------------------------------------------------------------------* - me->print_title_set_range( ). - - -ENDMETHOD. - - - method ZIF_EXCEL_SHEET_PROPERTIES~GET_STYLE. - IF zif_excel_sheet_properties~style IS NOT INITIAL. - ep_style = zif_excel_sheet_properties~style. - ELSE. - ep_style = me->excel->get_default_style( ). - ENDIF. -endmethod. - - - method ZIF_EXCEL_SHEET_PROPERTIES~INITIALIZE. - - zif_excel_sheet_properties~show_zeros = zif_excel_sheet_properties=>c_showzero. - zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. - zif_excel_sheet_properties~summaryright = zif_excel_sheet_properties=>c_right_on. - -* inizialize zoomscale values - ZIF_EXCEL_SHEET_PROPERTIES~zoomscale = 100. - ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_normal = 100. - ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_pagelayoutview = 100 . - ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_sheetlayoutview = 100 . -endmethod. - - - method ZIF_EXCEL_SHEET_PROPERTIES~SET_STYLE. - zif_excel_sheet_properties~style = ip_style. -endmethod. - - - method ZIF_EXCEL_SHEET_PROTECTION~INITIALIZE. - - me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_unprotected. - CLEAR me->zif_excel_sheet_protection~password. - me->zif_excel_sheet_protection~auto_filter = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~delete_columns = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~delete_rows = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~format_cells = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~format_columns = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~format_rows = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~insert_columns = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~insert_hyperlinks = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~insert_rows = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_noactive. -* me->zif_excel_sheet_protection~password = zif_excel_sheet_protection=>c_noactive. "issue #68 - me->zif_excel_sheet_protection~pivot_tables = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~select_locked_cells = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~select_unlocked_cells = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_noactive. - me->zif_excel_sheet_protection~sort = zif_excel_sheet_protection=>c_noactive. - -endmethod. - - - method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME. - me->zif_excel_sheet_vba_project~codename = ip_codename. -endmethod. - - - method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME_PR. - me->zif_excel_sheet_vba_project~codename_pr = ip_codename_pr. -endmethod. - - - - method ADD_DRAWING. - CASE ip_drawing->get_type( ). - WHEN zcl_excel_drawing=>type_image. - drawings->include( ip_drawing ). - WHEN zcl_excel_drawing=>type_chart. - charts->include( ip_drawing ). - ENDCASE. -endmethod. - - - - method ADD_NEW_CONDITIONAL_STYLE. - - CREATE OBJECT eo_conditional_style. - conditional_styles->add( eo_conditional_style ). -endmethod. - - - - method ADD_NEW_DATA_VALIDATION. - - CREATE OBJECT eo_data_validation. - data_validations->add( eo_data_validation ). -endmethod. - - - - method ADD_NEW_RANGE. -* Create default blank range - CREATE OBJECT eo_range. - ranges->add( eo_range ). -endmethod. - - - - - - - - - method BIND_ALV. - data: lo_converter type ref to zcl_excel_converter. - - create object lo_converter. - - try. - lo_converter->convert( - exporting - io_alv = io_alv - it_table = it_table - i_row_int = i_top - i_column_int = i_left - i_table = abap_true - i_style_table = table_style - io_worksheet = me - changing - co_excel = excel ). - catch zcx_excel . - endtry. - -endmethod. - - - - - - - - - - - - - - - - - - - - - - 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. - data: wa_DOC_HANDLE Type CNTL_HANDLE. - -* 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: <f_collect00> type standard table. - field-symbols: <f_collect01> type standard table. - field-symbols: <f_collect02> type standard table. - field-symbols: <f_collect03> type standard table. - field-symbols: <f_collect04> type standard table. - field-symbols: <f_collect05> type standard table. - field-symbols: <f_collect06> type standard table. - field-symbols: <f_collect07> type standard table. - field-symbols: <f_collect08> type standard table. - field-symbols: <f_collect09> type standard table. - -* table before append subtotal lines - field-symbols: <f_alv_tab> 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: <f_excel_tab> type standard table. - field-symbols: <f_excel_line> type any. - -* dyn subtotal tables - field-symbols: <f_collect_tab> type standard table. - field-symbols: <f_collect_line> type any. - - field-symbols: <f_filter_idx_line> like line of LT_FILTER_IDX_KKBLO. - field-symbols: <f_fieldcat_line> like line of LT_FIELDCAT_KKBLO. - field-symbols: <f_grouplevels_line> like line of LT_GROUPLEVELS_KKBLO. - field-symbols: <f_line> 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: <f_excel_column> type any. - field-symbols: <f_fcat_column> type any. - -* Data for session 4: write to excel -* ------------------------------------------ - - data: data_starting_at type i value 1. - data: data_ending_at type i value -1. - 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: <line> type any. - field-symbols: <item> 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 <f_alv_tab>. - -* 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 <f_collect00>. - assign lt_collect01->* to <f_collect01>. - assign lt_collect02->* to <f_collect02>. - assign lt_collect03->* to <f_collect03>. - assign lt_collect04->* to <f_collect04>. - assign lt_collect05->* to <f_collect05>. - assign lt_collect06->* to <f_collect06>. - assign lt_collect07->* to <f_collect07>. - assign lt_collect08->* to <f_collect08>. - assign lt_collect09->* to <f_collect09>. - -* 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 = <f_alv_tab> - 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 <f_ALV_TAB>. - assign lt_excel->* to <f_excel_tab>. - - loop at <f_alv_tab> assigning <f_line>. - l_save_index = sy-tabix. - -* filter base on filter index table - - read table LT_FILTER_IDX_KKBLO assigning <f_filter_idx_line> - with key index = l_save_index - binary search. - if sy-subrc ne 0. - append <f_line> to <f_excel_tab>. - endif. - -* append subtotal lines - - read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> - with key index_to = l_save_index - binary search. - if sy-subrc = 0. - l_tabix = sy-tabix. - do. - if <f_grouplevels_line>-subtot eq 'X' and - <f_grouplevels_line>-hide_level is initial and - <f_grouplevels_line>-cindex_from ne 0. - -* dynamic append subtotal line to excel table base on grouplevel table -* ex <f_GROUPLEVELS_line>-level = 1 -* then <f_collect_tab> = '<F_COLLECT01>' - - l_collect = <f_grouplevels_line>-level. - condense l_collect. - concatenate '<F_COLLECT0' - l_collect '>' -* '->*' - into l_collect. - - assign (l_collect) to <f_collect_tab>. - -* incase there're more than 1 total line of group, at the same level -* for example: subtotal of multi currency - - LOOP AT <f_collect_tab> assigning <f_collect_line>. - IF sy-tabix between <f_grouplevels_line>-cindex_from - and <f_grouplevels_line>-cindex_to. - - - append <f_collect_line> to <f_excel_tab>. - -* 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: <f_collect_tab>. - unassign: <f_collect_line>. - clear: l_collect. - endif. - -* check next subtotal level of group - - unassign: <f_grouplevels_line>. - add 1 to l_tabix. - - read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> - index l_tabix. - if sy-subrc ne 0 - or <f_grouplevels_line>-index_to ne l_save_index. - exit. - endif. - - unassign: - <f_collect_tab>, - <f_collect_line>. - - enddo. - endif. - - clear: - l_tabix, - l_save_index. - - unassign: - <f_filter_idx_line>, - <f_grouplevels_line>. - - endloop. - -* free local data - - unassign: - <f_line>, - <f_collect_tab>, - <f_collect_line>, - <f_fieldcat_line>. - -* append grand total line - - IF <f_collect00> is assigned. - assign <f_collect00> to <f_collect_tab>. - if <f_collect_tab> is not initial. - LOOP AT <f_collect_tab> assigning <f_collect_line>. - - append <f_collect_line> to <f_excel_tab>. - -* 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, - <f_collect00>, - <f_collect01>, - <f_collect02>, - <f_collect03>, - <f_collect04>, - <f_collect05>, - <f_collect06>, - <f_collect07>, - <f_collect08>, - <f_collect09>. - - unassign: - <f_collect00>, - <f_collect01>, - <f_collect02>, - <f_collect03>, - <f_collect04>, - <f_collect05>, - <f_collect06>, - <f_collect07>, - <f_collect08>, - <f_collect09>, - <f_collect_tab>, - <f_collect_line>. - -*--------------------------------------------------------------------* -* SESSION 3: MAP DATA TO SEMANTIC TABLE -*--------------------------------------------------------------------* - -* get dependent field field: currency and quantity - - create data wa like line of <f_excel_tab>. - assign wa->* to <f_excel_line>. - - describe field <f_excel_line> type l_typ components l_num. - - do l_num times. - l_save_index = sy-index. - assign component l_save_index of structure <f_excel_line> - to <f_excel_column>. - if sy-subrc ne 0. - message e059(0k) with 'FATAL ERROR' raising fatal_error. - endif. - - loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> - where tabname = l_tabname. - assign component <f_fieldcat_line>-fieldname - of structure <f_excel_line> to <f_fcat_column>. - - describe distance between <f_excel_column> and <f_fcat_column> - 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 = <f_fieldcat_line>-fieldname. - wa_column_index-tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-cfieldname is not initial. - clear wa_fieldcat_depf. - wa_fieldcat_depf-fieldname = <f_fieldcat_line>-cfieldname. - wa_fieldcat_depf-tabname = <f_fieldcat_line>-ctabname. - collect wa_fieldcat_depf into lt_fieldcat_depf. - endif. - - if <f_fieldcat_line>-qfieldname is not initial. - clear wa_fieldcat_depf. - wa_fieldcat_depf-fieldname = <f_fieldcat_line>-qfieldname. - wa_fieldcat_depf-tabname = <f_fieldcat_line>-qtabname. - collect wa_fieldcat_depf into lt_fieldcat_depf. - endif. - -* rewrite field data type - - if <f_fieldcat_line>-inttype = 'X' - and <f_fieldcat_line>-datatype(3) = 'INT'. - <f_fieldcat_line>-inttype = 'I'. - endif. - - endloop. - - clear: l_save_index. - unassign: <f_fieldcat_line>. - - enddo. - -* build semantic tables - - l_n_hrz_keys = 1. - -* Get keyfigures - - loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> - 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 = <f_fieldcat_line>-fieldname - tabname = <f_fieldcat_line>-tabname. - - if sy-subrc = 0. - wa_sema-col_typ = 'STR'. - wa_sema-col_ops = 'DFT'. - -* Keyfigures - - else. - case <f_fieldcat_line>-datatype. - when 'QUAN'. - wa_sema-col_typ = 'N03'. - - if <f_fieldcat_line>-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 <f_fieldcat_line>-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 = <f_fieldcat_line>-fieldname - tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-cfieldname is initial. - read table lt_column_index into wa_column_index with key - fieldname = <f_fieldcat_line>-cfieldname - tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-qfieldname is initial. - read table lt_column_index into wa_column_index with key - fieldname = <f_fieldcat_line>-qfieldname - tabname = <f_fieldcat_line>-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 <f_fieldcat_line>-currency is initial. - - select * from tcurx into table lt_tcurx. - sort lt_tcurx. - read table lt_tcurx into wa_tcurx - with key currkey = <f_fieldcat_line>-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 = <f_fieldcat_line>-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: - <f_fieldcat_line>, - <f_excel_line>, - <f_excel_column>, - <f_fcat_column>. - -*--------------------------------------------------------------------* -* 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. - exit. - 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 <f_excel_tab> 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: wa_usr type usr01. - select * from usr01 into wa_usr where bname = sy-uname. - endselect. - - data: comma_elim(4) type c. - data: help6 type i. - field-symbols <g> 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 = wa_usr-datfm. - 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 = '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 <f_excel_tab> assigning <line>. - assign component semaitem-col_no of structure <line> to <item>. - describe field <item> 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 <line> type typ components count. - mit = 1. - do count times. - if mit = semaitem-col_src. - assign component sy-index of structure <line> to <item>. - describe field <item> 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: conv_exit(10) type c. - 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 <f_excel_tab> assigning <line>. - -* 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 <line> to <item>. - else. - assign component sy-index - of structure <line> to <item>. - 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 <item> is initial and not <item> co ' ' and not - <item> co '0'. -* change for date in char format & sema_type = X starts - if sema_type = 'X'. - describe field <item> type typ. - if typ = 'C'. - temp_date = <item>. - number_of_days = temp_date - genesis. - else. - number_of_days = <item> - genesis. - endif. - else. - number_of_days = <item> - 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 <item> 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 <item> type typ. - - if semaitem-col_cur is initial. - if typ ne 'F'. - write <item> to contentsitem-value no-grouping - no-sign decimals 14. - else. - write <item> 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 <item> to contentsitem-value no-grouping - currency wa_tcurx-currkey no-sign decimals 14. - else. - write <item> to contentsitem-value no-grouping - currency wa_tcurx-currkey no-sign. - endif. - endif. - else. - assign component semaitem-col_cur - of structure <line> to <g>. -* 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 <f_fieldcat_line> - with key tabname = l_tabname - tech = space - no_out = space - col_pos = semaitem-col_no. - IF sy-subrc = 0. - IF <f_fieldcat_line>-cfieldname is not initial. - l_def = 'C'. - else."if <f_fieldcat_line>-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 = <g>. -* 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 <item> to contentsitem-value - currency <g> - no-sign no-grouping. - else. - write <item> to contentsitem-value - decimals 14 currency <g> - 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 = <g>. -* 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 <item> to contentsitem-value - unit <g> - 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 <f_fieldcat_line> - where tabname = l_tabname - and tech ne 'X' - and no_out ne 'X'. - if <f_fieldcat_line>-col_pos = semaitem-col_no. - if <f_fieldcat_line>-no_zero = 'X'. - if <item> = '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. - if <item> = '0'. - clear: contentsitem-value. - endif. - ENDIF. - endif. - endif. - endloop. - unassign: <f_fieldcat_line>. - - if <item> lt 0. - search contentsitem-value for 'E'. - if sy-fdpos eq 0. - -* bring negative sign to front of amount - - 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 <item> 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: <f_fieldcat_line>. - -* 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: item type colxxl_t. - 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: <f_source> type any. - field-symbols: <f_des> 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 <f_source>. - if <f_source> is not initial. - assign component sy-index of structure wa_format to <f_des>. - <f_des> = <f_source>. - unassign: <f_des>. - endif. - unassign: <f_source>. - 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. - if 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. - 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. - if 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. - 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 <f_source>. - if <f_source> is not initial. - assign component sy-index of structure wa_format to <f_des>. - <f_des> = <f_source>. - unassign: <f_des>. - endif. - unassign: <f_source>. - 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, - <f_excel_tab>. - - clear: - lo_error_w. - - unassign: - <line>, - <item>, - <f_excel_tab>. - -*--------------------------------------------------------------------* -* 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 i499(sy) with 'Document is Exported to ' p_path. - message i499(sy) with 'Data has been exported successfully'. - - clear: - ls_path, - li_document_size. - - close_document. -endmethod. - - - - - - - - METHOD bind_table. -*--------------------------------------------------------------------* -* issue #230 - Pimp my Code -* - Stefan Schmöcker, (wi p) 2012-12-01 -* - ... -* aligning code -* message made to support multilinguality -*--------------------------------------------------------------------* -* issue #237 - Check if overlapping areas exist -* - Alessandro Iannacci 2012-12-01 -* changes: - Added raise if overlaps are detected -*--------------------------------------------------------------------* - - CONSTANTS: - lc_top_left_column TYPE zexcel_cell_column_alpha VALUE 'B', - lc_top_left_row TYPE zexcel_cell_row VALUE '3'. - - DATA: - lv_row_int TYPE zexcel_cell_row, - lv_first_row TYPE zexcel_cell_row, - lv_last_row TYPE zexcel_cell_row, - lv_column_int TYPE zexcel_cell_column, - lv_column_alpha TYPE zexcel_cell_column_alpha, - lt_field_catalog TYPE zexcel_t_fieldcatalog, - lv_id TYPE i, - lv_rows TYPE i, - lv_formula TYPE string, - ls_settings TYPE zexcel_s_table_settings, - lo_table TYPE REF TO zcl_excel_table, - lt_column_name_buffer TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line, - lv_value TYPE string, - lv_syindex TYPE char3, - lv_errormessage TYPE string, "ins issue #237 - - lv_columns TYPE i, - lt_columns TYPE zexcel_t_fieldcatalog, - lv_maxcol TYPE i, - lv_maxrow TYPE i, - lo_iterator TYPE REF TO cl_object_collection_iterator, - lo_curtable TYPE REF TO zcl_excel_table. - - FIELD-SYMBOLS: - <ls_field_catalog> TYPE zexcel_s_fieldcatalog, - <ls_field_catalog_custom> TYPE zexcel_s_fieldcatalog, - <fs_table_line> TYPE ANY, - <fs_fldval> TYPE ANY. - - ls_settings = is_table_settings. - - IF ls_settings-top_left_column IS INITIAL. - ls_settings-top_left_column = lc_top_left_column. - ENDIF. - - IF ls_settings-table_style IS INITIAL. - ls_settings-table_style = zcl_excel_table=>builtinstyle_medium2. - ENDIF. - - IF ls_settings-top_left_row IS INITIAL. - ls_settings-top_left_row = lc_top_left_row. - ENDIF. - - IF it_field_catalog IS NOT SUPPLIED. - lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = ip_table ). - ELSE. - lt_field_catalog = it_field_catalog. - ENDIF. - - SORT lt_field_catalog BY position. - -*--------------------------------------------------------------------* -* issue #237 Check if overlapping areas exist Start -*--------------------------------------------------------------------* - "Get the number of columns for the current table - lt_columns = lt_field_catalog. - DELETE lt_columns WHERE dynpfld NE abap_true. - DESCRIBE TABLE lt_columns LINES lv_columns. - - "Calculate the top left row of the current table - lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). - lv_row_int = ls_settings-top_left_row. - - "Get number of row for the current table - DESCRIBE TABLE ip_table LINES lv_rows. - - "Calculate the bottom right row for the current table - lv_maxcol = lv_column_int + lv_columns - 1. - lv_maxrow = lv_row_int + lv_rows - 1. - ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( lv_maxcol ). - ls_settings-bottom_right_row = lv_maxrow. - - lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). - - lo_iterator = me->tables->if_object_collection~get_iterator( ). - WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. - - lo_curtable ?= lo_iterator->if_object_collection_iterator~get_next( ). - IF ( ( ls_settings-top_left_row GE lo_curtable->settings-top_left_row AND ls_settings-top_left_row LE lo_curtable->settings-bottom_right_row ) - OR - ( ls_settings-bottom_right_row GE lo_curtable->settings-top_left_row AND ls_settings-bottom_right_row LE lo_curtable->settings-bottom_right_row ) - ) - AND - ( ( lv_column_int GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_column_int LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) - OR - ( lv_maxcol GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_maxcol LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) - ). - lv_errormessage = 'Table overlaps with previously bound table and will not be added to worksheet.'(400). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - ENDWHILE. -*--------------------------------------------------------------------* -* issue #237 Check if overlapping areas exist End -*--------------------------------------------------------------------* - - CREATE OBJECT lo_table. - lo_table->settings = ls_settings. - lo_table->set_data( ir_data = ip_table ). - lv_id = me->excel->get_next_table_id( ). - lo_table->set_id( iv_id = lv_id ). -* lo_table->fieldcat = lt_field_catalog[]. - - me->tables->add( lo_table ). - -* It is better to loop column by column (only visible column) - LOOP AT lt_field_catalog ASSIGNING <ls_field_catalog> WHERE dynpfld EQ abap_true. - - lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). - - " Due restrinction of new table object we cannot have two column with the same name - " Check if a column with the same name exists, if exists add a counter - " If no medium description is provided we try to use small or long -* lv_value = <ls_field_catalog>-scrtext_m. - IF <ls_field_catalog>-scrtext_m IS NOT INITIAL. - lv_value = <ls_field_catalog>-scrtext_m. - <ls_field_catalog>-scrtext_l = lv_value. - ELSEIF <ls_field_catalog>-scrtext_s IS NOT INITIAL. - lv_value = <ls_field_catalog>-scrtext_s. - <ls_field_catalog>-scrtext_l = lv_value. - ELSEIF <ls_field_catalog>-scrtext_l IS NOT INITIAL. - lv_value = <ls_field_catalog>-scrtext_l. - ELSE. - lv_value = 'Column'. " default value as Excel does - <ls_field_catalog>-scrtext_l = lv_value. - ENDIF. - WHILE 1 = 1. - - READ TABLE lt_column_name_buffer TRANSPORTING NO FIELDS WITH KEY table_line = lv_value BINARY SEARCH. - IF sy-subrc <> 0. - <ls_field_catalog>-scrtext_l = lv_value. - INSERT lv_value INTO TABLE lt_column_name_buffer. - EXIT. - ELSE. - lv_syindex = sy-index. - CONCATENATE <ls_field_catalog>-scrtext_l lv_syindex INTO lv_value. - ENDIF. - - ENDWHILE. - " First of all write column header - IF <ls_field_catalog>-style_header IS NOT INITIAL. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = lv_value - ip_style = <ls_field_catalog>-style_header ). - ELSE. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = lv_value ). - ENDIF. - - ADD 1 TO lv_row_int. - LOOP AT ip_table ASSIGNING <fs_table_line>. - - ASSIGN COMPONENT <ls_field_catalog>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. - " issue #290 Add formula support in table - IF <ls_field_catalog>-formula EQ abap_true. - IF <ls_field_catalog>-style IS NOT INITIAL. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_formula = <fs_fldval> - ip_style = <ls_field_catalog>-style ). - ELSE. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_formula = <fs_fldval> ). - ENDIF. - ELSE. - IF <ls_field_catalog>-style IS NOT INITIAL. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = <fs_fldval> - ip_style = <ls_field_catalog>-style ). - ELSE. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = <fs_fldval> ). - ENDIF. - ENDIF. - ADD 1 TO lv_row_int. - - ENDLOOP. - IF sy-subrc <> 0. "create empty row if table has no data - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = space ). - ADD 1 TO lv_row_int. - ENDIF. - -*--------------------------------------------------------------------* - " totals -*--------------------------------------------------------------------* - IF <ls_field_catalog>-totals_function IS NOT INITIAL. - lv_formula = lo_table->get_totals_formula( ip_column = <ls_field_catalog>-scrtext_l ip_function = <ls_field_catalog>-totals_function ). - IF <ls_field_catalog>-style_total IS NOT INITIAL. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_formula = lv_formula - ip_style = <ls_field_catalog>-style_total ). - ELSE. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_formula = lv_formula ). - ENDIF. - ENDIF. - - lv_row_int = ls_settings-top_left_row. - ADD 1 TO lv_column_int. - -*--------------------------------------------------------------------* - " conditional formatting -*--------------------------------------------------------------------* - IF <ls_field_catalog>-cond_style IS NOT INITIAL. - lv_first_row = ls_settings-top_left_row + 1. " +1 to exclude header - lv_last_row = ls_settings-top_left_row + lv_rows. - <ls_field_catalog>-cond_style->set_range( ip_start_column = lv_column_alpha - ip_start_row = lv_first_row - ip_stop_column = lv_column_alpha - ip_stop_row = lv_last_row ). - ENDIF. - - ENDLOOP. - -*--------------------------------------------------------------------* - " Set field catalog -*--------------------------------------------------------------------* - lo_table->fieldcat = lt_field_catalog[]. - - es_table_settings = ls_settings. - es_table_settings-bottom_right_column = lv_column_alpha. - " >> Issue #291 - IF ip_table IS INITIAL. - es_table_settings-bottom_right_row = ls_settings-top_left_row + 2. "Last rows - ELSE. - es_table_settings-bottom_right_row = ls_settings-top_left_row + lv_rows + 1. "Last rows - ENDIF. - " << Issue #291 - -ENDMETHOD. - - - - - - - method CALCULATE_CELL_WIDTH. - DATA: cell_value TYPE zexcel_cell_value, - guid TYPE zexcel_cell_style, - stylemapping TYPE zexcel_s_stylemapping. - - me->get_cell( EXPORTING ip_column = ip_column " Cell Column - ip_row = ip_row " Cell Row - IMPORTING ep_value = cell_value - ep_guid = guid )." Cell Value ). - - - ep_width = STRLEN( cell_value ). - TRY. - stylemapping = me->excel->get_style_to_guid( guid ). - CATCH zcx_excel. - EXIT. " Do nothing if no style was found - ENDTRY. - - IF stylemapping-complete_stylex-font-size = 'X'. - ep_width = ep_width * stylemapping-complete_style-font-size / 11. - ENDIF. - -endmethod. - - - - method CALCULATE_COLUMN_WIDTHS. - TYPES: - BEGIN OF t_auto_size, - col_index TYPE int4, - width TYPE float, - END OF t_auto_size. - TYPES: tt_auto_size TYPE TABLE OF t_auto_size. - - DATA: column_dimensions TYPE zexcel_t_worksheet_columndime. - DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. - - DATA: auto_size TYPE flag. - DATA: auto_sizes TYPE tt_auto_size. -* DATA: col_alpha TYPE zexcel_cell_column_alpha." issue #155 - less restrictive typing for ip_column - DATA: cell_value TYPE zexcel_cell_value. - DATA: cell_style TYPE REF TO zcl_excel_style. - DATA: count TYPE int4. - DATA: highest_row TYPE int4. - DATA: width TYPE i. - - FIELD-SYMBOLS: <column_dimension> LIKE LINE OF column_dimensions. - FIELD-SYMBOLS: <auto_size> LIKE LINE OF auto_sizes. - - column_dimensions[] = me->get_column_dimensions( ). - LOOP AT column_dimensions ASSIGNING <column_dimension>. - auto_size = <column_dimension>-column_dimension->get_auto_size( ). - IF auto_size = abap_true. - APPEND INITIAL LINE TO auto_sizes ASSIGNING <auto_size>. - <auto_size>-col_index = <column_dimension>-column_dimension->get_column_index( ). - <auto_size>-width = -1. - ENDIF. - ENDLOOP. - - " There is only something to do if there are some auto-size columns - IF NOT auto_sizes IS INITIAL. - highest_row = me->get_highest_row( ). - LOOP AT auto_sizes ASSIGNING <auto_size>. -* col_alpha = zcl_excel_common=>convert_column2alpha( <auto_size>-col_index )." issue #155 - less restrictive typing for ip_column - count = 1. - WHILE count <= highest_row. -* Start of change # issue 139 - Dateretention of cellstyles -* IF cell_style IS BOUND. -* CREATE OBJECT cell_style. -* ENDIF. -* me->get_cell( -* EXPORTING -* ip_column = col_alpha " Cell Column -* ip_row = count " Cell Row -* IMPORTING -* ep_value = cell_value " Cell Value -* ep_style = cell_style " Request Cell Style as well -* ). -* " For an easy start we just take the number of characters as the width -* width = strlen( cell_value ). -* " Addition to solve issue #120, contribution by Stefan Schm#ƒÂ#cker -* " Calculate width using Font Size and Font Type -* IF cell_style IS BOUND -* AND cell_style->font IS BOUND. -* width = cell_style->font->calculate_text_width( cell_value ). -* ENDIF. -* width = calculate_cell_width( ip_column = col_alpha " issue #155 - less restrictive typing for ip_column - width = calculate_cell_width( ip_column = <auto_size>-col_index " issue #155 - less restrictive typing for ip_column - ip_row = count ). -* End of change # issue 139 - Dateretention of cellstyles - IF width > <auto_size>-width. - <auto_size>-width = width. - ENDIF. - count = count + 1. - ENDWHILE. -* column_dimension = me->get_column_dimension( col_alpha ). " issue #155 - less restrictive typing for ip_column - column_dimension = me->get_column_dimension( <auto_size>-col_index ). " issue #155 - less restrictive typing for ip_column - column_dimension->set_width( <auto_size>-width ). - ENDLOOP. - ENDIF. - -endmethod. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - method CHANGE_CELL_STYLE. - " issue # 139 - DATA: stylemapping TYPE zexcel_s_stylemapping, - - complete_style TYPE zexcel_s_cstyle_complete, - complete_stylex TYPE zexcel_s_cstylex_complete, - - borderx TYPE zexcel_s_cstylex_border, - l_guid TYPE zexcel_cell_style. "issue # 177 - -* We have a lot of parameters. Use some macros to make the coding more structured - - DEFINE clear_initial_colorxfields. - if &1-rgb is initial. - clear &2-rgb. - endif. - if &1-indexed is initial. - clear &2-indexed. - endif. - if &1-theme is initial. - clear &2-theme. - endif. - if &1-tint is initial. - clear &2-tint. - endif. - END-OF-DEFINITION. - - DEFINE move_supplied_borders. - if ip_&1 is supplied. " only act if parameter was supplied - if ip_x&1 is supplied. " - borderx = ip_x&1. " use supplied x-parameter - else. - clear borderx with 'X'. -* clear in a way that would be expected to work easily - if ip_&1-border_style is initial. - clear borderx-border_style. - endif. - clear_initial_colorxfields ip_&1-border_color borderx-border_color. - endif. - move-corresponding ip_&1 to complete_style-&2. - move-corresponding borderx to complete_stylex-&2. - endif. - END-OF-DEFINITION. - -* First get current stylsettings - TRY. - me->get_cell( EXPORTING ip_column = ip_column " Cell Column - ip_row = ip_row " Cell Row - IMPORTING ep_guid = l_guid )." Cell Value ). "issue # 177 - - - stylemapping = me->excel->get_style_to_guid( l_guid ). "issue # 177 - complete_style = stylemapping-complete_style. - complete_stylex = stylemapping-complete_stylex. - CATCH zcx_excel. -* Error --> use submitted style - ENDTRY. - -* move_supplied_multistyles: complete. - IF ip_complete IS SUPPLIED. - IF ip_xcomplete IS NOT SUPPLIED. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Complete styleinfo has to be supplied with corresponding X-field'. - ENDIF. - MOVE-CORRESPONDING ip_complete TO complete_style. - MOVE-CORRESPONDING ip_xcomplete TO complete_stylex. - ENDIF. - - - - IF ip_font IS SUPPLIED. - DATA: fontx LIKE ip_xfont. - IF ip_xfont IS SUPPLIED. - fontx = ip_xfont. - ELSE. -* Only supplied values should be used - exception: Flags bold and italic strikethrough underline - MOVE 'X' TO: fontx-bold, - fontx-italic, - fontx-strikethrough, - fontx-underline_mode. - CLEAR fontx-color WITH 'X'. - clear_initial_colorxfields ip_font-color fontx-color. - IF ip_font-family IS NOT INITIAL. - fontx-family = 'X'. - ENDIF. - IF ip_font-name IS NOT INITIAL. - fontx-name = 'X'. - ENDIF. - IF ip_font-scheme IS NOT INITIAL. - fontx-scheme = 'X'. - ENDIF. - IF ip_font-size IS NOT INITIAL. - fontx-size = 'X'. - ENDIF. - IF ip_font-underline_mode IS NOT INITIAL. - fontx-underline_mode = 'X'. - ENDIF. - ENDIF. - MOVE-CORRESPONDING ip_font TO complete_style-font. - MOVE-CORRESPONDING fontx TO complete_stylex-font. -* Correction for undeline mode - ENDIF. - - IF ip_fill IS SUPPLIED. - DATA: fillx LIKE ip_xfill. - IF ip_xfill IS SUPPLIED. - fillx = ip_xfill. - ELSE. - CLEAR fillx WITH 'X'. - IF ip_fill-filltype IS INITIAL. - CLEAR fillx-filltype. - ENDIF. - clear_initial_colorxfields ip_fill-fgcolor fillx-fgcolor. - clear_initial_colorxfields ip_fill-bgcolor fillx-bgcolor. - - ENDIF. - MOVE-CORRESPONDING ip_fill TO complete_style-fill. - MOVE-CORRESPONDING fillx TO complete_stylex-fill. - ENDIF. - - - IF ip_borders IS SUPPLIED. - DATA: bordersx LIKE ip_xborders. - IF ip_xborders IS SUPPLIED. - bordersx = ip_xborders. - ELSE. - CLEAR bordersx WITH 'X'. - IF ip_borders-allborders-border_style IS INITIAL. - CLEAR bordersx-allborders-border_style. - ENDIF. - IF ip_borders-diagonal-border_style IS INITIAL. - CLEAR bordersx-diagonal-border_style. - ENDIF. - IF ip_borders-down-border_style IS INITIAL. - CLEAR bordersx-down-border_style. - ENDIF. - IF ip_borders-left-border_style IS INITIAL. - CLEAR bordersx-left-border_style. - ENDIF. - IF ip_borders-right-border_style IS INITIAL. - CLEAR bordersx-right-border_style. - ENDIF. - IF ip_borders-top-border_style IS INITIAL. - CLEAR bordersx-top-border_style. - ENDIF. - clear_initial_colorxfields ip_borders-allborders-border_color bordersx-allborders-border_color. - clear_initial_colorxfields ip_borders-diagonal-border_color bordersx-diagonal-border_color. - clear_initial_colorxfields ip_borders-down-border_color bordersx-down-border_color. - clear_initial_colorxfields ip_borders-left-border_color bordersx-left-border_color. - clear_initial_colorxfields ip_borders-right-border_color bordersx-right-border_color. - clear_initial_colorxfields ip_borders-top-border_color bordersx-top-border_color. - - ENDIF. - MOVE-CORRESPONDING ip_borders TO complete_style-borders. - MOVE-CORRESPONDING bordersx TO complete_stylex-borders. - ENDIF. - - IF ip_alignment IS SUPPLIED. - DATA: alignmentx LIKE ip_xalignment. - IF ip_xalignment IS SUPPLIED. - alignmentx = ip_xalignment. - ELSE. - CLEAR alignmentx WITH 'X'. - IF ip_alignment-horizontal IS INITIAL. - CLEAR alignmentx-horizontal. - ENDIF. - IF ip_alignment-vertical IS INITIAL. - CLEAR alignmentx-vertical. - ENDIF. - ENDIF. - MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. - MOVE-CORRESPONDING alignmentx TO complete_stylex-alignment. - ENDIF. - - IF ip_protection IS SUPPLIED. - MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. - IF ip_xprotection IS SUPPLIED. - MOVE-CORRESPONDING ip_xprotection TO complete_stylex-protection. - ELSE. - IF ip_protection-hidden IS NOT INITIAL. - complete_style-protection-hidden = 'X'. - ENDIF. - IF ip_protection-locked IS NOT INITIAL. - complete_style-protection-locked = 'X'. - ENDIF. - ENDIF. - ENDIF. - - - move_supplied_borders : borders_allborders borders-allborders, - borders_diagonal borders-diagonal , - borders_down borders-down , - borders_left borders-left , - borders_right borders-right , - borders_top borders-top . - - DEFINE move_supplied_singlestyles. - if ip_&1 is supplied. - complete_style-&2 = ip_&1. - complete_stylex-&2 = 'X'. - endif. - END-OF-DEFINITION. - - move_supplied_singlestyles: number_format_format_code number_format-format_code, - font_bold font-bold, - font_color font-color, - font_color_rgb font-color-rgb, - font_color_indexed font-color-indexed, - font_color_theme font-color-theme, - font_color_tint font-color-tint, - - font_family font-family, - font_italic font-italic, - font_name font-name, - font_scheme font-scheme, - font_size font-size, - font_strikethrough font-strikethrough, - font_underline font-underline, - font_underline_mode font-underline_mode, - fill_filltype fill-filltype, - fill_rotation fill-rotation, - fill_fgcolor fill-fgcolor, - fill_fgcolor_rgb fill-fgcolor-rgb, - fill_fgcolor_indexed fill-fgcolor-indexed, - fill_fgcolor_theme fill-fgcolor-theme, - fill_fgcolor_tint fill-fgcolor-tint, - - fill_bgcolor fill-bgcolor, - fill_bgcolor_rgb fill-bgcolor-rgb, - fill_bgcolor_indexed fill-bgcolor-indexed, - fill_bgcolor_theme fill-bgcolor-theme, - fill_bgcolor_tint fill-bgcolor-tint, - - borders_diagonal_mode borders-diagonal_mode, - alignment_horizontal alignment-horizontal, - alignment_vertical alignment-vertical, - alignment_textrotation alignment-textrotation, - alignment_wraptext alignment-wraptext, - alignment_shrinktofit alignment-shrinktofit, - alignment_indent alignment-indent, - protection_hidden protection-hidden, - protection_locked protection-locked, - - borders_allborders_style borders-allborders-border_style, - borders_allborders_color borders-allborders-border_color, - borders_allbo_color_rgb borders-allborders-border_color-rgb, - borders_allbo_color_indexed borders-allborders-border_color-indexed, - borders_allbo_color_theme borders-allborders-border_color-theme, - borders_allbo_color_tint borders-allborders-border_color-tint, - - borders_diagonal_style borders-diagonal-border_style, - borders_diagonal_color borders-diagonal-border_color, - borders_diagonal_color_rgb borders-diagonal-border_color-rgb, - borders_diagonal_color_inde borders-diagonal-border_color-indexed, - borders_diagonal_color_them borders-diagonal-border_color-theme, - borders_diagonal_color_tint borders-diagonal-border_color-tint, - - borders_down_style borders-down-border_style, - borders_down_color borders-down-border_color, - borders_down_color_rgb borders-down-border_color-rgb, - borders_down_color_indexed borders-down-border_color-indexed, - borders_down_color_theme borders-down-border_color-theme, - borders_down_color_tint borders-down-border_color-tint, - - borders_left_style borders-left-border_style, - borders_left_color borders-left-border_color, - borders_left_color_rgb borders-left-border_color-rgb, - borders_left_color_indexed borders-left-border_color-indexed, - borders_left_color_theme borders-left-border_color-theme, - borders_left_color_tint borders-left-border_color-tint, - - borders_right_style borders-right-border_style, - borders_right_color borders-right-border_color, - borders_right_color_rgb borders-right-border_color-rgb, - borders_right_color_indexed borders-right-border_color-indexed, - borders_right_color_theme borders-right-border_color-theme, - borders_right_color_tint borders-right-border_color-tint, - - borders_top_style borders-top-border_style, - borders_top_color borders-top-border_color, - borders_top_color_rgb borders-top-border_color-rgb, - borders_top_color_indexed borders-top-border_color-indexed, - borders_top_color_theme borders-top-border_color-theme, - borders_top_color_tint borders-top-border_color-tint. - - -* Now we have a completly filled styles. -* This can be used to get the guid -* Return guid if requested. Might be used if copy&paste of styles is requested - ep_guid = me->excel->get_static_cellstyle_guid( ip_cstyle_complete = complete_style - ip_cstylex_complete = complete_stylex ). - me->set_cell_style( ip_column = ip_column - ip_row = ip_row - ip_style = ep_guid ). - -endmethod. - - - - - - method CONSTRUCTOR. - DATA: lv_title TYPE zexcel_sheet_title. - - me->excel = ip_excel. - - CALL FUNCTION 'GUID_CREATE' - IMPORTING - ev_guid_16 = me->guid. - - IF ip_title IS NOT INITIAL. - lv_title = ip_title. - ELSE. -* lv_title = me->guid. " del issue #154 - Names of worksheets - lv_title = me->generate_title( ). " ins issue #154 - Names of worksheets - ENDIF. - - me->set_title( ip_title = lv_title ). - - CREATE OBJECT sheet_setup. - CREATE OBJECT conditional_styles. - CREATE OBJECT data_validations. - CREATE OBJECT tables. - CREATE OBJECT ranges. " issue #163 - CREATE OBJECT drawings - EXPORTING - ip_type = zcl_excel_drawing=>type_image. - CREATE OBJECT charts - EXPORTING - ip_type = zcl_excel_drawing=>type_chart. - me->zif_excel_sheet_protection~initialize( ). - me->zif_excel_sheet_properties~initialize( ). - CREATE OBJECT hyperlinks. - -* initialize active cell coordinates - active_cell-cell_row = 1. - active_cell-cell_column = 1. - -* inizialize dimension range - lower_cell-cell_row = 1. - lower_cell-cell_column = 1. - upper_cell-cell_row = 1. - upper_cell-cell_column = 1. - -endmethod. - - - method DELETE_MERGE. - - DELETE sheet_content_merge INDEX 1. - DELETE sheet_content_merge INDEX 1. - -endmethod. - - - - - - method FREEZE_PANES. - data: lv_xsplit type i, - lv_ysplit type i. - - IF ip_num_columns IS NOT SUPPLIED AND ip_num_rows IS NOT SUPPLIED. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Pleas provide number of rows and/or columns to freeze'. - ENDIF. - - IF ip_num_columns IS SUPPLIED AND ip_num_columns <= 0. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Number of columns to freeze should be positive'. - ENDIF. - - IF ip_num_rows IS SUPPLIED AND ip_num_rows <= 0. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Number of rows to freeze should be positive'. - ENDIF. - - freeze_pane_cell_column = ip_num_columns + 1. - freeze_pane_cell_row = ip_num_rows + 1. -endmethod. - - - - method GENERATE_TITLE. - DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, - lo_worksheet TYPE REF TO zcl_excel_worksheet, - errormessage TYPE string. - - DATA: t_titles TYPE HASHED TABLE OF zexcel_sheet_title WITH UNIQUE KEY table_line, - title TYPE zexcel_sheet_title, - sheetnumber TYPE i. - -* Get list of currently used titles - lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). - WHILE lo_worksheets_iterator->has_next( ) = abap_true. - lo_worksheet ?= lo_worksheets_iterator->get_next( ). - title = lo_worksheet->get_title( ). - INSERT title INTO TABLE t_titles. - ADD 1 TO sheetnumber. - ENDWHILE. - -* Now build sheetnumber. Increase counter until we hit a number that is not used so far - ADD 1 TO sheetnumber. " Start counting with next number - DO. - title = sheetnumber. - SHIFT title LEFT DELETING LEADING space. - CONCATENATE 'Sheet'(001) title INTO ep_title. - INSERT ep_title INTO TABLE t_titles. - IF sy-subrc = 0. " Title not used so far --> take it - EXIT. - ENDIF. - - ADD 1 TO sheetnumber. - ENDDO. -endmethod. - - - - - method GET_ACTIVE_CELL. - - DATA: lv_active_column TYPE zexcel_cell_column_alpha, - lv_active_row TYPE string. - - lv_active_column = zcl_excel_common=>convert_column2alpha( active_cell-cell_column ). - lv_active_row = active_cell-cell_row. - SHIFT lv_active_row RIGHT DELETING TRAILING space. - SHIFT lv_active_row LEFT DELETING LEADING space. - CONCATENATE lv_active_column lv_active_row INTO ep_active_cell. - -endmethod. - - - - - - - - - - method GET_CELL. - - DATA: lv_column TYPE zexcel_cell_column, - ls_sheet_content TYPE zexcel_s_cell_data. - - FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. - - lv_column = zcl_excel_common=>convert_column2int( ip_column ). - - READ TABLE sheet_content INTO ls_sheet_content WITH TABLE KEY cell_row = ip_row - cell_column = lv_column. - - ep_rc = sy-subrc. - ep_value = ls_sheet_content-cell_value. - ep_guid = ls_sheet_content-cell_style. " issue 139 - added this to be used for columnwidth calculation - - " Addition to solve issue #120, contribution by Stefan Schm#ƒÂ#cker - DATA: style_iterator TYPE REF TO cl_object_collection_iterator, - style TYPE REF TO zcl_excel_style. - IF ep_style IS REQUESTED. - style_iterator = me->excel->get_styles_iterator( ). - WHILE style_iterator->has_next( ) = 'X'. - style ?= style_iterator->get_next( ). - IF style->get_guid( ) = ls_sheet_content-cell_style. - ep_style = style. - EXIT. - ENDIF. - ENDWHILE. - ENDIF. -endmethod. - - - - - - method GET_COLUMN_DIMENSION. - FIELD-SYMBOLS: <fs_column_dimension> LIKE LINE OF column_dimensions. - DATA: lv_column_alpha TYPE zexcel_cell_column_alpha. " issue #155 - less restrictive typing for ip_column - - lv_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column )." issue #155 - less restrictive typing for ip_column - READ TABLE me->column_dimensions ASSIGNING <fs_column_dimension> - WITH KEY column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column - - IF NOT <fs_column_dimension> IS ASSIGNED. - CREATE OBJECT r_column_dimension - EXPORTING - ip_index = lv_column_alpha " issue #155 - less restrictive typing for ip_column - ip_excel = me->excel " issue #157 - Allow style for columns - ip_worksheet = me. " issue #157 - Allow style for columns - APPEND INITIAL LINE TO me->column_dimensions ASSIGNING <fs_column_dimension>. - <fs_column_dimension>-column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column - <fs_column_dimension>-column_dimension = r_column_dimension. - ELSE. - r_column_dimension = <fs_column_dimension>-column_dimension. - ENDIF. - -endmethod. - - - - method GET_COLUMN_DIMENSIONS. - r_column_dimension[] = me->column_dimensions[]. -endmethod. - - - - method GET_COND_STYLES_ITERATOR. - - eo_iterator = me->conditional_styles->get_iterator( ). -endmethod. - - - - method GET_DATA_VALIDATIONS_ITERATOR. - - eo_iterator = me->data_validations->get_iterator( ). -endmethod. - - - - method GET_DATA_VALIDATIONS_SIZE. - ep_size = me->data_validations->size( ). -endmethod. - - - - method GET_DEFAULT_COLUMN_DIMENSION. - IF me->default_column_dimension IS NOT BOUND. - CREATE OBJECT me->default_column_dimension - EXPORTING - ip_index = 'A' " ???? - ip_worksheet = me - ip_excel = me->excel. - ENDIF. - - r_column_dimension = me->default_column_dimension. -endmethod. - - - - method GET_DEFAULT_EXCEL_DATE_FORMAT. - CONSTANTS: c_lang_e TYPE lang VALUE 'E'. - - IF default_excel_date_format IS NOT INITIAL. - ep_default_excel_date_format = default_excel_date_format. - RETURN. - ENDIF. - - "try to get defaults - TRY. - cl_abap_datfm=>get_date_format_des( EXPORTING im_langu = c_lang_e - IMPORTING ex_dateformat = default_excel_date_format ). - CATCH cx_abap_datfm_format_unknown. - - ENDTRY. - - " and fallback to fixed format - IF default_excel_date_format IS INITIAL. - default_excel_date_format = zcl_excel_style_number_format=>c_format_date_ddmmyyyydot. - ENDIF. - - ep_default_excel_date_format = default_excel_date_format. -endmethod. - - - - method GET_DEFAULT_EXCEL_TIME_FORMAT. - DATA: l_timefm TYPE xutimefm. - - IF default_excel_time_format IS NOT INITIAL. - ep_default_excel_time_format = default_excel_time_format. - RETURN. - ENDIF. - -* Let's get default - l_timefm = cl_abap_timefm=>get_environment_timefm( ). - CASE l_timefm. - WHEN 0. -*0 24 Hour Format (Example: 12:05:10) - default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. - WHEN 1. -*1 12 Hour Format (Example: 12:05:10 PM) - default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. - WHEN 2. -*2 12 Hour Format (Example: 12:05:10 pm) for now all the same. no chnage upper lower - default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. - WHEN 3. -*3 Hours from 0 to 11 (Example: 00:05:10 PM) for now all the same. no chnage upper lower - default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. - WHEN 4. -*4 Hours from 0 to 11 (Example: 00:05:10 pm) for now all the same. no chnage upper lower - default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. - WHEN OTHERS. - " and fallback to fixed format - default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. - ENDCASE. - - ep_default_excel_time_format = default_excel_time_format. -endmethod. - - - - method GET_DEFAULT_ROW_DIMENSION. - IF me->default_row_dimension IS NOT BOUND. - CREATE OBJECT me->default_row_dimension. - ENDIF. - - r_row_dimension = me->default_row_dimension. -endmethod. - - - - - method GET_DIMENSION_RANGE. - - me->update_dimension_range( ). - IF upper_cell EQ lower_cell. "only one cell - " Worksheet not filled -* IF upper_cell-cell_coords = '0'. - IF upper_cell-cell_coords IS INITIAL. - ep_dimension_range = 'A1'. - ELSE. - ep_dimension_range = upper_cell-cell_coords. - ENDIF. - ELSE. - CONCATENATE upper_cell-cell_coords ':' lower_cell-cell_coords INTO ep_dimension_range. - ENDIF. - -endmethod. - - - - - method GET_DRAWINGS. - - DATA: lo_drawing TYPE REF TO zcl_excel_drawing, - lo_iterator TYPE REF TO cl_object_collection_iterator. - - CASE ip_type. - WHEN zcl_excel_drawing=>type_image. - r_drawings = drawings. - WHEN zcl_excel_drawing=>type_chart. - r_drawings = charts. - WHEN space. - CREATE OBJECT r_drawings - EXPORTING - ip_type = ''. - - lo_iterator = drawings->get_iterator( ). - WHILE lo_iterator->has_next( ) = abap_true. - lo_drawing ?= lo_iterator->get_next( ). - r_drawings->include( lo_drawing ). - ENDWHILE. - lo_iterator = charts->get_iterator( ). - WHILE lo_iterator->has_next( ) = abap_true. - lo_drawing ?= lo_iterator->get_next( ). - r_drawings->include( lo_drawing ). - ENDWHILE. - WHEN OTHERS. - ENDCASE. -endmethod. - - - - - method GET_DRAWINGS_ITERATOR. - CASE ip_type. - WHEN zcl_excel_drawing=>type_image. - eo_iterator = drawings->get_iterator( ). - WHEN zcl_excel_drawing=>type_chart. - eo_iterator = charts->get_iterator( ). - ENDCASE. -endmethod. - - - - - method GET_FREEZE_CELL. - ep_row = me->freeze_pane_cell_row. - ep_column = me->freeze_pane_cell_column. -endmethod. - - - - method GET_GUID. - - ep_guid = me->guid. - -endmethod. - - - - - method GET_HIGHEST_COLUMN. - me->update_dimension_range( ). - r_highest_column = me->lower_cell-cell_column. -endmethod. - - - - - method GET_HIGHEST_ROW. - me->update_dimension_range( ). - r_highest_row = me->lower_cell-cell_row. -endmethod. - - - - method GET_HYPERLINKS_ITERATOR. - eo_iterator = hyperlinks->get_iterator( ). -endmethod. - - - - method GET_HYPERLINKS_SIZE. - ep_size = hyperlinks->size( ). -endmethod. - - - - - method GET_MERGE. - - DATA: lv_column_start TYPE string, - lv_column_end TYPE string, - lv_row TYPE string, - lv_index TYPE sy-tabix, - ls_sheet_content TYPE zexcel_s_cell_data, - range_from TYPE string, - range_to TYPE string, - lv_merge_range TYPE string, - lv_count TYPE string. - - FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. - - DESCRIBE TABLE sheet_content_merge LINES lv_count. - - WHILE lv_count GT lv_index. -* LOOP AT sheet_content_merge ASSIGNING <fs_sheet_content>. - lv_index = lv_index + 1. - READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX lv_index. - lv_column_start = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). - lv_row = <fs_sheet_content>-cell_row. - SHIFT lv_column_start RIGHT DELETING TRAILING space. - SHIFT lv_column_start LEFT DELETING LEADING space. - SHIFT lv_row RIGHT DELETING TRAILING space. - SHIFT lv_row LEFT DELETING LEADING space. - CONCATENATE lv_column_start lv_row - INTO range_from. - - lv_index = lv_index + 1. - READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX lv_index. - lv_column_end = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). - lv_row = <fs_sheet_content>-cell_row. - SHIFT lv_column_end RIGHT DELETING TRAILING space. - SHIFT lv_column_end LEFT DELETING LEADING space. - SHIFT lv_row RIGHT DELETING TRAILING space. - SHIFT lv_row LEFT DELETING LEADING space. - CONCATENATE lv_column_end lv_row - INTO range_to. - - CONCATENATE range_from range_to INTO lv_merge_range - SEPARATED BY ':'. - APPEND lv_merge_range TO merge_range. - ENDWHILE. -* ENDLOOP. - -* READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX 1. -* IF sy-subrc EQ 0 AND <fs_sheet_content> IS ASSIGNED. -* lv_column_start = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). -* lv_row = <fs_sheet_content>-cell_row. -* SHIFT lv_column_start RIGHT DELETING TRAILING space. -* SHIFT lv_column_start LEFT DELETING LEADING space. -* SHIFT lv_row RIGHT DELETING TRAILING space. -* SHIFT lv_row LEFT DELETING LEADING space. -* CONCATENATE lv_column_start lv_row -* INTO range_from. -* ENDIF. -* READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX 2. -* IF sy-subrc EQ 0 AND <fs_sheet_content> IS ASSIGNED. -* lv_column_end = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). -* SHIFT lv_column_end RIGHT DELETING TRAILING space. -* SHIFT lv_column_end LEFT DELETING LEADING space. -* CONCATENATE lv_column_end lv_row -* INTO range_to. -* ENDIF. - -* IF range_from NE space AND range_to NE space. -* CONCATENATE range_from range_to INTO ep_merge_range -* SEPARATED BY ':'. -* ENDIF. - -endmethod. - - - - method GET_RANGES_ITERATOR. - - eo_iterator = me->ranges->get_iterator( ). - -endmethod. - - - - - method GET_ROW_DIMENSION. - FIELD-SYMBOLS: <fs_row_dimension> LIKE LINE OF row_dimensions. - - READ TABLE me->row_dimensions ASSIGNING <fs_row_dimension> - WITH KEY row = ip_row. - - IF NOT <fs_row_dimension> IS ASSIGNED. - CREATE OBJECT r_row_dimension - EXPORTING - ip_index = ip_row. - APPEND INITIAL LINE TO me->row_dimensions ASSIGNING <fs_row_dimension>. - <fs_row_dimension>-row = ip_row. - <fs_row_dimension>-row_dimension = r_row_dimension. - ELSE. - r_row_dimension = <fs_row_dimension>-row_dimension. - ENDIF. - -endmethod. - - - - method GET_ROW_DIMENSIONS. - r_row_dimension[] = me->row_dimensions[]. -endmethod. - - - - method GET_TABCOLOR. - ev_tabcolor = me->tabcolor. -endmethod. - - - - method GET_TABLES_ITERATOR. - eo_iterator = tables->if_object_collection~get_iterator( ). -endmethod. - - - - method GET_TABLES_SIZE. - ep_size = tables->if_object_collection~size( ). -endmethod. - - - - - method GET_TITLE. - DATA lv_value TYPE string. - IF ip_escaped EQ abap_true. - lv_value = me->title. - ep_title = zcl_excel_common=>escape_string( lv_value ). - ELSE. - ep_title = me->title. - ENDIF. -endmethod. - - - - - - method GET_VALUE_TYPE. - DATA: lo_addit TYPE REF TO cl_abap_elemdescr, - ls_dfies TYPE dfies, - l_function TYPE funcname, - l_value(50) TYPE c. - - ep_value = ip_value. - ep_value_type = cl_abap_typedescr=>typekind_string. " Thats our default if something goes wrong. - - TRY. - lo_addit ?= cl_abap_typedescr=>describe_by_data( ip_value ). - CATCH cx_sy_move_cast_error. - CLEAR lo_addit. - ENDTRY. - IF lo_addit IS BOUND. - lo_addit->get_ddic_field( RECEIVING p_flddescr = ls_dfies - EXCEPTIONS not_found = 1 - no_ddic_type = 2 - OTHERS = 3 ) . - IF sy-subrc = 0. - ep_value_type = ls_dfies-inttype. - - IF ls_dfies-convexit IS NOT INITIAL. -* We need to convert with output conversion function - CONCATENATE 'CONVERSION_EXIT_' ls_dfies-convexit '_OUTPUT' INTO l_function. - SELECT SINGLE funcname INTO l_function - FROM tfdir - WHERE funcname = l_function. - IF sy-subrc = 0. - CALL FUNCTION l_function - EXPORTING - input = ip_value - IMPORTING -* LONG_TEXT = - output = l_value -* SHORT_TEXT = - EXCEPTIONS - OTHERS = 1. - IF sy-subrc <> 0. -* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO -* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. - ELSE. - ep_value = l_value. - ENDIF. - ENDIF. - ENDIF. - ELSE. - ep_value_type = lo_addit->get_data_type_kind( ip_value ). - ENDIF. - ENDIF. - -endmethod. - - - method PRINT_TITLE_SET_RANGE. -*--------------------------------------------------------------------* -* issue#235 - repeat rows/columns -* - Stefan Schmöcker, 2012-12-02 -*--------------------------------------------------------------------* - - - DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, - lo_range TYPE REF TO zcl_excel_range, - lv_repeat_range_sheetname TYPE string, - lv_repeat_range_col TYPE string, - lv_row_char_from TYPE char10, - lv_row_char_to TYPE char10, - lv_repeat_range_row TYPE string, - lv_repeat_range TYPE string. - - -*--------------------------------------------------------------------* -* Get range that represents printarea -* if non-existant, create it -*--------------------------------------------------------------------* - lo_range_iterator = me->get_ranges_iterator( ). - WHILE lo_range_iterator->has_next( ) = abap_true. - - lo_range ?= lo_range_iterator->get_next( ). - IF lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. - EXIT. " Found it - ENDIF. - CLEAR lo_range. - - ENDWHILE. - - - IF me->print_title_col_from IS INITIAL AND - me->print_title_row_from IS INITIAL. -*--------------------------------------------------------------------* -* No print titles are present, -*--------------------------------------------------------------------* - IF lo_range IS BOUND. - me->ranges->remove( lo_range ). - ENDIF. - ELSE. -*--------------------------------------------------------------------* -* Print titles are present, -*--------------------------------------------------------------------* - IF lo_range IS NOT BOUND. - lo_range = me->add_new_range( ). - lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. - ENDIF. - - lv_repeat_range_sheetname = me->get_title( ). - lv_repeat_range_sheetname = zcl_excel_common=>escape_string( lv_repeat_range_sheetname ). - -*--------------------------------------------------------------------* -* Repeat-columns -*--------------------------------------------------------------------* - IF me->print_title_col_from IS NOT INITIAL. - CONCATENATE lv_repeat_range_sheetname - '!$' me->print_title_col_from - ':$' me->print_title_col_to - INTO lv_repeat_range_col. - ENDIF. - -*--------------------------------------------------------------------* -* Repeat-rows -*--------------------------------------------------------------------* - IF me->print_title_row_from IS NOT INITIAL. - lv_row_char_from = me->print_title_row_from. - lv_row_char_to = me->print_title_row_to. - CONCATENATE '!$' lv_row_char_from - ':$' lv_row_char_to - INTO lv_repeat_range_row. - CONDENSE lv_repeat_range_row NO-GAPS. - CONCATENATE lv_repeat_range_sheetname - lv_repeat_range_row - INTO lv_repeat_range_row. - ENDIF. - -*--------------------------------------------------------------------* -* Concatenate repeat-rows and columns -*--------------------------------------------------------------------* - IF lv_repeat_range_col IS INITIAL. - lv_repeat_range = lv_repeat_range_row. - ELSEIF lv_repeat_range_row IS INITIAL. - lv_repeat_range = lv_repeat_range_col. - ELSE. - CONCATENATE lv_repeat_range_col lv_repeat_range_row - INTO lv_repeat_range SEPARATED BY ','. - ENDIF. - - - lo_range->set_range_value( lv_repeat_range ). - ENDIF. - - - -endmethod. - - - - - - - - - - - - method SET_CELL. - - DATA: lv_column TYPE zexcel_cell_column, - ls_sheet_content TYPE zexcel_s_cell_data, - lv_row_alpha TYPE string, - lv_col_alpha TYPE zexcel_cell_column_alpha, - lv_value TYPE zexcel_cell_value, - lv_data_type TYPE zexcel_cell_data_type, - lv_value_type TYPE abap_typekind, - lo_style TYPE REF TO zcl_excel_style, - lv_style_guid TYPE zexcel_cell_style, - lo_addit TYPE REF TO cl_abap_elemdescr, - lo_value TYPE REF TO data, - lo_value_new TYPE REF TO data. - - FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data, - <fs_numeric> TYPE numeric, - <fs_date> TYPE d, - <fs_time> TYPE t, - <fs_value> TYPE simple. - - IF ip_value IS NOT SUPPLIED AND ip_formula IS NOT SUPPLIED. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Please provide the value or formula'. - ENDIF. - -* Begin of change issue #152 - don't touch exisiting style if only value is passed -* lv_style_guid = ip_style. - lv_column = zcl_excel_common=>convert_column2int( ip_column ). - READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH TABLE KEY cell_row = ip_row " Changed to access via table key , Stefan Schmöcker, 2013-08-03 - cell_column = lv_column. - IF sy-subrc = 0. - IF ip_style IS INITIAL. - " If no style is provided as method-parameter and cell is found use cell's current style - lv_style_guid = <fs_sheet_content>-cell_style. - ELSE. - " Style provided as method-parameter --> use this - lv_style_guid = ip_style. - ENDIF. - ELSE. - " No cell found --> use supplied style even if empty - lv_style_guid = ip_style. - ENDIF. -* End of change issue #152 - don't touch exisiting style if only value is passed - - IF ip_value IS SUPPLIED. - "if data type is passed just write the value. Otherwise map abap type to excel and perform conversion - "IP_DATA_TYPE is passed by excel reader so source types are preserved -*First we get reference into local var. - CREATE DATA lo_value LIKE ip_value. - ASSIGN lo_value->* TO <fs_value>. - <fs_value> = ip_value. - IF ip_data_type IS SUPPLIED. - IF ip_abap_type IS NOT SUPPLIED. - get_value_type( EXPORTING ip_value = ip_value - IMPORTING ep_value = <fs_value> ) . - ENDIF. - lv_value = <fs_value>. - lv_data_type = ip_data_type. - ELSE. - IF ip_abap_type IS SUPPLIED. - lv_value_type = ip_abap_type. - ELSE. - get_value_type( EXPORTING ip_value = ip_value - IMPORTING ep_value = <fs_value> - ep_value_type = lv_value_type ). - ENDIF. - CASE lv_value_type. - WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. - lo_addit = cl_abap_elemdescr=>get_i( ). - CREATE DATA lo_value_new TYPE HANDLE lo_addit. - ASSIGN lo_value_new->* TO <fs_numeric>. - IF sy-subrc = 0. - <fs_numeric> = <fs_value>. - lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). - ENDIF. - - WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. - lo_addit = cl_abap_elemdescr=>get_f( ). - CREATE DATA lo_value_new TYPE HANDLE lo_addit. - ASSIGN lo_value_new->* TO <fs_numeric>. - IF sy-subrc = 0. - <fs_numeric> = <fs_value>. - lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). - ENDIF. - - WHEN cl_abap_typedescr=>typekind_char OR cl_abap_typedescr=>typekind_string OR cl_abap_typedescr=>typekind_num OR - cl_abap_typedescr=>typekind_hex. - lv_value = <fs_value>. - lv_data_type = 's'. - - WHEN cl_abap_typedescr=>typekind_date. - lo_addit = cl_abap_elemdescr=>get_d( ). - CREATE DATA lo_value_new TYPE HANDLE lo_addit. - ASSIGN lo_value_new->* TO <fs_date>. - IF sy-subrc = 0. - <fs_date> = <fs_value>. - lv_value = zcl_excel_common=>date_to_excel_string( ip_value = <fs_date> ) . - ENDIF. -* Begin of change issue #152 - don't touch exisiting style if only value is passed -* Moved to end of routine - apply date-format even if other styleinformation is passed -* IF ip_style IS NOT SUPPLIED. "get default date format in case parameter is initial -* lo_style = excel->add_new_style( ). -* lo_style->number_format->format_code = get_default_excel_date_format( ). -* lv_style_guid = lo_style->get_guid( ). -* ENDIF. -* End of change issue #152 - don't touch exisiting style if only value is passed - - WHEN cl_abap_typedescr=>typekind_time. - lo_addit = cl_abap_elemdescr=>get_t( ). - CREATE DATA lo_value_new TYPE HANDLE lo_addit. - ASSIGN lo_value_new->* TO <fs_time>. - IF sy-subrc = 0. - <fs_time> = <fs_value>. - lv_value = zcl_excel_common=>time_to_excel_string( ip_value = <fs_time> ). - ENDIF. -* Begin of change issue #152 - don't touch exisiting style if only value is passed -* Moved to end of routine - apply time-format even if other styleinformation is passed -* IF ip_style IS NOT SUPPLIED. "get default time format for user in case parameter is initial -* lo_style = excel->add_new_style( ). -* lo_style->number_format->format_code = zcl_excel_style_number_format=>c_format_date_time6. -* lv_style_guid = lo_style->get_guid( ). -* ENDIF. -* End of change issue #152 - don't touch exisiting style if only value is passed - - WHEN OTHERS. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Invalid data type of input value'. - ENDCASE. - ENDIF. - - ENDIF. - - IF ip_hyperlink IS BOUND. - ip_hyperlink->set_cell_reference( ip_column = ip_column - ip_row = ip_row ). - me->hyperlinks->add( ip_hyperlink ). - ENDIF. - -* Begin of change issue #152 - don't touch exisiting style if only value is passed -* Read table moved up, so that current style may be evaluated -* lv_column = zcl_excel_common=>convert_column2int( ip_column ). - -* READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row -* cell_column = lv_column. -* -* IF sy-subrc EQ 0. - IF <fs_sheet_content> IS ASSIGNED. -* End of change issue #152 - don't touch exisiting style if only value is passed - <fs_sheet_content>-cell_value = lv_value. - <fs_sheet_content>-cell_formula = ip_formula. - <fs_sheet_content>-cell_style = lv_style_guid. - <fs_sheet_content>-data_type = lv_data_type. - ELSE. - ls_sheet_content-cell_row = ip_row. - ls_sheet_content-cell_column = lv_column. - ls_sheet_content-cell_value = lv_value. - ls_sheet_content-cell_formula = ip_formula. - ls_sheet_content-cell_style = lv_style_guid. - ls_sheet_content-data_type = lv_data_type. - lv_row_alpha = ip_row. -* SHIFT lv_row_alpha RIGHT DELETING TRAILING space."del #152 - replaced with condense - should be faster -* SHIFT lv_row_alpha LEFT DELETING LEADING space. "del #152 - replaced with condense - should be faster - CONDENSE lv_row_alpha NO-GAPS. "ins #152 - replaced 2 shifts - should be faster - lv_col_alpha = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column - CONCATENATE lv_col_alpha lv_row_alpha INTO ls_sheet_content-cell_coords. " issue #155 - less restrictive typing for ip_column - INSERT ls_sheet_content INTO TABLE sheet_content ASSIGNING <fs_sheet_content>. "ins #152 - Now <fs_sheet_content> always holds the data -* APPEND ls_sheet_content TO sheet_content. -* SORT sheet_content BY cell_row cell_column. - " me->update_dimension_range( ). - - ENDIF. - -* Begin of change issue #152 - don't touch exisiting style if only value is passed -* For Date- or Timefields change the formatcode if nothing is set yet -* Enhancement option: Check if existing formatcode is a date/ or timeformat -* If not, use default - DATA: lo_format_code_datetime TYPE zexcel_number_format. - DATA: stylemapping TYPE zexcel_s_stylemapping. - CASE lv_value_type. - WHEN cl_abap_typedescr=>typekind_date. - TRY. - stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). - CATCH zcx_excel . - ENDTRY. - IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR - stylemapping-complete_style-number_format-format_code IS INITIAL. - lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_std. - ELSE. - lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. - ENDIF. - me->change_cell_style( ip_column = ip_column - ip_row = ip_row - ip_number_format_format_code = lo_format_code_datetime ). - - WHEN cl_abap_typedescr=>typekind_time. - TRY. - stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). - CATCH zcx_excel . - ENDTRY. - IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR - stylemapping-complete_style-number_format-format_code IS INITIAL. - lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_time6. - ELSE. - lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. - ENDIF. - me->change_cell_style( ip_column = ip_column - ip_row = ip_row - ip_number_format_format_code = lo_format_code_datetime ). - - ENDCASE. -* End of change issue #152 - don't touch exisiting style if only value is passed - -* Fix issue #162 - lv_value = ip_value. - IF lv_value CS cl_abap_char_utilities=>cr_lf. - me->change_cell_style( ip_column = ip_column - ip_row = ip_row - ip_alignment_wraptext = abap_true ). - ENDIF. -* End of Fix issue #162 - -endmethod. - - - - - - - METHOD set_cell_formula. - DATA: - lv_column TYPE zexcel_cell_column, - ls_sheet_content LIKE LINE OF me->sheet_content. - - FIELD-SYMBOLS: - <sheet_content> LIKE LINE OF me->sheet_content. - -*--------------------------------------------------------------------* -* Get cell to set formula into -*--------------------------------------------------------------------* - lv_column = zcl_excel_common=>convert_column2int( ip_column ). - READ TABLE me->sheet_content ASSIGNING <sheet_content> WITH TABLE KEY cell_row = ip_row - cell_column = lv_column. - IF sy-subrc <> 0. " Create new entry in sheet_content if necessary - CHECK ip_formula IS INITIAL. " no need to create new entry in sheet_content when no formula is passed - ls_sheet_content-cell_row = ip_row. - ls_sheet_content-cell_column = lv_column. - INSERT ls_sheet_content INTO TABLE me->sheet_content ASSIGNING <sheet_content>. - ENDIF. - -*--------------------------------------------------------------------* -* Fieldsymbol now holds the relevant cell -*--------------------------------------------------------------------* - <sheet_content>-cell_formula = ip_formula. - - -ENDMETHOD. - - - - - - - method SET_CELL_STYLE. - - DATA: lv_column TYPE zexcel_cell_column, - ls_sheet_content TYPE zexcel_s_cell_data, - lv_row_alpha TYPE string, - lo_style TYPE REF TO zcl_excel_style, - lv_style_guid TYPE zexcel_cell_style. - - FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. - - lv_style_guid = ip_style. - - lv_column = zcl_excel_common=>convert_column2int( ip_column ). - - READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row - cell_column = lv_column. - - IF sy-subrc EQ 0. - <fs_sheet_content>-cell_style = lv_style_guid. - ELSE. - set_cell( ip_column = ip_column ip_row = ip_row ip_value = '' ip_style = ip_style ). - ENDIF. - -endmethod. - - - - - - - method SET_COLUMN_WIDTH. - DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. - DATA: width TYPE float. - - column_dimension = me->get_column_dimension( ip_column ). - -* if a fix size is supplied use this - IF ip_width_fix IS SUPPLIED. - TRY. - width = ip_width_fix. - IF width <= 0. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Please supply a positive number as column-width'. - ENDIF. - column_dimension->set_width( width ). - EXIT. - CATCH cx_sy_conversion_no_number. -* Strange stuff passed --> raise error - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Unable to interpret supplied input as number'. - ENDTRY. - ENDIF. - -* If we get down to here, we have to use whatever is found in autosize. - column_dimension->set_auto_size( ip_width_autosize ). - - -endmethod. - - - - - method SET_DEFAULT_EXCEL_DATE_FORMAT. - - IF ip_default_excel_date_format IS INITIAL. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Default date format cannot be blank'. - ENDIF. - - default_excel_date_format = ip_default_excel_date_format. -endmethod. - - - - - - - - method SET_MERGE. - - DATA: lv_column_start TYPE zexcel_cell_column, - lv_column_end TYPE zexcel_cell_column, - ls_sheet_content TYPE zexcel_s_cell_data, - lv_row_alpha TYPE string. - - FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. - - lv_column_start = zcl_excel_common=>convert_column2int( ip_column_start ). - lv_column_end = zcl_excel_common=>convert_column2int( ip_column_end ). - - ls_sheet_content-cell_row = ip_row. - ls_sheet_content-cell_column = lv_column_start. - lv_row_alpha = ip_row. - SHIFT lv_row_alpha RIGHT DELETING TRAILING space. - SHIFT lv_row_alpha LEFT DELETING LEADING space. - CONCATENATE ip_column_start lv_row_alpha INTO ls_sheet_content-cell_coords. - INSERT ls_sheet_content INTO TABLE sheet_content_merge. - - ls_sheet_content-cell_column = lv_column_end. - IF ip_row_to IS SUPPLIED. - ls_sheet_content-cell_row = ip_row_to. - lv_row_alpha = ip_row_to. - ELSE. - lv_row_alpha = ip_row. - ls_sheet_content-cell_row = ip_row. - ENDIF. - - SHIFT lv_row_alpha RIGHT DELETING TRAILING space. - SHIFT lv_row_alpha LEFT DELETING LEADING space. - CONCATENATE ip_column_end lv_row_alpha INTO ls_sheet_content-cell_coords. - INSERT ls_sheet_content INTO TABLE sheet_content_merge. - -endmethod. - - - - method SET_PRINT_GRIDLINES. - me->print_gridlines = i_print_gridlines. -endmethod. - - - - - - method SET_ROW_HEIGHT. - DATA: row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. - DATA: height TYPE float. - - row_dimension = me->get_row_dimension( ip_row ). - -* if a fix size is supplied use this - TRY. - height = ip_height_fix. - IF height <= 0. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Please supply a positive number as row-height'. - ENDIF. - row_dimension->set_row_height( height ). - EXIT. - CATCH cx_sy_conversion_no_number. -* Strange stuff passed --> raise error - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Unable to interpret supplied input as number'. - ENDTRY. - - - -endmethod. - - - - method SET_SHOW_GRIDLINES. - me->show_gridlines = i_show_gridlines. -endmethod. - - - - method SET_SHOW_ROWCOLHEADERS. - me->show_rowcolheaders = i_show_rowcolheaders. -endmethod. - - - - method SET_TABCOLOR. - me->tabcolor = iv_tabcolor. -endmethod. - - - - - - - - - - - - method SET_TABLE. - - DATA: lo_tabdescr TYPE REF TO cl_abap_structdescr, - lr_data TYPE REF TO data, - ls_newline TYPE REF TO data, - ls_header TYPE x030l, - lt_dfies TYPE ddfields, - lv_row_header TYPE zexcel_cell_row VALUE '2', - lv_col_header TYPE zexcel_cell_column_alpha VALUE 'B', - lv_row_int TYPE zexcel_cell_row, - lv_column_int TYPE zexcel_cell_column, - lv_column_alpha TYPE zexcel_cell_column_alpha, - lv_cell_value TYPE zexcel_cell_value. - - - FIELD-SYMBOLS: <fs_table_line> TYPE ANY, - <fs_fldval> TYPE ANY, - <fs_dfies> TYPE dfies, - <fs_cell_value> TYPE zexcel_cell_value. - - lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). - lv_row_int = ip_top_left_row. - - CREATE DATA lr_data LIKE LINE OF ip_table. - - lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). - - ls_header = lo_tabdescr->get_ddic_header( ). - - lt_dfies = lo_tabdescr->get_ddic_field_list( ). - -* It is better to loop column by column - LOOP AT lt_dfies ASSIGNING <fs_dfies>. - lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). - - IF ip_no_header = abap_false. - " First of all write column header - lv_cell_value = <fs_dfies>-scrtext_m. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = lv_cell_value - ip_style = ip_hdr_style ). - IF ip_transpose = abap_true. - ADD 1 TO lv_column_int. - ELSE. - ADD 1 TO lv_row_int. - ENDIF. - ENDIF. - - LOOP AT ip_table ASSIGNING <fs_table_line>. - lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). - ASSIGN COMPONENT <fs_dfies>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. - MOVE <fs_fldval> TO lv_cell_value. - me->set_cell( ip_column = lv_column_alpha - ip_row = lv_row_int - ip_value = <fs_fldval> "lv_cell_value - ip_style = ip_body_style ). - IF ip_transpose = abap_true. - ADD 1 TO lv_column_int. - ELSE. - ADD 1 TO lv_row_int. - ENDIF. - ENDLOOP. - IF ip_transpose = abap_true. - lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). - ADD 1 TO lv_row_int. - ELSE. - lv_row_int = ip_top_left_row. - ADD 1 TO lv_column_int. - ENDIF. - ENDLOOP. - -endmethod. - - - - - method SET_TITLE. -*--------------------------------------------------------------------* -* ToDos: -* 2do§1 The current coding for replacing a named ranges name -* after renaming a sheet should be checked if it is -* really working if sheetname should be escaped -*--------------------------------------------------------------------* - -*--------------------------------------------------------------------* -* issue #230 - Pimp my Code -* - Stefan Schmöcker, (wip ) 2012-12-08 -* - ... -* changes: aligning code -* message made to support multilinguality -*--------------------------------------------------------------------* -* issue#243 - ' is not allowed as first character in sheet title -* - Stefan Schmöcker, 2012-12-02 -* changes: added additional check for ' as first character -*--------------------------------------------------------------------* - DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, - lo_worksheet TYPE REF TO zcl_excel_worksheet, - errormessage TYPE string, - lv_rangesheetname_old TYPE string, - lv_rangesheetname_new TYPE string, - lo_ranges_iterator TYPE REF TO cl_object_collection_iterator, - lo_range TYPE REF TO zcl_excel_range, - lv_range_value TYPE zexcel_range_value, - lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class - - -*--------------------------------------------------------------------* -* Check whether title consists only of allowed characters -* Illegal characters are: / \ [ ] * ? : --> http://msdn.microsoft.com/en-us/library/ff837411.aspx -* Illegal characters not in documentation: ' as first character -*--------------------------------------------------------------------* - IF ip_title CA '/\[]*?:'. - lv_errormessage = 'Found illegal character in sheetname. List of forbidden characters: /\[]*?:'(402). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - IF ip_title IS NOT INITIAL AND ip_title(1) = `'`. - lv_errormessage = 'Sheetname may not start with &'(403). " & used instead of ' to allow fallbacklanguage - REPLACE '&' IN lv_errormessage WITH `'`. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - -*--------------------------------------------------------------------* -* Check whether title is unique in workbook -*--------------------------------------------------------------------* - lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). - WHILE lo_worksheets_iterator->has_next( ) = 'X'. - - lo_worksheet ?= lo_worksheets_iterator->get_next( ). - CHECK me->guid <> lo_worksheet->get_guid( ). " Don't check against itself - IF ip_title = lo_worksheet->get_title( ). " Not unique --> raise exception - errormessage = 'Duplicate sheetname &'. - REPLACE '&' IN errormessage WITH ip_title. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = errormessage. - ENDIF. - - ENDWHILE. - -*--------------------------------------------------------------------* -* Remember old sheetname and rename sheet to desired name -*--------------------------------------------------------------------* - CONCATENATE me->title '!' INTO lv_rangesheetname_old. - me->title = ip_title. - -*--------------------------------------------------------------------* -* After changing this worksheet's title we have to adjust -* all ranges that are referring to this worksheet. -*--------------------------------------------------------------------* -* 2do§1 - Check if the following quickfix is solid -* I fear it isn't - but this implementation is better then -* nothing at all since it handles a supposed majority of cases -*--------------------------------------------------------------------* - CONCATENATE me->title '!' INTO lv_rangesheetname_new. - - lo_ranges_iterator = me->excel->get_ranges_iterator( ). - WHILE lo_ranges_iterator->has_next( ) = 'X'. - - lo_range ?= lo_ranges_iterator->get_next( ). - lv_range_value = lo_range->get_value( ). - REPLACE ALL OCCURRENCES OF lv_rangesheetname_old IN lv_range_value WITH lv_rangesheetname_new. - IF sy-subrc = 0. - lo_range->set_range_value( lv_range_value ). - ENDIF. - - ENDWHILE. - - -endmethod. - - - - method UPDATE_DIMENSION_RANGE. - - DATA: ls_sheet_content TYPE zexcel_s_cell_data, - lt_sheet_content TYPE zexcel_t_cell_data_unsorted, - lv_row_alpha TYPE string, - lv_column_alpha TYPE zexcel_cell_column_alpha. - - CHECK sheet_content IS NOT INITIAL. - -* update dimension range - lt_sheet_content = sheet_content. - "upper left corner - SORT lt_sheet_content BY cell_row. - READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. - upper_cell-cell_row = ls_sheet_content-cell_row. - SORT lt_sheet_content BY cell_column. - READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. - upper_cell-cell_column = ls_sheet_content-cell_column. - - lv_row_alpha = upper_cell-cell_row. - lv_column_alpha = zcl_excel_common=>convert_column2alpha( upper_cell-cell_column ). - SHIFT lv_row_alpha RIGHT DELETING TRAILING space. - SHIFT lv_row_alpha LEFT DELETING LEADING space. - CONCATENATE lv_column_alpha lv_row_alpha INTO upper_cell-cell_coords. - - "bottom right corner - SORT lt_sheet_content BY cell_row DESCENDING. - READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. - lower_cell-cell_row = ls_sheet_content-cell_row. - SORT lt_sheet_content BY cell_column DESCENDING. - READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. - lower_cell-cell_column = ls_sheet_content-cell_column. - - lv_row_alpha = lower_cell-cell_row. - lv_column_alpha = zcl_excel_common=>convert_column2alpha( lower_cell-cell_column ). - SHIFT lv_row_alpha RIGHT DELETING TRAILING space. - SHIFT lv_row_alpha LEFT DELETING LEADING space. - CONCATENATE lv_column_alpha lv_row_alpha INTO lower_cell-cell_coords. - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - - - - method ADD. - - worksheets->add( ip_worksheet ). - -endmethod. - - - method CLEAR. - - worksheets->clear( ). - -endmethod. - - - method CONSTRUCTOR. - - CREATE OBJECT worksheets. - -endmethod. - - - - - method GET. - - DATA lv_index TYPE i. - lv_index = ip_index. - eo_worksheet ?= worksheets->if_object_collection~get( lv_index ). - -endmethod. - - - - method GET_ITERATOR. - - eo_iterator ?= worksheets->if_object_collection~get_iterator( ). - -endmethod. - - - - method IS_EMPTY. - - is_empty = worksheets->if_object_collection~is_empty( ). - -endmethod. - - - - method REMOVE. - - worksheets->remove( ip_worksheet ). - -endmethod. - - - - method SIZE. - - ep_size = worksheets->if_object_collection~size( ). - -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - - - - - - - method CONSTRUCTOR. - me->column_index = zcl_excel_common=>convert_column2int( ip_index ). - me->width = -1. - me->auto_size = abap_false. - me->visible = abap_true. - me->outline_level = 0. - me->collapsed = abap_false. - me->excel = ip_excel. "ins issue #157 - Allow Style for columns - me->worksheet = ip_worksheet. "ins issue #157 - Allow Style for columns - - " set default index to cellXf - me->xf_index = 0. - -endmethod. - - - - method GET_AUTO_SIZE. - r_auto_size = me->auto_size. -endmethod. - - - - method GET_COLLAPSED. - r_Collapsed = me->Collapsed. -endmethod. - - - - method GET_COLUMN_INDEX. - r_column_index = me->column_index. -endmethod. - - - - - method GET_COLUMN_STYLE_GUID. - IF me->style_guid IS NOT INITIAL. - ep_style_guid = me->style_guid. - ELSE. - ep_style_guid = me->worksheet->zif_excel_sheet_properties~get_style( ). - ENDIF. -endmethod. - - - - method GET_OUTLINE_LEVEL. - r_outline_level = me->outline_level. -endmethod. - - - - method GET_VISIBLE. - r_Visible = me->Visible. -endmethod. - - - - method GET_WIDTH. - r_WIDTH = me->WIDTH. -endmethod. - - - - method GET_XF_INDEX. - r_xf_index = me->xf_index. -endmethod. - - - - - method SET_AUTO_SIZE. - me->auto_size = ip_auto_size. - r_worksheet_columndime = me. -endmethod. - - - - - method SET_COLLAPSED. - me->Collapsed = ip_Collapsed. - r_worksheet_columndime = me. -endmethod. - - - - - method SET_COLUMN_INDEX. - me->column_index = zcl_excel_common=>convert_column2int( ip_index ). - r_worksheet_columndime = me. -endmethod. - - - - - method SET_COLUMN_STYLE_BY_GUID. - DATA: stylemapping TYPE zexcel_s_stylemapping. - - IF me->excel IS NOT BOUND. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Internal error - reference to ZCL_EXCEL not bound'. - ENDIF. - TRY. - stylemapping = me->excel->get_style_to_guid( ip_style_guid ). - me->style_guid = stylemapping-guid. - - CATCH zcx_excel . - EXIT. " leave as is in case of error - ENDTRY. - -endmethod. - - - - method SET_OUTLINE_LEVEL. - me->outline_level = ip_outline_level. -endmethod. - - - - - method SET_VISIBLE. - me->Visible = ip_Visible. - r_worksheet_columndime = me. -endmethod. - - - - - - method SET_WIDTH. - TRY. - me->width = ip_width. - r_worksheet_columndime = me. - CATCH cx_sy_conversion_no_number. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Unable to interpret width as number'. - ENDTRY. -endmethod. - - - - - method SET_XF_INDEX. - me->XF_INDEX = ip_XF_INDEX. - r_worksheet_columndime = me. -endmethod. - - - - *"* local class implementation for public class -*"* use this source file for the implementation part of -*"* local helper classes - *"* use this source file for any type declarations (class -*"* definitions, interfaces or data types) you need for method -*"* implementation or private method's signature - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - ABAP - - - - - - - - - method CONSTRUCTOR. - " Initialise values - me->row_index = ip_index. - me->row_height = -1. - me->visible = abap_true. - me->outline_level = 0. - me->collapsed = abap_false. - - " set row dimension as unformatted by default - me->xf_index = 0. -endmethod. - - - - method GET_COLLAPSED. - r_collapsed = me->collapsed. -endmethod. - - - - method GET_OUTLINE_LEVEL. - r_outline_level = me->outline_level. -endmethod. - - - - method GET_ROW_HEIGHT. - r_row_height = me->row_height. -endmethod. - - - - method GET_ROW_INDEX. - r_row_index = me->row_index. -endmethod. - - - - method GET_VISIBLE. - r_visible = me->visible. -endmethod. - - - - method GET_XF_INDEX. - r_xf_index = me->xf_index. -endmethod. - - - - method SET_COLLAPSED. - me->collapsed = ip_collapsed. -endmethod. - - - - - method SET_OUTLINE_LEVEL. - IF ip_outline_level < 0 - OR ip_outline_level > 7. - - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Outline level must range between 0 and 7.'. - - ENDIF. - me->outline_level = ip_outline_level. -endmethod. - - - - - method SET_ROW_HEIGHT. - TRY. - me->row_height = ip_row_height. - CATCH cx_sy_conversion_no_number. - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = 'Unable to interpret ip_row_height as number'. - ENDTRY. -endmethod. - - - - method SET_ROW_INDEX. - me->row_index = ip_index. -endmethod. - - - - method SET_VISIBLE. - me->visible = ip_visible. -endmethod. - - - - method SET_XF_INDEX. - me->XF_INDEX = ip_XF_INDEX. -endmethod. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -25464,10 +24676,16 @@ endmethod. - + - + + + + + + + @@ -25530,13 +24748,7 @@ endmethod. - - - - - - - + @@ -25545,7 +24757,7 @@ endmethod. - + @@ -25608,6 +24820,12 @@ endmethod. + + + + + + @@ -25617,7 +24835,7 @@ endmethod. - + @@ -25674,21 +24892,6 @@ endmethod. - - - - - - - - - - - - - - - @@ -25772,14 +24975,15 @@ endmethod. - + - - - + + + + @@ -27400,7 +26604,7 @@ START-OF-SELECTION. lo_style_rotated = lo_excel->add_new_style( ). lo_style_rotated->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. lo_style_rotated->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. - lo_style_rotated->alignment->textrotation = 165. " -75° == 90° + 75° + lo_style_rotated->alignment->textrotation = 165. " -75° == 90° + 75° lv_style_rotated_guid = lo_style_rotated->get_guid( ). @@ -27434,7 +26638,7 @@ START-OF-SELECTION. " Rotated lo_worksheet->set_cell( ip_row = 10 ip_column = 'D' - ip_value = 'This is a centered text rotated by -75°' + ip_value = 'This is a centered text rotated by -75°' ip_style = lv_style_rotated_guid ). " forced line break @@ -29638,272 +28842,6 @@ START-OF-SELECTION. *** Create output lcl_output=>output( lo_excel ). - - - - - - - *&---------------------------------------------------------------------* -*& Report ZABAP2XLSX_DEMO_SHOW -*&---------------------------------------------------------------------* -REPORT zabap2xlsx_demo_like_se83. - - -*----------------------------------------------------------------------* -* CLASS lcl_perform DEFINITION -*----------------------------------------------------------------------* -CLASS lcl_perform DEFINITION CREATE PRIVATE. - PUBLIC SECTION. - CLASS-METHODS: setup_objects, - collect_reports, - - handle_nav FOR EVENT double_click OF cl_gui_alv_grid - IMPORTING e_row. - - PRIVATE SECTION. - TYPES: BEGIN OF ty_reports, - progname TYPE reposrc-progname, - sort TYPE reposrc-progname, - filename TYPE string, - END OF ty_reports. - - CLASS-DATA: - lo_grid TYPE REF TO cl_gui_alv_grid, - lo_text TYPE REF TO cl_gui_textedit, - cl_document TYPE REF TO i_oi_document_proxy, - - t_reports TYPE STANDARD TABLE OF ty_reports WITH NON-UNIQUE DEFAULT KEY. - CLASS-DATA:error TYPE REF TO i_oi_error, - t_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY, - cl_control TYPE REF TO i_oi_container_control. "Office Dokument - -ENDCLASS. "lcl_perform DEFINITION - - -START-OF-SELECTION. - lcl_perform=>collect_reports( ). - lcl_perform=>setup_objects( ). - -END-OF-SELECTION. - - WRITE '.'. " Force output - - -*----------------------------------------------------------------------* -* CLASS lcl_perform IMPLEMENTATION -*----------------------------------------------------------------------* -CLASS lcl_perform IMPLEMENTATION. - METHOD setup_objects. - DATA: lo_split TYPE REF TO cl_gui_splitter_container, - lo_container TYPE REF TO cl_gui_container. - - DATA: it_fieldcat TYPE lvc_t_fcat, - is_layout TYPE lvc_s_layo, - is_variant TYPE disvariant. - FIELD-SYMBOLS: <fc> LIKE LINE OF it_fieldcat. - - - CREATE OBJECT lo_split - EXPORTING - parent = cl_gui_container=>screen0 - rows = 1 - columns = 3 - no_autodef_progid_dynnr = 'X'. - lo_split->set_column_width( EXPORTING id = 1 - width = 20 ). - lo_split->set_column_width( EXPORTING id = 2 - width = 40 ). - -* Left: List of reports - lo_container = lo_split->get_container( row = 1 - column = 1 ). - - CREATE OBJECT lo_grid - EXPORTING - i_parent = lo_container. - SET HANDLER lcl_perform=>handle_nav FOR lo_grid. - - is_variant-report = sy-repid. - is_variant-handle = '0001'. - - is_layout-cwidth_opt = 'X'. - - APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. - <fc>-fieldname = 'PROGNAME'. - <fc>-tabname = 'REPOSRC'. - - APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. - <fc>-fieldname = 'SORT'. - <fc>-ref_field = 'PROGNAME'. - <fc>-ref_table = 'REPOSRC'. - - - lo_grid->set_table_for_first_display( EXPORTING - is_variant = is_variant - i_save = 'A' - is_layout = is_layout - CHANGING - it_outtab = t_reports - it_fieldcatalog = it_fieldcat - EXCEPTIONS - invalid_parameter_combination = 1 - program_error = 2 - too_many_lines = 3 - OTHERS = 4 ). - -* Middle: Text with coding - lo_container = lo_split->get_container( row = 1 - column = 2 ). - CREATE OBJECT lo_text - EXPORTING - parent = lo_container. - lo_text->set_readonly_mode( cl_gui_textedit=>true ). - lo_text->set_font_fixed( ). - - - -* right: DemoOutput - lo_container = lo_split->get_container( row = 1 - column = 3 ). - - c_oi_container_control_creator=>get_container_control( IMPORTING control = cl_control - error = error ). - APPEND error TO t_errors. - - cl_control->init_control( EXPORTING inplace_enabled = 'X' - no_flush = 'X' - r3_application_name = 'Demo Document Container' - parent = lo_container - IMPORTING error = error - EXCEPTIONS OTHERS = 2 ). - APPEND error TO t_errors. - - cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL - no_flush = ' ' - IMPORTING document_proxy = cl_document - error = error ). - APPEND error TO t_errors. -* Errorhandling should be inserted here - - - ENDMETHOD. "setup_objects - - "collect_reports - METHOD collect_reports. - FIELD-SYMBOLS:<report> LIKE LINE OF t_reports. - DATA: t_source TYPE STANDARD TABLE OF text255 WITH NON-UNIQUE DEFAULT KEY. - -* Get all demoreports - SELECT progname - INTO CORRESPONDING FIELDS OF TABLE t_reports - FROM reposrc - WHERE progname LIKE 'ZDEMO_EXCEL%' - AND progname <> sy-repid - AND subc = '1'. - - LOOP AT t_reports ASSIGNING <report>. - -* Check if already switched to new outputoptions - READ REPORT <report>-progname INTO t_source. - IF sy-subrc = 0. - FIND 'INCLUDE zdemo_excel_outputopt_incl.' IN TABLE t_source IGNORING CASE. - ENDIF. - IF sy-subrc <> 0. - DELETE t_reports. - CONTINUE. - ENDIF. - - -* Build half-numeric sort - <report>-sort = <report>-progname. - REPLACE REGEX '(ZDEMO_EXCEL)(\d\d)\s*$' IN <report>-sort WITH '$1\0$2'. " REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE - - REPLACE REGEX '(ZDEMO_EXCEL)(\d)\s*$' IN <report>-sort WITH '$1\0\0$2'. - ENDLOOP. - SORT t_reports BY sort progname. - - ENDMETHOD. "collect_reports - - METHOD handle_nav. - CONSTANTS: filename TYPE text80 VALUE 'ZABAP2XLSX_DEMO_SHOW.xlsx'. - DATA: wa_report LIKE LINE OF t_reports, - t_source TYPE STANDARD TABLE OF text255, - t_rawdata TYPE solix_tab, - wa_rawdata LIKE LINE OF t_rawdata, - bytecount TYPE i, - length TYPE i, - add_selopt TYPE flag. - - - READ TABLE t_reports INTO wa_report INDEX e_row-index. - CHECK sy-subrc = 0. - -* Set new text into middle frame - READ REPORT wa_report-progname INTO t_source. - lo_text->set_text_as_r3table( EXPORTING table = t_source ). - - -* Unload old xls-file - cl_document->close_document( ). - -* Get the demo -* If additional parameters found on selection screen, start via selection screen , otherwise start w/o - CLEAR add_selopt. - FIND 'PARAMETERS' IN TABLE t_source. - IF sy-subrc = 0. - add_selopt = 'X'. - ELSE. - FIND 'SELECT-OPTIONS' IN TABLE t_source. - IF sy-subrc = 0. - add_selopt = 'X'. - ENDIF. - ENDIF. - IF add_selopt IS INITIAL. - SUBMIT (wa_report-progname) AND RETURN - WITH p_backfn = filename - WITH rb_back = 'X' - WITH rb_down = ' ' - WITH rb_send = ' ' - WITH rb_show = ' '. - ELSE. - SUBMIT (wa_report-progname) VIA SELECTION-SCREEN AND RETURN - WITH p_backfn = filename - WITH rb_back = 'X' - WITH rb_down = ' ' - WITH rb_send = ' ' - WITH rb_show = ' '. - ENDIF. - - OPEN DATASET filename FOR INPUT IN BINARY MODE. - IF sy-subrc = 0. - DO. - CLEAR wa_rawdata. - READ DATASET filename INTO wa_rawdata LENGTH length. - IF sy-subrc <> 0. - APPEND wa_rawdata TO t_rawdata. - ADD length TO bytecount. - EXIT. - ENDIF. - APPEND wa_rawdata TO t_rawdata. - ADD length TO bytecount. - ENDDO. - CLOSE DATASET filename. - ENDIF. - - cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL - no_flush = ' ' - IMPORTING document_proxy = cl_document - error = error ). - - cl_document->open_document_from_table( EXPORTING document_size = bytecount - document_table = t_rawdata - open_inplace = 'X' ). - - ENDMETHOD. "handle_nav - -ENDCLASS. "lcl_perform IMPLEMENTATION - @@ -30144,7 +29082,7 @@ CLASS lcl_output IMPLEMENTATION. ENDAT. TRANSFER <rawdata> TO p_backfn. - SUBTRACT 255 FROM bytes_remain. " Solix hat Länge 255 + SUBTRACT 255 FROM bytes_remain. " Solix hat Länge 255 ENDLOOP. @@ -32102,6 +31040,272 @@ START-OF-SELECTION. *** Create output lcl_output=>output( lo_excel ). + + + + + + + *&---------------------------------------------------------------------* +*& Report ZABAP2XLSX_DEMO_SHOW +*&---------------------------------------------------------------------* +REPORT zabap2xlsx_demo_like_se83. + + +*----------------------------------------------------------------------* +* CLASS lcl_perform DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_perform DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS: setup_objects, + collect_reports, + + handle_nav FOR EVENT double_click OF cl_gui_alv_grid + IMPORTING e_row. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_reports, + progname TYPE reposrc-progname, + sort TYPE reposrc-progname, + filename TYPE string, + END OF ty_reports. + + CLASS-DATA: + lo_grid TYPE REF TO cl_gui_alv_grid, + lo_text TYPE REF TO cl_gui_textedit, + cl_document TYPE REF TO i_oi_document_proxy, + + t_reports TYPE STANDARD TABLE OF ty_reports WITH NON-UNIQUE DEFAULT KEY. + CLASS-DATA:error TYPE REF TO i_oi_error, + t_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY, + cl_control TYPE REF TO i_oi_container_control. "Office Dokument + +ENDCLASS. "lcl_perform DEFINITION + + +START-OF-SELECTION. + lcl_perform=>collect_reports( ). + lcl_perform=>setup_objects( ). + +END-OF-SELECTION. + + WRITE '.'. " Force output + + +*----------------------------------------------------------------------* +* CLASS lcl_perform IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_perform IMPLEMENTATION. + METHOD setup_objects. + DATA: lo_split TYPE REF TO cl_gui_splitter_container, + lo_container TYPE REF TO cl_gui_container. + + DATA: it_fieldcat TYPE lvc_t_fcat, + is_layout TYPE lvc_s_layo, + is_variant TYPE disvariant. + FIELD-SYMBOLS: <fc> LIKE LINE OF it_fieldcat. + + + CREATE OBJECT lo_split + EXPORTING + parent = cl_gui_container=>screen0 + rows = 1 + columns = 3 + no_autodef_progid_dynnr = 'X'. + lo_split->set_column_width( EXPORTING id = 1 + width = 20 ). + lo_split->set_column_width( EXPORTING id = 2 + width = 40 ). + +* Left: List of reports + lo_container = lo_split->get_container( row = 1 + column = 1 ). + + CREATE OBJECT lo_grid + EXPORTING + i_parent = lo_container. + SET HANDLER lcl_perform=>handle_nav FOR lo_grid. + + is_variant-report = sy-repid. + is_variant-handle = '0001'. + + is_layout-cwidth_opt = 'X'. + + APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. + <fc>-fieldname = 'PROGNAME'. + <fc>-tabname = 'REPOSRC'. + + APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. + <fc>-fieldname = 'SORT'. + <fc>-ref_field = 'PROGNAME'. + <fc>-ref_table = 'REPOSRC'. + + + lo_grid->set_table_for_first_display( EXPORTING + is_variant = is_variant + i_save = 'A' + is_layout = is_layout + CHANGING + it_outtab = t_reports + it_fieldcatalog = it_fieldcat + EXCEPTIONS + invalid_parameter_combination = 1 + program_error = 2 + too_many_lines = 3 + OTHERS = 4 ). + +* Middle: Text with coding + lo_container = lo_split->get_container( row = 1 + column = 2 ). + CREATE OBJECT lo_text + EXPORTING + parent = lo_container. + lo_text->set_readonly_mode( cl_gui_textedit=>true ). + lo_text->set_font_fixed( ). + + + +* right: DemoOutput + lo_container = lo_split->get_container( row = 1 + column = 3 ). + + c_oi_container_control_creator=>get_container_control( IMPORTING control = cl_control + error = error ). + APPEND error TO t_errors. + + cl_control->init_control( EXPORTING inplace_enabled = 'X' + no_flush = 'X' + r3_application_name = 'Demo Document Container' + parent = lo_container + IMPORTING error = error + EXCEPTIONS OTHERS = 2 ). + APPEND error TO t_errors. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + APPEND error TO t_errors. +* Errorhandling should be inserted here + + + ENDMETHOD. "setup_objects + + "collect_reports + METHOD collect_reports. + FIELD-SYMBOLS:<report> LIKE LINE OF t_reports. + DATA: t_source TYPE STANDARD TABLE OF text255 WITH NON-UNIQUE DEFAULT KEY. + +* Get all demoreports + SELECT progname + INTO CORRESPONDING FIELDS OF TABLE t_reports + FROM reposrc + WHERE progname LIKE 'ZDEMO_EXCEL%' + AND progname <> sy-repid + AND subc = '1'. + + LOOP AT t_reports ASSIGNING <report>. + +* Check if already switched to new outputoptions + READ REPORT <report>-progname INTO t_source. + IF sy-subrc = 0. + FIND 'INCLUDE zdemo_excel_outputopt_incl.' IN TABLE t_source IGNORING CASE. + ENDIF. + IF sy-subrc <> 0. + DELETE t_reports. + CONTINUE. + ENDIF. + + +* Build half-numeric sort + <report>-sort = <report>-progname. + REPLACE REGEX '(ZDEMO_EXCEL)(\d\d)\s*$' IN <report>-sort WITH '$1\0$2'. " REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE + + REPLACE REGEX '(ZDEMO_EXCEL)(\d)\s*$' IN <report>-sort WITH '$1\0\0$2'. + ENDLOOP. + SORT t_reports BY sort progname. + + ENDMETHOD. "collect_reports + + METHOD handle_nav. + CONSTANTS: filename TYPE text80 VALUE 'ZABAP2XLSX_DEMO_SHOW.xlsx'. + DATA: wa_report LIKE LINE OF t_reports, + t_source TYPE STANDARD TABLE OF text255, + t_rawdata TYPE solix_tab, + wa_rawdata LIKE LINE OF t_rawdata, + bytecount TYPE i, + length TYPE i, + add_selopt TYPE flag. + + + READ TABLE t_reports INTO wa_report INDEX e_row-index. + CHECK sy-subrc = 0. + +* Set new text into middle frame + READ REPORT wa_report-progname INTO t_source. + lo_text->set_text_as_r3table( EXPORTING table = t_source ). + + +* Unload old xls-file + cl_document->close_document( ). + +* Get the demo +* If additional parameters found on selection screen, start via selection screen , otherwise start w/o + CLEAR add_selopt. + FIND 'PARAMETERS' IN TABLE t_source. + IF sy-subrc = 0. + add_selopt = 'X'. + ELSE. + FIND 'SELECT-OPTIONS' IN TABLE t_source. + IF sy-subrc = 0. + add_selopt = 'X'. + ENDIF. + ENDIF. + IF add_selopt IS INITIAL. + SUBMIT (wa_report-progname) AND RETURN + WITH p_backfn = filename + WITH rb_back = 'X' + WITH rb_down = ' ' + WITH rb_send = ' ' + WITH rb_show = ' '. + ELSE. + SUBMIT (wa_report-progname) VIA SELECTION-SCREEN AND RETURN + WITH p_backfn = filename + WITH rb_back = 'X' + WITH rb_down = ' ' + WITH rb_send = ' ' + WITH rb_show = ' '. + ENDIF. + + OPEN DATASET filename FOR INPUT IN BINARY MODE. + IF sy-subrc = 0. + DO. + CLEAR wa_rawdata. + READ DATASET filename INTO wa_rawdata LENGTH length. + IF sy-subrc <> 0. + APPEND wa_rawdata TO t_rawdata. + ADD length TO bytecount. + EXIT. + ENDIF. + APPEND wa_rawdata TO t_rawdata. + ADD length TO bytecount. + ENDDO. + CLOSE DATASET filename. + ENDIF. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + + cl_document->open_document_from_table( EXPORTING document_size = bytecount + document_table = t_rawdata + open_inplace = 'X' ). + + ENDMETHOD. "handle_nav + +ENDCLASS. "lcl_perform IMPLEMENTATION + @@ -36580,56 +35784,849 @@ START-OF-SELECTION. *** Create output lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -36641,113 +36638,34 @@ START-OF-SELECTION. - + - - + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -36761,843 +36679,199 @@ START-OF-SELECTION. - - + + - - + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37670,84 +36944,13 @@ START-OF-SELECTION. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - @@ -37837,4 +37040,12 @@ START-OF-SELECTION. + + + + + + + + diff --git a/build/ABAP2XLSX_V_7_0.zip b/build/ABAP2XLSX_V_7_0.zip index 24789f84dcd648b05addad1141133528ae9f709f..d478a558afd5232ebeac32f152c466a59c1a0f29 100644 GIT binary patch literal 288183 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

-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

&u?x`Ub{b5}n+ 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%0APnpv-R!m!^Cmk!VYSj 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