From e26b71976a0404ea910f2ad8e12df81382ba28c9 Mon Sep 17 00:00:00 2001 From: Alessandro Iannacci Date: Tue, 23 Jun 2015 14:39:58 +0200 Subject: [PATCH] New Daily Nugget V 7.0.4 (NO Transports - just nugget) New Daily Nugget V 7.0.4 (NO Transports - just nugget) included all the new slenkees, consistency check and corrections. --- build/ABAP2XLSX_V_7_0_4.nugg | 42337 ++++++++++++++++ build/ABAP2XLSX_V_7_0_4.nugg.zip | Bin 0 -> 324753 bytes .../{ => old_releases}/ABAP2XLSX_V_7_0_3.nugg | 0 .../ABAP2XLSX_V_7_0_3.nugg.zip | Bin .../{ => old_releases}/ABAP2XLSX_V_7_0_3.zip | Bin 5 files changed, 42337 insertions(+) create mode 100644 build/ABAP2XLSX_V_7_0_4.nugg create mode 100644 build/ABAP2XLSX_V_7_0_4.nugg.zip rename build/{ => old_releases}/ABAP2XLSX_V_7_0_3.nugg (100%) rename build/{ => old_releases}/ABAP2XLSX_V_7_0_3.nugg.zip (100%) rename build/{ => old_releases}/ABAP2XLSX_V_7_0_3.zip (100%) diff --git a/build/ABAP2XLSX_V_7_0_4.nugg b/build/ABAP2XLSX_V_7_0_4.nugg new file mode 100644 index 0000000..9fced81 --- /dev/null +++ b/build/ABAP2XLSX_V_7_0_4.nugg @@ -0,0 +1,42337 @@ + + + + *"* 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 + TYPES: BEGIN OF t_relationship, + id TYPE string, + type TYPE string, + target TYPE string, + END OF t_relationship. + +* + CLASS lcl_abap_zip_archive DEFINITION + INHERITING FROM lcl_zip_archive + CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS create + IMPORTING i_data TYPE xstring + RETURNING value(r_zip) TYPE REF TO lcl_zip_archive + RAISING zcx_excel. + METHODS read REDEFINITION. + PRIVATE SECTION. + DATA: abap_zip TYPE REF TO cl_abap_zip. + METHODS constructor IMPORTING i_data TYPE xstring + RAISING zcx_excel. + ENDCLASS. "lcl_abap_zip_archive DEFINITION + +* + CLASS lcl_alternate_zip_archive DEFINITION + INHERITING FROM lcl_zip_archive + CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS create + IMPORTING i_data TYPE xstring + i_alternate_zip_class TYPE seoclsname + RETURNING value(r_zip) TYPE REF TO lcl_zip_archive + RAISING zcx_excel. + METHODS read REDEFINITION. + PRIVATE SECTION. + DATA: alternate_zip TYPE REF TO object. + METHODS constructor + IMPORTING i_data TYPE xstring + i_alternate_zip_class TYPE seoclsname + RAISING zcx_excel. + ENDCLASS. "lcl_alternate_zip_archive DEFINITION + +* + CLASS lcl_abap_zip_archive IMPLEMENTATION. + METHOD create. + CREATE OBJECT r_zip TYPE lcl_abap_zip_archive + EXPORTING + i_data = i_data. + ENDMETHOD. "create + METHOD constructor. + DATA: lv_errormessage TYPE string. + super->constructor( ). + CREATE OBJECT abap_zip. + abap_zip->load( + EXPORTING + zip = i_data + EXCEPTIONS + zip_parse_error = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + lv_errormessage = 'ZIP parse error'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "constructor + METHOD read. + DATA: lv_errormessage TYPE string. + CALL METHOD abap_zip->get + EXPORTING + name = i_filename + IMPORTING + content = r_content + EXCEPTIONS + zip_index_error = 1 + zip_decompression_error = 2 + OTHERS = 3. + IF sy-subrc <> 0. + lv_errormessage = 'File not found in zip-archive'(003). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "read + ENDCLASS. "lcl_abap_zip_archive IMPLEMENTATION + +* + CLASS lcl_alternate_zip_archive IMPLEMENTATION. + METHOD create. + CREATE OBJECT r_zip TYPE lcl_alternate_zip_archive + EXPORTING + i_alternate_zip_class = i_alternate_zip_class + i_data = i_data. + ENDMETHOD. "create + METHOD constructor. + DATA: lv_errormessage TYPE string. + super->constructor( ). + CREATE OBJECT alternate_zip TYPE (i_alternate_zip_class). + TRY. + CALL METHOD alternate_zip->('LOAD') + EXPORTING + zip = i_data + EXCEPTIONS + zip_parse_error = 1 + OTHERS = 2. + CATCH cx_sy_dyn_call_illegal_method. + lv_errormessage = 'Method LOAD missing in alternative zipclass'. "#EC NOTEXT This is a workaround until class CL_ABAP_ZIP is fixed + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDTRY. + + IF sy-subrc <> 0. + lv_errormessage = 'ZIP parse error'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "constructor + METHOD read. + DATA: lv_errormessage TYPE string. + TRY. + CALL METHOD alternate_zip->('GET') + EXPORTING + name = i_filename + IMPORTING + content = r_content " Contents + EXCEPTIONS + zip_index_error = 1 + zip_decompression_error = 2 + OTHERS = 3. + CATCH cx_sy_dyn_call_illegal_method. + lv_errormessage = 'Method GET missing in alternative zipclass'. "#EC NOTEXT This is a workaround until class CL_ABAP_ZIP is fixed + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDTRY. + IF sy-subrc <> 0. + lv_errormessage = 'File not found in zip-archive'(003). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "read + ENDCLASS. "lcl_alternate_zip_archive IMPLEMENTATION + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + +* +class lcl_zip_archive definition abstract. + public section. + methods read abstract + importing i_filename type csequence + returning value(r_content) type xstring " Remember copy-on-write! + raising zcx_excel. +endclass. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + IXML + + + + + + + METHOD zif_excel_reader~load. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Map Document Properties to ZCL_EXCEL +*--------------------------------------------------------------------* + + CONSTANTS: lcv_core_properties TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + lcv_office_document TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument'. + + DATA: lo_rels TYPE REF TO if_ixml_document, + lo_node TYPE REF TO if_ixml_element, + ls_relationship TYPE t_relationship. + +*--------------------------------------------------------------------* +* §1 Create EXCEL-Object we want to return to caller + +* §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 +* +* The xlsx Zip-archive has generally the following folder structure: +* <root> | +* |--> _rels +* |--> doc_Props +* |--> xl | +* |--> _rels +* |--> theme +* |--> worksheets + +* §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"> +* <Relationship Target="docProps/app.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Id="rId3"/> +* <Relationship Target="docProps/core.xml" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Id="rId2"/> +* <Relationship Target="xl/workbook.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Id="rId1"/> +* </Relationships> +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* §1 Create EXCEL-Object we want to return to caller +*--------------------------------------------------------------------* + IF iv_zcl_excel_classname IS INITIAL. + CREATE OBJECT r_excel. + ELSE. + CREATE OBJECT r_excel TYPE (iv_zcl_excel_classname). + ENDIF. + + zip = create_zip_archive( i_xlsx_binary = i_excel2007 + i_use_alternate_zip = i_use_alternate_zip ). + +*--------------------------------------------------------------------* +* §2 Get file in folderstructure +*--------------------------------------------------------------------* + lo_rels = get_ixml_from_zip_archive( '_rels/.rels' ). + +*--------------------------------------------------------------------* +* §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. + + fill_struct_from_attributes( EXPORTING + ip_element = lo_node + CHANGING + cp_structure = ls_relationship ). + CASE ls_relationship-type. + + WHEN lcv_office_document. +*--------------------------------------------------------------------* +* Parse workbook - main part here +*--------------------------------------------------------------------* + load_workbook( iv_workbook_full_filename = ls_relationship-target + io_excel = r_excel ). + + WHEN lcv_core_properties. + " 2do§1 Map Document Properties to ZCL_EXCEL + + WHEN OTHERS. + + ENDCASE. + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + METHOD zif_excel_reader~load_file. + + DATA: lv_excel_data TYPE xstring. + +*--------------------------------------------------------------------* +* Read file into binary string +*--------------------------------------------------------------------* + IF i_from_applserver = abap_true. + lv_excel_data = read_from_applserver( i_filename ). + ELSE. + lv_excel_data = read_from_local_file( i_filename ). + ENDIF. + +*--------------------------------------------------------------------* +* Parse Excel data into ZCL_EXCEL object from binary string +*--------------------------------------------------------------------* + r_excel = zif_excel_reader~load( i_excel2007 = lv_excel_data + i_use_alternate_zip = i_use_alternate_zip + iv_zcl_excel_classname = iv_zcl_excel_classname ). + +ENDMETHOD. + + + + + + + METHOD create_zip_archive. + CASE i_use_alternate_zip. + WHEN space. + e_zip = lcl_abap_zip_archive=>create( i_xlsx_binary ). + WHEN OTHERS. + e_zip = lcl_alternate_zip_archive=>create( i_data = i_xlsx_binary + i_alternate_zip_class = i_use_alternate_zip ). + ENDCASE. +ENDMETHOD. + + + + + METHOD fill_row_outlines. + + TYPES: BEGIN OF lts_row_data, + row TYPE i, + outline_level TYPE i, + END OF lts_row_data, + ltt_row_data TYPE SORTED TABLE OF lts_row_data WITH UNIQUE KEY row. + + DATA: lt_row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + + lt_row_data TYPE ltt_row_data, + ls_row_data LIKE LINE OF lt_row_data, + lt_collapse_rows TYPE HASHED TABLE OF i WITH UNIQUE KEY table_line, + + lv_collapsed TYPE abap_bool, + + lv_outline_level TYPE i, + lv_next_consecutive_row TYPE i, + lt_outline_rows TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + ls_outline_row LIKE LINE OF lt_outline_rows, + + lv_row_offset TYPE i, + lv_row_collapse_flag TYPE i. + + + FIELD-SYMBOLS: <ls_row_dimension> LIKE LINE OF lt_row_dimensions, + <ls_row_data> LIKE LINE OF lt_row_data. + +* First collect information about outlines ( outline leven and collapsed state ) + lt_row_dimensions = io_worksheet->get_row_dimensions( ). + LOOP AT lt_row_dimensions ASSIGNING <ls_row_dimension>. + + ls_row_data-row = <ls_row_dimension>-row. + ls_row_data-outline_level = <ls_row_dimension>-row_dimension->get_outline_level( ). + IF ls_row_data-outline_level IS NOT INITIAL. + INSERT ls_row_data INTO TABLE lt_row_data. + ENDIF. + + lv_collapsed = <ls_row_dimension>-row_dimension->get_collapsed( ). + IF lv_collapsed = abap_true. + INSERT <ls_row_dimension>-row INTO TABLE lt_collapse_rows. + ENDIF. + + ENDLOOP. + +* Now parse this information - we need consecutive rows - any gap will create a new outline + DO 7 TIMES. " max number of outlines allowed + lv_outline_level = sy-index. + CLEAR lv_next_consecutive_row. + CLEAR ls_outline_row. + LOOP AT lt_row_data ASSIGNING <ls_row_data> WHERE outline_level >= lv_outline_level. + + IF lv_next_consecutive_row <> <ls_row_data>-row " A gap --> close all open outlines + AND lv_next_consecutive_row IS NOT INITIAL. " First time in loop. + INSERT ls_outline_row INTO TABLE lt_outline_rows. + CLEAR: ls_outline_row. + ENDIF. + + IF ls_outline_row-row_from IS INITIAL. + ls_outline_row-row_from = <ls_row_data>-row. + ENDIF. + ls_outline_row-row_to = <ls_row_data>-row. + + lv_next_consecutive_row = <ls_row_data>-row + 1. + + ENDLOOP. + IF ls_outline_row-row_from IS NOT INITIAL. + INSERT ls_outline_row INTO TABLE lt_outline_rows. + ENDIF. + ENDDO. + +* lt_outline_rows holds all outline information +* we now need to determine whether the outline is collapsed or not + LOOP AT lt_outline_rows INTO ls_outline_row. + + IF io_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_off. + lv_row_collapse_flag = ls_outline_row-row_from - 1. + ELSE. + lv_row_collapse_flag = ls_outline_row-row_to + 1. + ENDIF. + READ TABLE lt_collapse_rows TRANSPORTING NO FIELDS WITH TABLE KEY table_line = lv_row_collapse_flag. + IF sy-subrc = 0. + ls_outline_row-collapsed = abap_true. + ENDIF. + io_worksheet->set_row_outline( iv_row_from = ls_outline_row-row_from + iv_row_to = ls_outline_row-row_to + iv_collapsed = ls_outline_row-collapsed ). + + ENDLOOP. + +* Finally purge outline information ( collapsed state, outline leve) from row_dimensions, since we want to keep these in the outline-table + LOOP AT lt_row_dimensions ASSIGNING <ls_row_dimension>. + + <ls_row_dimension>-row_dimension->set_outline_level( 0 ). + <ls_row_dimension>-row_dimension->set_collapsed( abap_false ). + + ENDLOOP. + +ENDMETHOD. + + + + + method fill_struct_from_attributes. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-07 +* - ... +* changes: renaming variables to naming conventions +* aligning code +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + + data: lv_name type string, + lo_attributes type ref to if_ixml_named_node_map, + lo_attribute type ref to if_ixml_attribute, + lo_iterator type ref to if_ixml_node_iterator. + + field-symbols: <component> type any. + +*--------------------------------------------------------------------* +* The values of named attributes of a tag are being read and moved into corresponding +* fields of given structure +* Behaves like move-corresonding tag to structure + +* Example: +* <Relationship Target="docProps/app.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Id="rId3"/> +* Here the attributes are Target, Type and Id. Thus if the passed +* structure has fieldnames Id and Target these would be filled with +* "rId3" and "docProps/app.xml" respectively +*--------------------------------------------------------------------* + clear cp_structure. + + lo_attributes = ip_element->get_attributes( ). + lo_iterator = lo_attributes->create_iterator( ). + lo_attribute ?= lo_iterator->get_next( ). + while lo_attribute is bound. + + lv_name = lo_attribute->get_name( ). + translate lv_name to upper case. + assign component lv_name of structure cp_structure to <component>. + if sy-subrc = 0. + <component> = lo_attribute->get_value( ). + endif. + lo_attribute ?= lo_iterator->get_next( ). + + endwhile. + + +endmethod. + + + + + + METHOD get_dxf_style_guid. + DATA: lo_ixml_dxf_children TYPE REF TO if_ixml_node_list, + lo_ixml_iterator_dxf_children TYPE REF TO if_ixml_node_iterator, + lo_ixml_dxf_child TYPE REF TO if_ixml_element, + + lv_dxf_child_type TYPE string, + + lo_ixml_element TYPE REF TO if_ixml_element, + lo_ixml_element2 TYPE REF TO if_ixml_element, + lv_val TYPE string. + + DATA: ls_cstyle TYPE zexcel_s_cstyle_complete, + ls_cstylex TYPE zexcel_s_cstylex_complete. + + + + lo_ixml_dxf_children = io_ixml_dxf->get_children( ). + lo_ixml_iterator_dxf_children = lo_ixml_dxf_children->create_iterator( ). + lo_ixml_dxf_child ?= lo_ixml_iterator_dxf_children->get_next( ). + WHILE lo_ixml_dxf_child IS BOUND. + + lv_dxf_child_type = lo_ixml_dxf_child->get_name( ). + CASE lv_dxf_child_type. + + WHEN 'font'. +*--------------------------------------------------------------------* +* italic +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'i' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'val' ). + IF lv_val <> '0'. + ls_cstyle-font-italic = 'X'. + ls_cstylex-font-italic = 'X'. + ENDIF. + + ENDIF. +*--------------------------------------------------------------------* +* bold +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'b' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'val' ). + IF lv_val <> '0'. + ls_cstyle-font-bold = 'X'. + ls_cstylex-font-bold = 'X'. + ENDIF. + + ENDIF. +*--------------------------------------------------------------------* +* strikethrough +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'strike' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'val' ). + IF lv_val <> '0'. + ls_cstyle-font-strikethrough = 'X'. + ls_cstylex-font-strikethrough = 'X'. + ENDIF. + + ENDIF. +*--------------------------------------------------------------------* +* color +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'color' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'rgb' ). + ls_cstyle-font-color-rgb = lv_val. + ls_cstylex-font-color-rgb = 'X'. + ENDIF. + + WHEN 'fill'. + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'patternFill' ). + IF lo_ixml_element IS BOUND. + lo_ixml_element2 = lo_ixml_element->find_from_name( 'bgColor' ). + IF lo_ixml_element2 IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element2->get_attribute_ns( 'rgb' ). + IF lv_val IS NOT INITIAL. + ls_cstyle-fill-filltype = zcl_excel_style_fill=>c_fill_solid. + ls_cstyle-fill-bgcolor-rgb = lv_val. + ls_cstylex-fill-filltype = 'X'. + ls_cstylex-fill-bgcolor-rgb = 'X'. + ENDIF. + ENDIF. + CLEAR lv_val. + lv_val = lo_ixml_element2->get_attribute_ns( 'theme' ). + IF lv_val IS NOT INITIAL. + ls_cstyle-fill-filltype = zcl_excel_style_fill=>c_fill_solid. + ls_cstyle-fill-bgcolor-theme = lv_val. + ls_cstylex-fill-filltype = 'X'. + ls_cstylex-fill-bgcolor-theme = 'X'. + ENDIF. + ENDIF. + +* 2do - borders into dxf-styles. Here and in writerclass +* WHEN 'border'. +* lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'left' ). +* IF lo_ixml_element IS BOUND. +* CLEAR lv_val. +* lv_val = lo_ixml_element2->get_attribute_ns( 'style' ). +* IF lv_val IS NOT INITIAL. +* ls_cstyle-borders-left-border_style = lv_val. +* ls_cstylex-borders-left-border_style = 'X'. +* ENDIF. +* ENDIF. + + ENDCASE. + + lo_ixml_dxf_child ?= lo_ixml_iterator_dxf_children->get_next( ). + + ENDWHILE. + + + + + rv_style_guid = io_excel->get_static_cellstyle_guid( ip_cstyle_complete = ls_cstyle + ip_cstylex_complete = ls_cstylex ). + + +ENDMETHOD. + + + + + + METHOD get_from_zip_archive. + + ASSERT zip IS BOUND. " zip object has to exist at this point + + r_content = zip->read( i_filename ). + +ENDMETHOD. + + + + + + + METHOD get_ixml_from_zip_archive. + + DATA: lv_content TYPE xstring, + lo_ixml TYPE REF TO if_ixml, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_istream TYPE REF TO if_ixml_istream, + lo_parser TYPE REF TO if_ixml_parser. + +*--------------------------------------------------------------------* +* Load XML file from archive into an input stream, +* and parse that stream into an ixml object +*--------------------------------------------------------------------* + lv_content = me->get_from_zip_archive( i_filename ). + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_istream = lo_streamfactory->create_istream_xstring( lv_content ). + r_ixml = lo_ixml->create_document( ). + lo_parser = lo_ixml->create_parser( stream_factory = lo_streamfactory + istream = lo_istream + document = r_ixml ). + lo_parser->set_normalizing( is_normalizing ). + lo_parser->set_validating( mode = if_ixml_parser=>co_no_validation ). + lo_parser->parse( ). + +ENDMETHOD. + + + + + + method LOAD_DRAWING_ANCHOR. + + TYPES: BEGIN OF t_c_nv_pr, + name TYPE string, + id TYPE string, + END OF t_c_nv_pr. + + TYPES: BEGIN OF t_blip, + cstate TYPE string, + embed TYPE string, + END OF t_blip. + + TYPES: BEGIN OF t_chart, + id TYPE string, + END OF t_chart. + + TYPES: BEGIN OF t_ext, + cx TYPE string, + cy TYPE string, + END OF t_ext. + + CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_true_int TYPE string VALUE '1'. + CONSTANTS: lc_rel_chart TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', + lc_rel_image TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'. + + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + node TYPE REF TO if_ixml_element, + node2 TYPE REF TO if_ixml_element, + node3 TYPE REF TO if_ixml_element, + node4 TYPE REF TO if_ixml_element, + + ls_upper TYPE zexcel_drawing_location, + ls_lower TYPE zexcel_drawing_location, + ls_size TYPE zexcel_drawing_size, + ext TYPE t_ext, + lv_content TYPE xstring, + lv_relation_id TYPE string, + lv_title TYPE zexcel_sheet_title, + + cnvpr TYPE t_c_nv_pr, + blip TYPE t_blip, + chart TYPE t_chart, + drawing_type TYPE zexcel_drawing_type, + + rel_drawing TYPE t_rel_drawing. + + node ?= io_anchor_element->find_from_name( name = 'from' namespace = 'xdr' ). + CHECK node IS NOT INITIAL. + node2 ?= node->find_from_name( name = 'col' namespace = 'xdr' ). + ls_upper-col = node2->get_value( ). + node2 ?= node->find_from_name( name = 'row' namespace = 'xdr' ). + ls_upper-row = node2->get_value( ). + node2 ?= node->find_from_name( name = 'colOff' namespace = 'xdr' ). + ls_upper-col_offset = node2->get_value( ). + node2 ?= node->find_from_name( name = 'rowOff' namespace = 'xdr' ). + ls_upper-row_offset = node2->get_value( ). + + node ?= io_anchor_element->find_from_name( name = 'ext' namespace = 'xdr' ). + IF node IS INITIAL. + CLEAR ls_size. + ELSE. + me->fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = ext ). + ls_size-width = ext-cx. + ls_size-height = ext-cy. + ENDIF. + + node ?= io_anchor_element->find_from_name( name = 'to' namespace = 'xdr' ). + IF node IS INITIAL. + CLEAR ls_lower. + ELSE. + node2 ?= node->find_from_name( name = 'col' namespace = 'xdr' ). + ls_lower-col = node2->get_value( ). + node2 ?= node->find_from_name( name = 'row' namespace = 'xdr' ). + ls_lower-row = node2->get_value( ). + node2 ?= node->find_from_name( name = 'colOff' namespace = 'xdr' ). + ls_lower-col_offset = node2->get_value( ). + node2 ?= node->find_from_name( name = 'rowOff' namespace = 'xdr' ). + ls_lower-row_offset = node2->get_value( ). + ENDIF. + + node ?= io_anchor_element->find_from_name( name = 'pic' namespace = 'xdr' ). + IF node IS NOT INITIAL. + node2 ?= node->find_from_name( name = 'nvPicPr' namespace = 'xdr' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'cNvPr' namespace = 'xdr' ). + CHECK node3 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = cnvpr ). + lv_title = cnvpr-name. + + node2 ?= node->find_from_name( name = 'blipFill' namespace = 'xdr' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'blip' namespace = 'a' ). + CHECK node3 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = blip ). + lv_relation_id = blip-embed. + + drawing_type = zcl_excel_drawing=>type_image. + ENDIF. + + node ?= io_anchor_element->find_from_name( name = 'graphicFrame' namespace = 'xdr' ). + IF node IS NOT INITIAL. + node2 ?= node->find_from_name( name = 'nvGraphicFramePr' namespace = 'xdr' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'cNvPr' namespace = 'xdr' ). + CHECK node3 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = cnvpr ). + lv_title = cnvpr-name. + + node2 ?= node->find_from_name( name = 'graphic' namespace = 'a' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'graphicData' namespace = 'a' ). + CHECK node3 IS NOT INITIAL. + node4 ?= node2->find_from_name( name = 'chart' namespace = 'c' ). + CHECK node4 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node4 CHANGING cp_structure = chart ). + lv_relation_id = chart-id. + + drawing_type = zcl_excel_drawing=>type_chart. + ENDIF. + + lo_drawing = io_worksheet->excel->add_new_drawing( + ip_type = drawing_type + ip_title = lv_title ). + io_worksheet->add_drawing( lo_drawing ). + + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + READ TABLE it_related_drawings INTO rel_drawing + WITH KEY id = lv_relation_id. + + lo_drawing->set_media( + EXPORTING + ip_media = rel_drawing-content + ip_media_type = rel_drawing-file_ext + ip_width = ls_size-width + ip_height = ls_size-height ). + + if drawing_type = zcl_excel_drawing=>type_chart. + "-------------Added by Alessandro Iannacci - Should load chart attributes + lo_drawing->load_chart_attributes( rel_drawing-content_xml ). + endif. + + endmethod. + + + + + + METHOD load_dxf_styles. + + DATA: lo_styles_xml TYPE REF TO if_ixml_document, + lo_node_dxfs TYPE REF TO if_ixml_element, + + lo_nodes_dxf TYPE REF TO if_ixml_node_collection, + lo_iterator_dxf TYPE REF TO if_ixml_node_iterator, + lo_node_dxf TYPE REF TO if_ixml_element, + + lv_dxf_count TYPE i. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF mt_dxf_styles. + +*--------------------------------------------------------------------* +* Look for dxfs-node +*--------------------------------------------------------------------* + lo_styles_xml = me->get_ixml_from_zip_archive( iv_path ). + lo_node_dxfs = lo_styles_xml->find_from_name( 'dxfs' ). + CHECK lo_node_dxfs IS BOUND. + + +*--------------------------------------------------------------------* +* loop through all dxf-nodes and create style for each +*--------------------------------------------------------------------* + lo_nodes_dxf ?= lo_node_dxfs->get_elements_by_tag_name( 'dxf' ). + lo_iterator_dxf = lo_nodes_dxf->create_iterator( ). + lo_node_dxf ?= lo_iterator_dxf->get_next( ). + WHILE lo_node_dxf IS BOUND. + + APPEND INITIAL LINE TO mt_dxf_styles ASSIGNING <ls_dxf_style>. + <ls_dxf_style>-dxf = lv_dxf_count. " We start counting at 0 + ADD 1 TO lv_dxf_count. " prepare next entry + + <ls_dxf_style>-guid = get_dxf_style_guid( io_ixml_dxf = lo_node_dxf + io_excel = io_excel ). + lo_node_dxf ?= lo_iterator_dxf->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + method LOAD_SHARED_STRINGS. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Support partial formatting of strings in cells +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-11 +* - ... +* changes: renaming variables to naming conventions +* renaming variables to indicate what they are used for +* aligning code +* adding comments to explain what we are trying to achieve +* rewriting code for better readibility +*--------------------------------------------------------------------* + + + + DATA: + lo_shared_strings_xml TYPE REF TO if_ixml_document, + lo_node_si TYPE REF TO if_ixml_element, + lo_node_si_child TYPE REF TO if_ixml_element, + lo_node_r_child_t TYPE REF TO if_ixml_element, + lv_tag_name TYPE string, + lv_node_value TYPE string. + + FIELD-SYMBOLS: <lv_shared_string> LIKE LINE OF me->shared_strings. + +*--------------------------------------------------------------------* + +* §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 + +* Following is an example how this file could be set up; 2 strings in simple formatting, 3rd string rich textformatted + + +* <?xml version="1.0" encoding="UTF-8" standalone="true"?> +* <sst uniqueCount="6" count="6" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> +* <si> +* <t>This is a teststring 1</t> +* </si> +* <si> +* <t>This is a teststring 2</t> +* </si> +* <si> +* <r> +* <t>T</t> +* </r> +* <r> +* <rPr> +* <sz val="11"/> +* <color rgb="FFFF0000"/> +* <rFont val="Calibri"/> +* <family val="2"/> +* <scheme val="minor"/> +* </rPr> +* <t xml:space="preserve">his is a </t> +* </r> +* <r> +* <rPr> +* <sz val="11"/> +* <color theme="1"/> +* <rFont val="Calibri"/> +* <family val="2"/> +* <scheme val="minor"/> +* </rPr> +* <t>teststring 3</t> +* </r> +* </si> +* </sst> +*--------------------------------------------------------------------* + + lo_shared_strings_xml = me->get_ixml_from_zip_archive( i_filename = ip_path + is_normalizing = space ). " NO!!! normalizing - otherwise leading blanks will be omitted and that is not really desired for the stringtable + lo_node_si ?= lo_shared_strings_xml->find_from_name( 'si' ). + WHILE lo_node_si IS BOUND. + + APPEND INITIAL LINE TO me->shared_strings ASSIGNING <lv_shared_string>. " Each <si>-entry in the xml-file must lead to an entry in our stringtable + lo_node_si_child ?= lo_node_si->get_first_child( ). + IF lo_node_si_child IS BOUND. + lv_tag_name = lo_node_si_child->get_name( ). + IF lv_tag_name = 't'. +*--------------------------------------------------------------------* +* §1.1 - "simple" strings +* Example: see above +*--------------------------------------------------------------------* + <lv_shared_string> = lo_node_si_child->get_value( ). + ELSE. +*--------------------------------------------------------------------* +* §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 +* Example: see above +*--------------------------------------------------------------------* + WHILE lo_node_si_child IS BOUND. " actually these children of <si> are <r>-tags + + lo_node_r_child_t ?= lo_node_si_child->find_from_name( 't' ). " extract the <t>...</t> part of each <r>-tag + IF lo_node_r_child_t IS BOUND. + lv_node_value = lo_node_r_child_t->get_value( ). + CONCATENATE <lv_shared_string> lv_node_value INTO <lv_shared_string> RESPECTING BLANKS. + ENDIF. + + lo_node_si_child ?= lo_node_si_child->get_next( ). + + ENDWHILE. + ENDIF. + ENDIF. + + lo_node_si ?= lo_node_si->get_next( ). + ENDWHILE. + + endmethod. + + + + + + METHOD load_styles. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (wip ) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + TYPES: BEGIN OF lty_xf, + applyalignment TYPE string, + applyborder TYPE string, + applyfill TYPE string, + applyfont TYPE string, + applynumberformat TYPE string, + applyprotection TYPE string, + borderid TYPE string, + fillid TYPE string, + fontid TYPE string, + numfmtid TYPE string, + pivotbutton TYPE string, + quoteprefix TYPE string, + xfid TYPE string, + END OF lty_xf. + + TYPES: BEGIN OF lty_alignment, + horizontal TYPE string, + indent TYPE string, + justifylastline TYPE string, + readingorder TYPE string, + relativeindent TYPE string, + shrinktofit TYPE string, + textrotation TYPE string, + vertical TYPE string, + wraptext TYPE string, + END OF lty_alignment. + + TYPES: BEGIN OF lty_protection, + hidden TYPE string, + locked TYPE string, + END OF lty_protection. + + DATA: lo_styles_xml TYPE REF TO if_ixml_document, + lo_style TYPE REF TO zcl_excel_style, + + lt_num_formats TYPE t_num_formats, + lt_fills TYPE t_fills, + lt_borders TYPE t_borders, + lt_fonts TYPE t_fonts, + + ls_num_format TYPE t_num_format, + ls_fill TYPE REF TO zcl_excel_style_fill, + ls_cell_border TYPE REF TO zcl_excel_style_borders, + ls_font TYPE REF TO zcl_excel_style_font, + + lo_node_cellxfs TYPE REF TO if_ixml_element, + lo_node_cellxfs_xf TYPE REF TO if_ixml_element, + lo_node_cellxfs_xf_alignment TYPE REF TO if_ixml_element, + lo_node_cellxfs_xf_protection TYPE REF TO if_ixml_element, + + lo_nodes_xf TYPE REF TO if_ixml_node_collection, + lo_iterator_cellxfs TYPE REF TO if_ixml_node_iterator, + + ls_xf TYPE lty_xf, + ls_alignment TYPE lty_alignment, + ls_protection TYPE lty_protection, + lv_index TYPE i. + +*--------------------------------------------------------------------* +* 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 + +* Following is an example how this part of a file could be set up +* ... +* parts with various formatinformation - see §1,§2,§3,§4 +* ... +* <cellXfs count="26"> +* <xf numFmtId="0" borderId="0" fillId="0" fontId="0" xfId="0"/> +* <xf numFmtId="0" borderId="0" fillId="2" fontId="0" xfId="0" applyFill="1"/> +* <xf numFmtId="0" borderId="1" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="2" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="3" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="4" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="0" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* ... +* </cellXfs> +*--------------------------------------------------------------------* + + lo_styles_xml = me->get_ixml_from_zip_archive( ip_path ). + +*--------------------------------------------------------------------* +* The styles are build up from +* §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 + +*--------------------------------------------------------------------* +* Now everything is prepared to build a "full" style +*--------------------------------------------------------------------* + lo_node_cellxfs = lo_styles_xml->find_from_name( name = 'cellXfs' ). + IF lo_node_cellxfs IS BOUND. + lo_nodes_xf = lo_node_cellxfs->get_elements_by_tag_name( name = 'xf' ). + lo_iterator_cellxfs = lo_nodes_xf->create_iterator( ). + lo_node_cellxfs_xf ?= lo_iterator_cellxfs->get_next( ). + WHILE lo_node_cellxfs_xf IS BOUND. + + lo_style = ip_excel->add_new_style( ). + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_cellxfs_xf + CHANGING + cp_structure = ls_xf ). +*--------------------------------------------------------------------* +* §2 fill style +*--------------------------------------------------------------------* + IF ls_xf-applyfill = '1' AND ls_xf-fillid IS NOT INITIAL. + lv_index = ls_xf-fillid + 1. + READ TABLE lt_fills INTO ls_fill INDEX lv_index. + IF sy-subrc = 0. + lo_style->fill = ls_fill. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §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. + IF sy-subrc = 0. + lo_style->number_format = ls_num_format-format. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §3 border style +*--------------------------------------------------------------------* + IF ls_xf-applyborder = '1' AND ls_xf-borderid IS NOT INITIAL. + lv_index = ls_xf-borderid + 1. + READ TABLE lt_borders INTO ls_cell_border INDEX lv_index. + IF sy-subrc = 0. + lo_style->borders = ls_cell_border. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §4 font +*--------------------------------------------------------------------* + IF ls_xf-applyfont = '1' AND ls_xf-fontid IS NOT INITIAL. + lv_index = ls_xf-fontid + 1. + READ TABLE lt_fonts INTO ls_font INDEX lv_index. + IF sy-subrc = 0. + lo_style->font = ls_font. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §5 - Alignment +*--------------------------------------------------------------------* + lo_node_cellxfs_xf_alignment ?= lo_node_cellxfs_xf->find_from_name( 'alignment' ). + IF lo_node_cellxfs_xf_alignment IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_cellxfs_xf_alignment + CHANGING + cp_structure = ls_alignment ). + IF ls_alignment-horizontal IS NOT INITIAL. + lo_style->alignment->horizontal = ls_alignment-horizontal. + ENDIF. + + IF ls_alignment-vertical IS NOT INITIAL. + lo_style->alignment->vertical = ls_alignment-vertical. + ENDIF. + + IF ls_alignment-textrotation IS NOT INITIAL. + lo_style->alignment->textrotation = ls_alignment-textrotation. + ENDIF. + + IF ls_alignment-wraptext = '1' OR ls_alignment-wraptext = 'true'. + lo_style->alignment->wraptext = abap_true. + ENDIF. + + IF ls_alignment-shrinktofit = '1' OR ls_alignment-shrinktofit = 'true'. + lo_style->alignment->shrinktofit = abap_true. + ENDIF. + + IF ls_alignment-indent IS NOT INITIAL. + lo_style->alignment->indent = ls_alignment-indent. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §6 - Protection +*--------------------------------------------------------------------* + lo_node_cellxfs_xf_protection ?= lo_node_cellxfs_xf->find_from_name( 'protection' ). + IF lo_node_cellxfs_xf_protection IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_cellxfs_xf_protection + CHANGING + cp_structure = ls_protection ). + IF ls_protection-locked = '1' OR ls_protection-locked = 'true'. + lo_style->protection->locked = zcl_excel_style_protection=>c_protection_locked. + ELSE. + lo_style->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. + ENDIF. + + IF ls_protection-hidden = '1' OR ls_protection-hidden = 'true'. + lo_style->protection->hidden = zcl_excel_style_protection=>c_protection_hidden. + ELSE. + lo_style->protection->hidden = zcl_excel_style_protection=>c_protection_unhidden. + ENDIF. + + ENDIF. + + INSERT lo_style INTO TABLE me->styles. + + lo_node_cellxfs_xf ?= lo_iterator_cellxfs->get_next( ). + + ENDWHILE. + ENDIF. + +ENDMETHOD. + + + + + method LOAD_STYLE_BORDERS. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* renaming variables to indicate what they are used for +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + DATA: lo_node_border TYPE REF TO if_ixml_element, + lo_node_bordertype TYPE REF TO if_ixml_element, + lo_node_bordercolor TYPE REF TO if_ixml_element, + lo_cell_border TYPE REF TO zcl_excel_style_borders, + lo_border TYPE REF TO zcl_excel_style_border, + ls_color TYPE t_color. + +*--------------------------------------------------------------------* +* We need a table of used borderformats to build up our styles +* §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 + +* Following is an example how this part of a file could be set up +* <border diagonalDown="1"> +* <left style="mediumDashDotDot"> +* <color rgb="FFFF0000"/> +* </left> +* <right/> +* <top style="thick"> +* <color rgb="FFFF0000"/> +* </top> +* <bottom style="thick"> +* <color rgb="FFFF0000"/> +* </bottom> +* <diagonal style="thick"> +* <color rgb="FFFF0000"/> +* </diagonal> +* </border> +*--------------------------------------------------------------------* + lo_node_border ?= ip_xml->find_from_name( 'border' ). + WHILE lo_node_border IS BOUND. + + CREATE OBJECT lo_cell_border. + +*--------------------------------------------------------------------* +* Diagonal borderlines are formatted the equally. Determine what kind of diagonal borders are present if any +*--------------------------------------------------------------------* +* DiagonalNone = 0 +* DiagonalUp = 1 +* DiagonalDown = 2 +* DiagonalBoth = 3 +*--------------------------------------------------------------------* + IF lo_node_border->get_attribute( 'diagonalDown' ) IS NOT INITIAL. + add zcl_excel_style_borders=>c_diagonal_down to lo_cell_border->diagonal_mode. + ENDIF. + + IF lo_node_border->get_attribute( 'diagonalUp' ) IS NOT INITIAL. + add zcl_excel_style_borders=>c_diagonal_up to lo_cell_border->diagonal_mode. + ENDIF. + + 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 +*--------------------------------------------------------------------* +* Up, down, left, right, diagonal +*--------------------------------------------------------------------* + CREATE OBJECT lo_border. + + CASE lo_node_bordertype->get_name( ). + + WHEN 'left'. + lo_cell_border->left = lo_border. + + WHEN 'right'. + lo_cell_border->right = lo_border. + + WHEN 'top'. + lo_cell_border->top = lo_border. + + WHEN 'bottom'. + lo_cell_border->down = lo_border. + + WHEN 'diagonal'. + lo_cell_border->diagonal = lo_border. + + ENDCASE. + +*--------------------------------------------------------------------* +* §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' ). + IF lo_node_bordercolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_bordercolor + CHANGING + cp_structure = ls_color ). + + lo_border->border_color-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_border->border_color-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_border->border_color-theme = ls_color-theme. + ENDIF. + lo_border->border_color-tint = ls_color-tint. + ENDIF. + + lo_node_bordertype ?= lo_node_bordertype->get_next( ). + + ENDWHILE. + + INSERT lo_cell_border INTO TABLE ep_borders. + + lo_node_border ?= lo_node_border->get_next( ). + + ENDWHILE. + + + endmethod. + + + + + method LOAD_STYLE_FILLS. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Support gradientFill +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* commenting on problems/future enhancements/todos we already know of or should decide upon +* adding comments to explain what we are trying to achieve +* renaming variables to indicate what they are used for +*--------------------------------------------------------------------* + DATA: lv_value TYPE string, + lo_node_fill TYPE REF TO if_ixml_element, + lo_node_fill_child TYPE REF TO if_ixml_element, + lo_node_bgcolor TYPE REF TO if_ixml_element, + lo_node_fgcolor TYPE REF TO if_ixml_element, + lo_node_stop TYPE REF TO if_ixml_element, + lo_fill TYPE REF TO zcl_excel_style_fill, + ls_color TYPE t_color. + +*--------------------------------------------------------------------* +* We need a table of used fillformats to build up our styles + +* Following is an example how this part of a file could be set up +* <fill> +* <patternFill patternType="gray125"/> +* </fill> +* <fill> +* <patternFill patternType="solid"> +* <fgColor rgb="FFFFFF00"/> +* <bgColor indexed="64"/> +* </patternFill> +* </fill> +*--------------------------------------------------------------------* + + lo_node_fill ?= ip_xml->find_from_name( 'fill' ). + WHILE lo_node_fill IS BOUND. + + CREATE OBJECT lo_fill. + lo_node_fill_child ?= lo_node_fill->get_first_child( ). + lv_value = lo_node_fill_child->get_name( ). + CASE lv_value. + +*--------------------------------------------------------------------* +* Patternfill +*--------------------------------------------------------------------* + WHEN 'patternFill'. + lo_fill->filltype = lo_node_fill_child->get_attribute( 'patternType' ). +*--------------------------------------------------------------------* +* Patternfill - background color +*--------------------------------------------------------------------* + lo_node_bgcolor = lo_node_fill_child->find_from_name( 'bgColor' ). + IF lo_node_bgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_bgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->bgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->bgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->bgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->bgcolor-tint = ls_color-tint. + ENDIF. + +*--------------------------------------------------------------------* +* Patternfill - foreground color +*--------------------------------------------------------------------* + lo_node_fgcolor = lo_node_fill->find_from_name( 'fgColor' ). + IF lo_node_fgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_fgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->fgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->fgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->fgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->fgcolor-tint = ls_color-tint. + ENDIF. + + +*--------------------------------------------------------------------* +* gradientFill +*--------------------------------------------------------------------* + WHEN 'gradientFill'. + lo_fill->gradtype-type = lo_node_fill_child->get_attribute( 'type' ). + lo_fill->gradtype-top = lo_node_fill_child->get_attribute( 'top' ). + lo_fill->gradtype-left = lo_node_fill_child->get_attribute( 'left' ). + lo_fill->gradtype-right = lo_node_fill_child->get_attribute( 'right' ). + lo_fill->gradtype-bottom = lo_node_fill_child->get_attribute( 'bottom' ). + lo_fill->gradtype-degree = lo_node_fill_child->get_attribute( 'degree' ). + free lo_node_stop. + lo_node_stop ?= lo_node_fill_child->find_from_name( 'stop' ). + while lo_node_stop is bound. + if lo_fill->gradtype-position1 is initial. + lo_fill->gradtype-position1 = lo_node_stop->get_attribute( 'position' ). + lo_node_bgcolor = lo_node_stop->find_from_name( 'color' ). + IF lo_node_bgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_bgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->bgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->bgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->bgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->bgcolor-tint = ls_color-tint. + ENDIF. + elseif lo_fill->gradtype-position2 is initial. + lo_fill->gradtype-position2 = lo_node_stop->get_attribute( 'position' ). + lo_node_fgcolor = lo_node_stop->find_from_name( 'color' ). + IF lo_node_fgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_fgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->fgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->fgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->fgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->fgcolor-tint = ls_color-tint. + ENDIF. + elseif lo_fill->gradtype-position3 is initial. + lo_fill->gradtype-position3 = lo_node_stop->get_attribute( 'position' ). + "BGColor is filled already with position 1 no need to check again + endif. + + lo_node_stop ?= lo_node_stop->get_next( ). + ENDWHILE. + + WHEN OTHERS. + + ENDCASE. + + + INSERT lo_fill INTO TABLE ep_fills. + + lo_node_fill ?= lo_node_fill->get_next( ). + + ENDWHILE. + + + endmethod. + + + + + METHOD load_style_fonts. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* removing unused variables +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + DATA: lo_node_font TYPE REF TO if_ixml_element, + lo_node2 TYPE REF TO if_ixml_element, + lo_font TYPE REF TO zcl_excel_style_font, + ls_color TYPE t_color. + +*--------------------------------------------------------------------* +* We need a table of used fonts to build up our styles + +* Following is an example how this part of a file could be set up +* <font> +* <sz val="11"/> +* <color theme="1"/> +* <name val="Calibri"/> +* <family val="2"/> +* <scheme val="minor"/> +* </font> +*--------------------------------------------------------------------* + lo_node_font ?= ip_xml->find_from_name( 'font' ). + WHILE lo_node_font IS BOUND. + + CREATE OBJECT lo_font. +*--------------------------------------------------------------------* +* Bold +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'b' ) IS BOUND. + lo_font->bold = abap_true. + ENDIF. + +*--------------------------------------------------------------------* +* Italic +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'i' ) IS BOUND. + lo_font->italic = abap_true. + ENDIF. + +*--------------------------------------------------------------------* +* Underline +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'u' ). + IF lo_node2 IS BOUND. + lo_font->underline = abap_true. + lo_font->underline_mode = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* StrikeThrough +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'strike' ) IS BOUND. + lo_font->strikethrough = abap_true. + ENDIF. + +*--------------------------------------------------------------------* +* Fontsize +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'sz' ). + IF lo_node2 IS BOUND. + lo_font->size = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* Fontname +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'name' ). + IF lo_node2 IS BOUND. + lo_font->name = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* Fontfamily +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'family' ). + IF lo_node2 IS BOUND. + lo_font->family = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* Fontscheme +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'scheme' ). + IF lo_node2 IS BOUND. + lo_font->scheme = lo_node2->get_attribute( 'val' ). + ELSE. + CLEAR lo_font->scheme. + ENDIF. + +*--------------------------------------------------------------------* +* Fontcolor +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'color' ). + IF lo_node2 IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node2 + CHANGING + cp_structure = ls_color ). + lo_font->color-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_font->color-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_font->color-theme = ls_color-theme. + ENDIF. + lo_font->color-tint = ls_color-tint. + ENDIF. + + INSERT lo_font INTO TABLE ep_fonts. + + lo_node_font ?= lo_node_font->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + method LOAD_STYLE_NUM_FORMATS. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Explain gaps in predefined formats +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - 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 +* aligning code +*--------------------------------------------------------------------* + DATA: lo_node_numfmt TYPE REF TO if_ixml_element, + ls_num_format TYPE t_num_format. + +*--------------------------------------------------------------------* +* 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 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"> +* <numFmt formatCode="#,###,###,###,##0.00" numFmtId="164"/> +* </numFmts> +*--------------------------------------------------------------------* + lo_node_numfmt ?= ip_xml->find_from_name( 'numFmt' ). + WHILE lo_node_numfmt IS BOUND. + + CLEAR ls_num_format. + + CREATE OBJECT ls_num_format-format. + ls_num_format-format->format_code = lo_node_numfmt->get_attribute( 'formatCode' ). + ls_num_format-id = lo_node_numfmt->get_attribute( 'numFmtId' ). + INSERT ls_num_format INTO TABLE ep_num_formats. + + lo_node_numfmt ?= lo_node_numfmt->get_next( ). + + ENDWHILE. + + DEFINE predefined_format. + ls_num_format-id = &1. + create object ls_num_format-format. + ls_num_format-format->format_code = &2. + insert ls_num_format into table ep_num_formats. + END-OF-DEFINITION. + +*--------------------------------------------------------------------* +* §1 Get internal predefined numberformats +*--------------------------------------------------------------------* + predefined_format '1' '0'. + predefined_format '2' '0.00'. + predefined_format '3' '#,##0'. + predefined_format '4' '#,##0.00'. + predefined_format '5' '$#,##0_);($#,##0)'. + predefined_format '6' '$#,##0_);[Red]($#,##0)'. + predefined_format '7' '$#,##0.00_);($#,##0.00)'. + predefined_format '8' '$#,##0.00_);[Red]($#,##0.00)'. + predefined_format '9' '0%'. + predefined_format '10' '0.00%'. + predefined_format '11' '0.00E+00'. + predefined_format '12' '# ?/?'. + predefined_format '13' '# ??/??'. + predefined_format '14' 'm/d/yyyy'. + predefined_format '15' 'd-mmm-yy'. + predefined_format '16' 'd-mmm'. + predefined_format '17' 'mmm-yy'. + predefined_format '18' 'h:mm AM/PM'. + predefined_format '19' 'h:mm:ss AM/PM'. + 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? + + + + + + + + + + + + + + predefined_format '37' '#,##0_);(#,##0)'. + 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? + + + + predefined_format '45' 'mm:ss'. + predefined_format '46' '[h]:mm:ss'. + predefined_format '47' 'mm:ss.0'. + predefined_format '48' '##0.0E+0'. + predefined_format '49' '@'. +* 2do§1 Is 49 really the last predefined format? + + + endmethod. + + + + + + method LOAD_WORKBOOK. +*--------------------------------------------------------------------* +* ToDos: +* 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 +* - ... +* changes: renaming variables to naming conventions +* aligning code +* removing unused variables +* adding me-> where possible +* renaming variables to indicate what they are used for +* adding comments to explain what we are trying to achieve +* renaming i/o parameters: previous input-parameter ip_path holds a (full) filename and not a path --> rename to iv_workbook_full_filename +* ip_excel renamed while being at it --> rename to io_excel +*--------------------------------------------------------------------* +* issue #232 - Read worksheetstate hidden/veryHidden +* - Stefan Schmöcker, 2012-11-11 +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - 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 +* changes: initialize area to hold referenced formulaedata +* after all worksheets have been read resolve formuae +*--------------------------------------------------------------------* + + CONSTANTS: lcv_shared_strings TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', + lcv_worksheet TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', + lcv_styles TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + lcv_vba_project TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', "#EC NEEDED for future incorporation of XLSM-reader +*--------------------------------------------------------------------* +* #232: Read worksheetstate hidden/veryHidden - begin data declarations +*--------------------------------------------------------------------* + lcv_worksheet_state_hidden TYPE string VALUE 'hidden', + lcv_worksheet_state_veryhidden TYPE string VALUE 'veryHidden'. +*--------------------------------------------------------------------* +* #232: Read worksheetstate hidden/veryHidden - end data declarations +*--------------------------------------------------------------------* + + DATA: + lv_path TYPE string, + lv_filename TYPE chkfile, + lv_full_filename TYPE string, + + lo_rels_workbook TYPE REF TO if_ixml_document, + lt_worksheets TYPE STANDARD TABLE OF t_relationship WITH NON-UNIQUE DEFAULT KEY, + lo_workbook TYPE REF TO if_ixml_document, + lv_workbook_index TYPE i, + lv_worksheet_path TYPE string, + ls_sheet TYPE t_sheet, + + lo_node TYPE REF TO if_ixml_element, + ls_relationship TYPE t_relationship, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lv_worksheet_title TYPE zexcel_sheet_title, + lv_tabix TYPE sytabix, " #235 - repeat rows/cols. Needed to link defined name to correct worksheet + + ls_range TYPE t_range, + lv_range_value TYPE zexcel_range_value, +*--------------------------------------------------------------------* +* #229: Set active worksheet - begin data declarations +*--------------------------------------------------------------------* + lv_active_sheet_string TYPE string, + lv_zexcel_active_worksheet TYPE zexcel_active_worksheet, +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns - added autofilter support while changing this section + lo_autofilter TYPE REF TO zcl_excel_autofilter, + ls_area TYPE zexcel_s_autofilter_area, + lv_col_start_alpha TYPE zexcel_cell_column_alpha, + lv_col_end_alpha TYPE zexcel_cell_column_alpha, + lv_row_start TYPE zexcel_cell_row, + lv_row_end TYPE zexcel_cell_row , + lv_regex TYPE string, + lv_range_value_1 TYPE zexcel_range_value, + lv_range_value_2 TYPE zexcel_range_value. +*--------------------------------------------------------------------* +* #229: Set active worksheet - end data declarations +*--------------------------------------------------------------------* + FIELD-SYMBOLS: <worksheet> TYPE t_relationship. + + +*--------------------------------------------------------------------* + +* §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 +* <workbookroot>/_rels/<workbookfilename>.rels and their positions +* be be given relative to the workbookroot + +* 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"> +* <Relationship Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Id="rId6"/> +* <Relationship Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Id="rId5"/> +* <Relationship Target="worksheets/sheet1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId1"/> +* <Relationship Target="worksheets/sheet2.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId2"/> +* <Relationship Target="worksheets/sheet3.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId3"/> +* <Relationship Target="worksheets/sheet4.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId4"/> +* <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 +* 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 +* ... +* +* §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 + +* <?xml version="1.0" encoding="UTF-8" standalone="true"?> +* <workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> +* <fileVersion rupBuild="4506" lowestEdited="4" lastEdited="4" appName="xl"/> +* <workbookPr defaultThemeVersion="124226"/> +* <bookViews> +* <workbookView activeTab="1" windowHeight="8445" windowWidth="19035" yWindow="120" xWindow="120"/> +* </bookViews> +* <sheets> +* <sheet r:id="rId1" sheetId="1" name="Sheet1"/> +* <sheet r:id="rId2" sheetId="2" name="Sheet2"/> +* <sheet r:id="rId3" sheetId="3" name="Sheet3" state="hidden"/> +* <sheet r:id="rId4" sheetId="4" name="Sheet4"/> +* </sheets> +* <definedNames/> +* <calcPr calcId="125725"/> +* </workbook> +*--------------------------------------------------------------------* + + CLEAR me->mt_ref_formulae. " ins issue#284 + +*--------------------------------------------------------------------* +* §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' + EXPORTING + full_name = iv_workbook_full_filename + IMPORTING + stripped_name = lv_filename + file_path = lv_path. + + CONCATENATE lv_path '_rels/' lv_filename '.rels' + INTO lv_full_filename. + lo_rels_workbook = me->get_ixml_from_zip_archive( lv_full_filename ). + + lo_node ?= lo_rels_workbook->find_from_name( 'Relationship' ). "#EC NOTEXT + WHILE lo_node IS BOUND. + + me->fill_struct_from_attributes( EXPORTING ip_element = lo_node CHANGING cp_structure = ls_relationship ). + + CASE ls_relationship-type. + +*--------------------------------------------------------------------* +* §2.1 Shared strings - This holds all strings that are used in all worksheets +*--------------------------------------------------------------------* + WHEN lcv_shared_strings. + CONCATENATE lv_path ls_relationship-target + INTO lv_full_filename. + me->load_shared_strings( lv_full_filename ). + +*--------------------------------------------------------------------* +* §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 +*--------------------------------------------------------------------* + WHEN lcv_worksheet. + APPEND ls_relationship TO lt_worksheets. + +*--------------------------------------------------------------------* +* §2.2 Styles - This holds the styles that are used in all worksheets +*--------------------------------------------------------------------* + WHEN lcv_styles. + CONCATENATE lv_path ls_relationship-target + INTO lv_full_filename. + me->load_styles( ip_path = lv_full_filename + ip_excel = io_excel ). + me->load_dxf_styles( iv_path = lv_full_filename + io_excel = io_excel ). + + WHEN OTHERS. + + ENDCASE. + + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + +*--------------------------------------------------------------------* +* §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 +*--------------------------------------------------------------------* + lo_node ?= lo_workbook->find_from_name( 'sheet' ). + lv_workbook_index = 1. + WHILE lo_node IS BOUND. + + me->fill_struct_from_attributes( EXPORTING + ip_element = lo_node + CHANGING + cp_structure = ls_sheet ). +*--------------------------------------------------------------------* +* Create new worksheet in workbook with correct name +*--------------------------------------------------------------------* + lv_worksheet_title = ls_sheet-name. + IF lv_workbook_index = 1. " First sheet has been added automatically by creating io_excel + lo_worksheet = io_excel->get_active_worksheet( ). + lo_worksheet->set_title( lv_worksheet_title ). + ELSE. + lo_worksheet = io_excel->add_new_worksheet( lv_worksheet_title ). + ENDIF. +*--------------------------------------------------------------------* +* #232 - Read worksheetstate hidden/veryHidden - begin of coding +* Set status hidden if necessary +*--------------------------------------------------------------------* + CASE ls_sheet-state. + + WHEN lcv_worksheet_state_hidden. + lo_worksheet->zif_excel_sheet_properties~hidden = zif_excel_sheet_properties=>c_hidden. + + WHEN lcv_worksheet_state_veryhidden. + lo_worksheet->zif_excel_sheet_properties~hidden = zif_excel_sheet_properties=>c_veryhidden. + + ENDCASE. +*--------------------------------------------------------------------* +* #232 - Read worksheetstate hidden/veryHidden - end of coding +*--------------------------------------------------------------------* +*--------------------------------------------------------------------* +* Load worksheetdata +*--------------------------------------------------------------------* + READ TABLE lt_worksheets ASSIGNING <worksheet> WITH KEY id = ls_sheet-id. + IF sy-subrc = 0. + <worksheet>-sheetid = ls_sheet-sheetid. "ins #235 - repeat rows/cols - needed to identify correct sheet + CONCATENATE lv_path <worksheet>-target + INTO lv_worksheet_path. + me->load_worksheet( ip_path = lv_worksheet_path + io_worksheet = lo_worksheet ). + <worksheet>-worksheet = lo_worksheet. + ENDIF. + + lo_node ?= lo_node->get_next( ). + ADD 1 TO lv_workbook_index. + + ENDWHILE. + SORT lt_worksheets BY sheetid. " needed for localSheetid -referencing + +*--------------------------------------------------------------------* +* #284: Set active worksheet - Resolve referenced formulae to +* explicit formulae those cells +*--------------------------------------------------------------------* + me->resolve_referenced_formulae( ). + " ins issue#284 +*--------------------------------------------------------------------* +* #229: Set active worksheet - begin coding +* §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' ). + IF lo_node IS BOUND. + lv_active_sheet_string = lo_node->get_attribute( 'activeTab' ). + TRY. + lv_zexcel_active_worksheet = lv_active_sheet_string + 1. " EXCEL numbers the sheets from 0 onwards --> index into worksheettable is increased by one + CATCH cx_sy_conversion_error. "#EC NO_HANDLER - error here --> just use the default 1st sheet + ENDTRY. + ENDIF. + io_excel->set_active_sheet_index( lv_zexcel_active_worksheet ). +*--------------------------------------------------------------------* +* #229: Set active worksheet - end coding +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* §3.3 Defined names +* So far I have encountered these +* - named ranges - sheetlocal +* - named ranges - workbookglobal +* - autofilters - sheetlocal ( special range ) +* - repeat rows/cols - sheetlocal ( special range ) +* +*--------------------------------------------------------------------* + lo_node ?= lo_workbook->find_from_name( 'definedName' ). + WHILE lo_node IS BOUND. + + CLEAR lo_range. "ins issue #235 - repeat rows/cols + me->fill_struct_from_attributes( EXPORTING + ip_element = lo_node + CHANGING + cp_structure = ls_range ). + lv_range_value = lo_node->get_value( ). + + IF ls_range-localsheetid IS NOT INITIAL. " issue #163+ +* READ TABLE lt_worksheets ASSIGNING <worksheet> WITH KEY id = ls_range-localsheetid. "del issue #235 - repeat rows/cols " issue #163+ +* lo_range = <worksheet>-worksheet->add_new_range( ). "del issue #235 - repeat rows/cols " issue #163+ +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns - begin +*--------------------------------------------------------------------* + lv_tabix = ls_range-localsheetid + 1. + READ TABLE lt_worksheets ASSIGNING <worksheet> INDEX lv_tabix. + IF sy-subrc = 0. + CASE ls_range-name. + +*--------------------------------------------------------------------* +* insert autofilters +*--------------------------------------------------------------------* + WHEN zcl_excel_autofilters=>c_autofilter. + lo_autofilter = io_excel->add_new_autofilter( io_sheet = <worksheet>-worksheet ) . + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range_value + IMPORTING e_column_start = lv_col_start_alpha + e_column_end = lv_col_end_alpha + e_row_start = ls_area-row_start ). + ls_area-col_start = zcl_excel_common=>convert_column2int( lv_col_start_alpha ). + ls_area-col_end = zcl_excel_common=>convert_column2int( lv_col_end_alpha ). + lo_autofilter->set_filter_area( is_area = ls_area ). + +*--------------------------------------------------------------------* +* repeat print rows/columns +*--------------------------------------------------------------------* + WHEN zif_excel_sheet_printsettings=>gcv_print_title_name. + lo_range = <worksheet>-worksheet->add_new_range( ). +*--------------------------------------------------------------------* +* This might be a temporary solution. Maybe ranges get be reworked +* to support areas consisting of multiple rectangles +* But for now just split the range into row and columnpart +*--------------------------------------------------------------------* + CLEAR:lv_range_value_1, + lv_range_value_2. + IF lv_range_value IS INITIAL. +* Empty --> nothing to do + ELSE. + IF lv_range_value(1) = `'`. " Escaped + lv_regex = `^('[^']*')+![^,]*,`. + ELSE. + lv_regex = `^[^!]*![^,]*,`. + ENDIF. +* Split into two ranges if necessary + FIND REGEX lv_regex IN lv_range_value MATCH LENGTH sy-fdpos. + IF sy-subrc = 0 AND sy-fdpos > 0. + lv_range_value_2 = lv_range_value+sy-fdpos. + SUBTRACT 1 FROM sy-fdpos. + lv_range_value_1 = lv_range_value(sy-fdpos). + ELSE. + lv_range_value_1 = lv_range_value. + ENDIF. + ENDIF. +* 1st range + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range_value_1 + IMPORTING e_column_start = lv_col_start_alpha + e_column_end = lv_col_end_alpha + e_row_start = lv_row_start + e_row_end = lv_row_end ). + IF lv_col_start_alpha IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_columns( iv_columns_from = lv_col_start_alpha + iv_columns_to = lv_col_end_alpha ). + ENDIF. + IF lv_row_start IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_rows( iv_rows_from = lv_row_start + iv_rows_to = lv_row_end ). + ENDIF. + +* 2nd range + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range_value_2 + IMPORTING e_column_start = lv_col_start_alpha + e_column_end = lv_col_end_alpha + e_row_start = lv_row_start + e_row_end = lv_row_end ). + IF lv_col_start_alpha IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_columns( iv_columns_from = lv_col_start_alpha + iv_columns_to = lv_col_end_alpha ). + ENDIF. + IF lv_row_start IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_rows( iv_rows_from = lv_row_start + iv_rows_to = lv_row_end ). + ENDIF. + + WHEN OTHERS. + + ENDCASE. + ENDIF. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns - end +*--------------------------------------------------------------------* + ELSE. " issue #163+ + lo_range = io_excel->add_new_range( ). " issue #163+ + ENDIF. " issue #163+ +* lo_range = ip_excel->add_new_range( ). " issue #163- + IF lo_range IS BOUND. "ins issue #235 - repeat rows/cols + lo_range->name = ls_range-name. + lo_range->set_range_value( lv_range_value ). + ENDIF. "ins issue #235 - repeat rows/cols + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + + endmethod. + + + + + + METHOD load_worksheet. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Header/footer +* +* Please don't just delete these ToDos if they are not +* needed but leave a comment that states this +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, +* - ... +* changes: renaming variables to naming conventions +* aligning code (started) +* add a list of open ToDos here +* adding comments to explain what we are trying to achieve (started) +*--------------------------------------------------------------------* +* issue #345 - Dump on small pagemargins +* Took the chance to modularize this very long method +* by extracting the code that needed correction into +* own method ( load_worksheet_pagemargins ) +*--------------------------------------------------------------------* + TYPES: BEGIN OF lty_cell, + r TYPE string, + t TYPE string, + s TYPE string, + END OF lty_cell. + + TYPES: BEGIN OF lty_column, + min TYPE string, + max TYPE string, + width TYPE float, + customwidth TYPE string, + style TYPE string, + bestfit TYPE string, + collapsed TYPE string, + hidden TYPE string, + outlinelevel TYPE string, + END OF lty_column. + + TYPES: BEGIN OF lty_sheetview, + showgridlines TYPE zexcel_show_gridlines, + tabselected TYPE string, + zoomscalenormal TYPE string, + workbookviewid TYPE string, + showrowcolheaders TYPE string, + END OF lty_sheetview. + + TYPES: BEGIN OF lty_mergecell, + ref TYPE string, + END OF lty_mergecell. + + TYPES: BEGIN OF lty_row, + r TYPE string, + customheight TYPE string, + ht TYPE float, + spans TYPE string, + thickbot TYPE string, + customformat TYPE string, + thicktop TYPE string, + collapsed TYPE string, + hidden TYPE string, + outlinelevel TYPE string, + END OF lty_row. + + TYPES: BEGIN OF lty_page_setup, + id TYPE string, + orientation TYPE string, + scale TYPE string, + END OF lty_page_setup. + + TYPES: BEGIN OF lty_sheetformatpr, + customheight TYPE string, + defaultrowheight TYPE string, + customwidth TYPE string, + defaultcolwidth TYPE string, + END OF lty_sheetformatpr. + + TYPES: BEGIN OF lty_headerfooter, + alignwithmargins TYPE string, + differentoddeven TYPE string, + END OF lty_headerfooter. + + TYPES: BEGIN OF lty_tabcolor, + rgb TYPE string, + theme TYPE string, + END OF lty_tabcolor. + + TYPES: BEGIN OF lty_datavalidation, + type TYPE zexcel_data_val_type, + allowblank TYPE flag, + showinputmessage TYPE flag, + showerrormessage TYPE flag, + showdropdown TYPE flag, + operator TYPE zexcel_data_val_operator, + formula1 TYPE zexcel_validation_formula1, + formula2 TYPE zexcel_validation_formula1, + sqref TYPE string, + cell_column TYPE zexcel_cell_column_alpha, + cell_column_to TYPE zexcel_cell_column_alpha, + cell_row TYPE zexcel_cell_row, + cell_row_to TYPE zexcel_cell_row, + error TYPE string, + errortitle TYPE string, + prompt TYPE string, + prompttitle TYPE string, + errorstyle TYPE zexcel_data_val_error_style, + END OF lty_datavalidation. + + + + CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_true_int TYPE string VALUE '1', + lc_rel_drawing TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', + lc_rel_hyperlink TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', + lc_rel_printer TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings'. + + DATA: lo_ixml_worksheet TYPE REF TO if_ixml_document, + lo_ixml_cells TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml_iterator2 TYPE REF TO if_ixml_node_iterator, + lo_ixml_row_elem TYPE REF TO if_ixml_element, + lo_ixml_cell_elem TYPE REF TO if_ixml_element, + ls_cell TYPE lty_cell, + lv_index TYPE i, + lo_ixml_value_elem TYPE REF TO if_ixml_element, + lo_ixml_formula_elem TYPE REF TO if_ixml_element, + lv_cell_value TYPE zexcel_cell_value, + lv_cell_formula TYPE zexcel_cell_formula, + lv_cell_column TYPE zexcel_cell_column_alpha, + lv_cell_row TYPE zexcel_cell_row, + lo_excel_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style, + + lo_ixml_imension_elem TYPE REF TO if_ixml_element, "#+234 + lv_dimension_range TYPE string, "#+234 + + lo_ixml_sheetview_elem TYPE REF TO if_ixml_element, + ls_sheetview TYPE lty_sheetview, + lo_ixml_pane_elem TYPE REF TO if_ixml_element, + ls_excel_pane TYPE zexcel_pane, + lv_pane_cell_row TYPE zexcel_cell_row, + lv_pane_cell_col_a TYPE zexcel_cell_column_alpha, + lv_pane_cell_col TYPE zexcel_cell_column, + + lo_ixml_mergecells TYPE REF TO if_ixml_node_collection, + lo_ixml_mergecell_elem TYPE REF TO if_ixml_element, + ls_mergecell TYPE lty_mergecell, + lv_merge_column_start TYPE zexcel_cell_column_alpha, + lv_merge_column_end TYPE zexcel_cell_column_alpha, + lv_merge_row_start TYPE zexcel_cell_row, + lv_merge_row_end TYPE zexcel_cell_row, + + lo_ixml_sheetformatpr_elem TYPE REF TO if_ixml_element, + ls_sheetformatpr TYPE lty_sheetformatpr, + lv_height TYPE float, + + lo_ixml_headerfooter_elem TYPE REF TO if_ixml_element, + ls_headerfooter TYPE lty_headerfooter, + ls_odd_header TYPE zexcel_s_worksheet_head_foot, + ls_odd_footer TYPE zexcel_s_worksheet_head_foot, + ls_even_header TYPE zexcel_s_worksheet_head_foot, + ls_even_footer TYPE zexcel_s_worksheet_head_foot, + lo_ixml_hf_value_elem TYPE REF TO if_ixml_element, + + lo_ixml_pagesetup_elem TYPE REF TO if_ixml_element, + ls_pagesetup TYPE lty_page_setup, + + lo_ixml_columns TYPE REF TO if_ixml_node_collection, + lo_ixml_column_elem TYPE REF TO if_ixml_element, + ls_column TYPE lty_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lv_outline_level TYPE int4, + + lo_ixml_tabcolor TYPE REF TO if_ixml_element, + ls_tabcolor TYPE lty_tabcolor, + ls_excel_s_tabcolor TYPE zexcel_s_tabcolor, + + lo_ixml_rows TYPE REF TO if_ixml_node_collection, + ls_row TYPE lty_row, + lv_max_col TYPE i, "for use with SPANS element +* lv_min_col TYPE i, "for use with SPANS element " not in use currently + lv_max_col_s TYPE char10, "for use with SPANS element + lv_min_col_s TYPE char10, "for use with SPANS element + lo_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, +*--- End of current code aligning ------------------------------------------------------------------- + + lv_path TYPE string, + lo_ixml_node TYPE REF TO if_ixml_element, + ls_relationship TYPE t_relationship, + lo_ixml_rels_worksheet TYPE REF TO if_ixml_document, + lv_rels_worksheet_path TYPE string, + lv_stripped_name TYPE chkfile, + lv_dirname TYPE string, + + lt_external_hyperlinks TYPE gtt_external_hyperlinks, + ls_external_hyperlink LIKE LINE OF lt_external_hyperlinks, + + lo_ixml_datavalidations TYPE REF TO if_ixml_node_collection, + lo_ixml_datavalidation_elem TYPE REF TO if_ixml_element, + ls_datavalidation TYPE lty_datavalidation, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lv_datavalidation_range TYPE string, + lt_datavalidation_range TYPE TABLE OF string. + +*--------------------------------------------------------------------* +* §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 +* +* The xlsx Zip-archive has generally the following folder structure: +* <root> | +* |--> _rels +* |--> doc_Props +* |--> xl | +* |--> _rels +* |--> theme +* |--> worksheets +*--------------------------------------------------------------------* + + " Read Workbook Relationships + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = ip_path + IMPORTING + stripped_name = lv_stripped_name + file_path = lv_dirname. + CONCATENATE lv_dirname '_rels/' lv_stripped_name '.rels' + INTO lv_rels_worksheet_path. + TRY. " +#222 _rels/xxx.rels might not be present. If not found there can be no drawings --> just ignore this section + lo_ixml_rels_worksheet = me->get_ixml_from_zip_archive( lv_rels_worksheet_path ). + lo_ixml_node ?= lo_ixml_rels_worksheet->find_from_name( 'Relationship' ). + CATCH zcx_excel. "#EC NO_HANDLER +#222 + " +#222 No errorhandling necessary - node will be unbound if error occurs + ENDTRY. " +#222 + WHILE lo_ixml_node IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_node + CHANGING + cp_structure = ls_relationship ). + CONCATENATE lv_dirname ls_relationship-target INTO lv_path. + lv_path = resolve_path( lv_path ). + + CASE ls_relationship-type. + WHEN lc_rel_drawing. + " Read Drawings +* Issue # 339 Not all drawings are in the path mentioned below. +* Some Excel elements like textfields (which we don't support ) have a drawing-part in the relationsships +* but no "xl/drawings/_rels/drawing____.xml.rels" part. +* Since we don't support these there is no need to read them. Catching exceptions thrown +* in the "load_worksheet_drawing" shouldn't lead to an abortion of the reading + TRY. + me->load_worksheet_drawing( ip_path = lv_path + io_worksheet = io_worksheet ). + CATCH zcx_excel. "--> then ignore it + ENDTRY. + + WHEN lc_rel_printer. + " Read Printer settings + + WHEN lc_rel_hyperlink. + MOVE-CORRESPONDING ls_relationship TO ls_external_hyperlink. + INSERT ls_external_hyperlink INTO TABLE lt_external_hyperlinks. + + WHEN OTHERS. + ENDCASE. + + lo_ixml_node ?= lo_ixml_node->get_next( ). + ENDWHILE. + + + lo_ixml_worksheet = me->get_ixml_from_zip_archive( ip_path ). + + + lo_ixml_tabcolor ?= lo_ixml_worksheet->find_from_name( 'tabColor' ). + IF lo_ixml_tabcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_tabcolor + CHANGING + cp_structure = ls_tabcolor ). +* Theme not supported yet + IF ls_tabcolor-rgb IS NOT INITIAL. + ls_excel_s_tabcolor-rgb = ls_tabcolor-rgb. + io_worksheet->set_tabcolor( ls_excel_s_tabcolor ). + ENDIF. + ENDIF. + + lo_ixml_rows = lo_ixml_worksheet->get_elements_by_tag_name( name = 'row' ). + lo_ixml_iterator = lo_ixml_rows->create_iterator( ). + lo_ixml_row_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_row_elem IS BOUND. + + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_row_elem + CHANGING + cp_structure = ls_row ). + SPLIT ls_row-spans AT ':' INTO lv_min_col_s lv_max_col_s. + lv_index = lv_max_col_s. + IF lv_index > lv_max_col. + lv_max_col = lv_index. + ENDIF. + lv_cell_row = ls_row-r. + IF ls_row-customheight = '1' + OR ls_row-collapsed = lc_xml_attr_true + OR ls_row-collapsed = lc_xml_attr_true_int + OR ls_row-hidden = lc_xml_attr_true + OR ls_row-hidden = lc_xml_attr_true_int + OR ls_row-outlinelevel > '0'. + lo_row_dimension = io_worksheet->get_row_dimension( lv_cell_row ). + IF ls_row-customheight = '1'. + lo_row_dimension->set_row_height( ls_row-ht ). + ENDIF. + + IF ls_row-collapsed = lc_xml_attr_true + OR ls_row-collapsed = lc_xml_attr_true_int. + lo_row_dimension->set_collapsed( abap_true ). + ENDIF. + + IF ls_row-hidden = lc_xml_attr_true + OR ls_row-hidden = lc_xml_attr_true_int. + lo_row_dimension->set_visible( abap_false ). + ENDIF. + + IF ls_row-outlinelevel > ''. +* outline_level = condense( row-outlineLevel ). "For basis 7.02 and higher + CONDENSE ls_row-outlinelevel. + lv_outline_level = ls_row-outlinelevel. + IF lv_outline_level > 0. + lo_row_dimension->set_outline_level( lv_outline_level ). + ENDIF. + ENDIF. + ENDIF. + + lo_ixml_cells = lo_ixml_row_elem->get_elements_by_tag_name( name = 'c' ). + lo_ixml_iterator2 = lo_ixml_cells->create_iterator( ). + lo_ixml_cell_elem ?= lo_ixml_iterator2->get_next( ). + WHILE lo_ixml_cell_elem IS BOUND. + CLEAR: lv_cell_value, + lv_cell_formula, + lv_style_guid. + + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_cell_elem CHANGING cp_structure = ls_cell ). + + lo_ixml_value_elem = lo_ixml_cell_elem->find_from_name( name = 'v' ). + + CASE ls_cell-t. + WHEN 's'. " String values are stored as index in shared string table + lv_index = lo_ixml_value_elem->get_value( ) + 1. + READ TABLE shared_strings INTO lv_cell_value INDEX lv_index. + WHEN 'inlineStr'. " inlineStr values are kept in special node + lo_ixml_value_elem = lo_ixml_cell_elem->find_from_name( name = 'is' ). + IF lo_ixml_value_elem IS BOUND. + lv_cell_value = lo_ixml_value_elem->get_value( ). + ENDIF. + WHEN OTHERS. "other types are stored directly + IF lo_ixml_value_elem IS BOUND. + lv_cell_value = lo_ixml_value_elem->get_value( ). + ENDIF. + ENDCASE. + + CLEAR lv_style_guid. + "read style based on index + IF ls_cell-s IS NOT INITIAL. + lv_index = ls_cell-s + 1. + READ TABLE styles INTO lo_excel_style INDEX lv_index. + IF sy-subrc = 0. + lv_style_guid = lo_excel_style->get_guid( ). + ENDIF. + ENDIF. + + lo_ixml_formula_elem = lo_ixml_cell_elem->find_from_name( name = 'f' ). + IF lo_ixml_formula_elem IS BOUND. + lv_cell_formula = lo_ixml_formula_elem->get_value( ). +*--------------------------------------------------------------------* +* Begin of insertion issue#284 - Copied formulae not +*--------------------------------------------------------------------* + DATA: BEGIN OF ls_formula_attributes, + ref TYPE string, + si TYPE i, + t TYPE string, + END OF ls_formula_attributes, + ls_ref_formula TYPE ty_ref_formulae. + + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_formula_elem CHANGING cp_structure = ls_formula_attributes ). + IF ls_formula_attributes-t = 'shared'. + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_cell-r + IMPORTING + e_column = lv_cell_column + e_row = lv_cell_row ). + + TRY. + CLEAR ls_ref_formula. + ls_ref_formula-sheet = io_worksheet. + ls_ref_formula-row = lv_cell_row. + ls_ref_formula-column = zcl_excel_common=>convert_column2int( lv_cell_column ). + ls_ref_formula-si = ls_formula_attributes-si. + ls_ref_formula-ref = ls_formula_attributes-ref. + ls_ref_formula-formula = lv_cell_formula. + INSERT ls_ref_formula INTO TABLE me->mt_ref_formulae. + CATCH cx_root. + BREAK-POINT. + ENDTRY. + ENDIF. +*--------------------------------------------------------------------* +* End of insertion issue#284 - Copied formulae not +*--------------------------------------------------------------------* + ENDIF. + + IF lv_cell_value IS NOT INITIAL + OR lv_cell_formula IS NOT INITIAL + OR lv_style_guid IS NOT INITIAL. + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_cell-r + IMPORTING + e_column = lv_cell_column + e_row = lv_cell_row ). + io_worksheet->set_cell( ip_column = lv_cell_column " cell_elem Column + ip_row = lv_cell_row " cell_elem row_elem + ip_value = lv_cell_value " cell_elem Value + ip_formula = lv_cell_formula + ip_data_type = ls_cell-t + ip_style = lv_style_guid ). + ENDIF. + lo_ixml_cell_elem ?= lo_ixml_iterator2->get_next( ). + ENDWHILE. + lo_ixml_row_elem ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + +*--------------------------------------------------------------------* +*#234 - column width not read correctly - begin of coding +* reason - libre office doesn't use SPAN in row - definitions +*--------------------------------------------------------------------* + IF lv_max_col = 0. + lo_ixml_imension_elem = lo_ixml_worksheet->find_from_name( name = 'dimension' ). + IF lo_ixml_imension_elem IS BOUND. + lv_dimension_range = lo_ixml_imension_elem->get_attribute( 'ref' ). + IF lv_dimension_range CS ':'. + REPLACE REGEX '\D+\d+:(\D+)\d+' IN lv_dimension_range WITH '$1'. " Get max column + ELSE. + REPLACE REGEX '(\D+)\d+' IN lv_dimension_range WITH '$1'. " Get max column + ENDIF. + lv_max_col = zcl_excel_common=>convert_column2int( lv_dimension_range ). + ENDIF. + ENDIF. +*--------------------------------------------------------------------* +*#234 - column width not read correctly - end of coding +*--------------------------------------------------------------------* + + "Get the customized column width + lo_ixml_columns = lo_ixml_worksheet->get_elements_by_tag_name( name = 'col' ). + lo_ixml_iterator = lo_ixml_columns->create_iterator( ). + lo_ixml_column_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_column_elem IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_column_elem + CHANGING + cp_structure = ls_column ). + lo_ixml_column_elem ?= lo_ixml_iterator->get_next( ). + IF ls_column-customwidth = lc_xml_attr_true + OR ls_column-customwidth = lc_xml_attr_true_int + OR ls_column-bestfit = lc_xml_attr_true + OR ls_column-bestfit = lc_xml_attr_true_int + OR ls_column-collapsed = lc_xml_attr_true + OR ls_column-collapsed = lc_xml_attr_true_int + OR ls_column-hidden = lc_xml_attr_true + OR ls_column-hidden = lc_xml_attr_true_int + OR ls_column-outlinelevel > '' + OR ls_column-style > ''. + lv_index = ls_column-min. + WHILE lv_index <= ls_column-max AND lv_index <= lv_max_col. + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_index ). + lo_column_dimension = io_worksheet->get_column_dimension( lv_column_alpha ). + + IF ls_column-customwidth = lc_xml_attr_true + OR ls_column-customwidth = lc_xml_attr_true_int + OR ls_column-width IS NOT INITIAL. "+#234 + lo_column_dimension->set_width( ls_column-width ). + ENDIF. + + IF ls_column-bestfit = lc_xml_attr_true + OR ls_column-bestfit = lc_xml_attr_true_int. + lo_column_dimension->set_auto_size( abap_true ). + ENDIF. + + IF ls_column-collapsed = lc_xml_attr_true + OR ls_column-collapsed = lc_xml_attr_true_int. + lo_column_dimension->set_collapsed( abap_true ). + ENDIF. + + IF ls_column-hidden = lc_xml_attr_true + OR ls_column-hidden = lc_xml_attr_true_int. + lo_column_dimension->set_visible( abap_false ). + ENDIF. + + IF ls_column-outlinelevel > ''. +* outline_level = condense( column-outlineLevel ). + CONDENSE ls_column-outlinelevel. + lv_outline_level = ls_column-outlinelevel. + IF lv_outline_level > 0. + lo_column_dimension->set_outline_level( lv_outline_level ). + ENDIF. + ENDIF. + + IF ls_column-style > ''. + sy-index = ls_column-style + 1. + READ TABLE styles INTO lo_excel_style INDEX sy-index. + DATA: dummy_zexcel_cell_style TYPE zexcel_cell_style. + dummy_zexcel_cell_style = lo_excel_style->get_guid( ). + lo_column_dimension->set_column_style_by_guid( dummy_zexcel_cell_style ). + ENDIF. + + ADD 1 TO lv_index. + ENDWHILE. + ENDIF. + +* issue #367 - hide columns from + IF ls_column-max = zcl_excel_common=>c_excel_sheet_max_col. " Max = very right column + IF ls_column-hidden = 1 " all hidden + AND ls_column-min > 0. + io_worksheet->zif_excel_sheet_properties~hide_columns_from = zcl_excel_common=>convert_column2alpha( ls_column-min ). + ELSEIF ls_column-style > ''. +* Set default style for remaining columns + io_worksheet->zif_excel_sheet_properties~set_style( dummy_zexcel_cell_style ). + ENDIF. + ENDIF. + + + ENDWHILE. + + "Now we need to get information from the sheetView node + lo_ixml_sheetview_elem = lo_ixml_worksheet->find_from_name( name = 'sheetView' ). + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_sheetview_elem CHANGING cp_structure = ls_sheetview ). + IF ls_sheetview-showgridlines IS INITIAL OR + ls_sheetview-showgridlines = lc_xml_attr_true OR + ls_sheetview-showgridlines = lc_xml_attr_true_int. + "If the attribute is not specified or set to true, we will show grid lines + ls_sheetview-showgridlines = abap_true. + ELSE. + ls_sheetview-showgridlines = abap_false. + ENDIF. + io_worksheet->set_show_gridlines( ls_sheetview-showgridlines ). + + + "Add merge cell information + lo_ixml_mergecells = lo_ixml_worksheet->get_elements_by_tag_name( name = 'mergeCell' ). + lo_ixml_iterator = lo_ixml_mergecells->create_iterator( ). + lo_ixml_mergecell_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_mergecell_elem IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_mergecell_elem + CHANGING + cp_structure = ls_mergecell ). + zcl_excel_common=>convert_range2column_a_row( EXPORTING + i_range = ls_mergecell-ref + IMPORTING + e_column_start = lv_merge_column_start + e_column_end = lv_merge_column_end + e_row_start = lv_merge_row_start + e_row_end = lv_merge_row_end ). + lo_ixml_mergecell_elem ?= lo_ixml_iterator->get_next( ). + io_worksheet->set_merge( EXPORTING + ip_column_start = lv_merge_column_start + ip_column_end = lv_merge_column_end + ip_row = lv_merge_row_start + ip_row_to = lv_merge_row_end ). + ENDWHILE. + + " read sheet format properties + lo_ixml_sheetformatpr_elem = lo_ixml_worksheet->find_from_name( 'sheetFormatPr' ). + IF lo_ixml_sheetformatpr_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_sheetformatpr_elem CHANGING cp_structure = ls_sheetformatpr ). + IF ls_sheetformatpr-customheight = '1'. + lv_height = ls_sheetformatpr-defaultrowheight. + lo_row_dimension = io_worksheet->get_default_row_dimension( ). + lo_row_dimension->set_row_height( lv_height ). + ENDIF. + + " TODO... column + ENDIF. + + " Read in page margins + me->load_worksheet_pagemargins( EXPORTING + io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet ). + + " Read in page setup + lo_ixml_pagesetup_elem = lo_ixml_worksheet->find_from_name( 'pageSetup' ). + IF lo_ixml_pagesetup_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_pagesetup_elem + CHANGING + cp_structure = ls_pagesetup ). + io_worksheet->sheet_setup->orientation = ls_pagesetup-orientation. + io_worksheet->sheet_setup->scale = ls_pagesetup-scale. + ENDIF. + + " Read header footer + lo_ixml_headerfooter_elem = lo_ixml_worksheet->find_from_name( 'headerFooter' ). + IF lo_ixml_headerfooter_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_headerfooter_elem CHANGING cp_structure = ls_headerfooter ). + io_worksheet->sheet_setup->diff_oddeven_headerfooter = ls_headerfooter-differentoddeven. + + lo_ixml_hf_value_elem = lo_ixml_headerfooter_elem->find_from_name( 'oddFooter' ). + IF lo_ixml_hf_value_elem IS NOT INITIAL. + ls_odd_footer-left_value = lo_ixml_hf_value_elem->get_value( ). + ENDIF. + +* 2do§1 Header/footer + " TODO.. get the rest. + + io_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_odd_header + ip_odd_footer = ls_odd_footer + ip_even_header = ls_even_header + ip_even_footer = ls_even_footer ). + + ENDIF. + + " Start fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 + " Read pane + lo_ixml_pane_elem = lo_ixml_sheetview_elem->find_from_name( name = 'pane' ). + IF lo_ixml_pane_elem IS BOUND. + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_pane_elem CHANGING cp_structure = ls_excel_pane ). + " Issue #194 + " Replace REGEX with method from the common class + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_excel_pane-topleftcell + IMPORTING + e_column = lv_pane_cell_col_a " Cell Column + e_row = lv_pane_cell_row ). " Natural number + lv_pane_cell_col = zcl_excel_common=>convert_column2int( lv_pane_cell_col_a ). + SUBTRACT 1 FROM: lv_pane_cell_col, + lv_pane_cell_row. + IF lv_pane_cell_col > 0 + AND lv_pane_cell_row > 0. + io_worksheet->freeze_panes( ip_num_rows = lv_pane_cell_row + ip_num_columns = lv_pane_cell_col ). + ELSEIF lv_pane_cell_row > 0. + io_worksheet->freeze_panes( ip_num_rows = lv_pane_cell_row ). + ELSE. + io_worksheet->freeze_panes( ip_num_columns = lv_pane_cell_col ). + ENDIF. + ENDIF. + " End fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 + + " Start fix 276 Read data validations + lo_ixml_datavalidations = lo_ixml_worksheet->get_elements_by_tag_name( name = 'dataValidation' ). + lo_ixml_iterator = lo_ixml_datavalidations->create_iterator( ). + lo_ixml_datavalidation_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_datavalidation_elem IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_datavalidation_elem + CHANGING + cp_structure = ls_datavalidation ). + CLEAR lo_ixml_formula_elem. + lo_ixml_formula_elem = lo_ixml_datavalidation_elem->find_from_name( name = 'formula1' ). + IF lo_ixml_formula_elem IS BOUND. + ls_datavalidation-formula1 = lo_ixml_formula_elem->get_value( ). + ENDIF. + CLEAR lo_ixml_formula_elem. + lo_ixml_formula_elem = lo_ixml_datavalidation_elem->find_from_name( name = 'formula2' ). + IF lo_ixml_formula_elem IS BOUND. + ls_datavalidation-formula2 = lo_ixml_formula_elem->get_value( ). + ENDIF. + SPLIT ls_datavalidation-sqref AT space INTO TABLE lt_datavalidation_range. + LOOP AT lt_datavalidation_range INTO lv_datavalidation_range. + zcl_excel_common=>convert_range2column_a_row( EXPORTING + i_range = lv_datavalidation_range + IMPORTING + e_column_start = ls_datavalidation-cell_column + e_column_end = ls_datavalidation-cell_column_to + e_row_start = ls_datavalidation-cell_row + e_row_end = ls_datavalidation-cell_row_to ). + lo_data_validation = io_worksheet->add_new_data_validation( ). + lo_data_validation->type = ls_datavalidation-type. + lo_data_validation->allowblank = ls_datavalidation-allowblank. + lo_data_validation->showinputmessage = ls_datavalidation-showinputmessage. + lo_data_validation->showerrormessage = ls_datavalidation-showerrormessage. + lo_data_validation->showdropdown = ls_datavalidation-showdropdown. + lo_data_validation->operator = ls_datavalidation-operator. + lo_data_validation->formula1 = ls_datavalidation-formula1. + lo_data_validation->formula2 = ls_datavalidation-formula2. + lo_data_validation->prompttitle = ls_datavalidation-prompttitle. + lo_data_validation->prompt = ls_datavalidation-prompt. + lo_data_validation->errortitle = ls_datavalidation-errortitle. + lo_data_validation->error = ls_datavalidation-error. + lo_data_validation->errorstyle = ls_datavalidation-errorstyle. + lo_data_validation->cell_row = ls_datavalidation-cell_row. + lo_data_validation->cell_row_to = ls_datavalidation-cell_row_to. + lo_data_validation->cell_column = ls_datavalidation-cell_column. + lo_data_validation->cell_column_to = ls_datavalidation-cell_column_to. + ENDLOOP. + lo_ixml_datavalidation_elem ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + " End fix 276 Read data validations + + " Read hyperlinks + TRY. + me->load_worksheet_hyperlinks( io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet + it_external_hyperlinks = lt_external_hyperlinks ). + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + + TRY. + me->fill_row_outlines( io_worksheet = io_worksheet ). + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + + " Issue #366 - conditional formatting + TRY. + me->load_worksheet_cond_format( io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet ). + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + + " Issue #377 - pagebreaks + TRY. + me->load_worksheet_pagebreaks( io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet ). + CATCH zcx_excel. " Ignore pagebreak reading errors - pass everything we were able to identify + ENDTRY. + + +ENDMETHOD. + + + + + + METHOD load_worksheet_cond_format. + + DATA: lo_ixml_cond_formats TYPE REF TO if_ixml_node_collection, + lo_ixml_cond_format TYPE REF TO if_ixml_element, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, +* lo_ixml_iterator2 TYPE REF TO if_ixml_node_iterator, +* lo_ixml TYPE REF TO if_ixml_element, + lo_ixml_rule TYPE REF TO if_ixml_element, +* lo_ixml_rule_iconset TYPE REF TO if_ixml_element, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional. + + + DATA: lv_area TYPE string, + lv_area_start_row TYPE zexcel_cell_row, + lv_area_end_row TYPE zexcel_cell_row, + lv_area_start_col TYPE zexcel_cell_column_alpha, + lv_area_end_col TYPE zexcel_cell_column_alpha, + lv_rule TYPE zexcel_condition_rule. + + +* FIELD-SYMBOLS: <ls_external_hyperlink> LIKE LINE OF it_external_hyperlinks. + + lo_ixml_cond_formats = io_ixml_worksheet->get_elements_by_tag_name( name = 'conditionalFormatting' ). + lo_ixml_iterator = lo_ixml_cond_formats->create_iterator( ). + lo_ixml_cond_format ?= lo_ixml_iterator->get_next( ). + + WHILE lo_ixml_cond_format IS BOUND. + + CLEAR: lv_area, + lo_ixml_rule, + lo_style_conditional. + + +*--------------------------------------------------------------------* +* Get type of rule +*--------------------------------------------------------------------* + lo_ixml_rule ?= lo_ixml_cond_format->get_first_child( ). " = cfRule + IF lo_ixml_rule IS BOUND. + lv_rule = lo_ixml_rule->get_attribute_ns( 'type' ). + +*--------------------------------------------------------------------* +* Depending on ruletype get additional information +*--------------------------------------------------------------------* + CASE lv_rule. + + WHEN zcl_excel_style_conditional=>c_rule_cellis. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_ci( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + +* WHEN zcl_excel_style_conditional=>c_rule_containstext. +* + WHEN zcl_excel_style_conditional=>c_rule_databar. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_db( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_expression. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_ex( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_is( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_colorscale. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_cs( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_top10. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_t10( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_above_average. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_aa( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + +* WHEN zcl_excel_style_conditional=>c_rule_none. +* + + WHEN OTHERS. + ENDCASE. + ENDIF. + + IF lo_style_conditional IS BOUND. + lo_style_conditional->rule = lv_rule. + lo_style_conditional->priority = lo_ixml_rule->get_attribute_ns( 'priority' ). +*--------------------------------------------------------------------* +* Set area to which conditional formatting belongs +*--------------------------------------------------------------------* + lv_area = lo_ixml_cond_format->get_attribute_ns( 'sqref' ). + zcl_excel_common=>convert_range2column_a_row( EXPORTING + i_range = lv_area + IMPORTING + e_column_start = lv_area_start_col + e_column_end = lv_area_end_col + e_row_start = lv_area_start_row + e_row_end = lv_area_end_row ). + lo_style_conditional->set_range( ip_start_column = lv_area_start_col + ip_stop_column = lv_area_end_col + ip_start_row = lv_area_start_row + ip_stop_row = lv_area_end_row ). + + ENDIF. + + + lo_ixml_cond_format ?= lo_ixml_iterator->get_next( ). + + ENDWHILE. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_aa. + DATA: lv_dxf_style_index TYPE i, + val TYPE string. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + +*--------------------------------------------------------------------* +* above or below average +*--------------------------------------------------------------------* + val = io_ixml_rule->get_attribute_ns( 'aboveAverage' ). + IF val = '0'. " 0 = below average + io_style_conditional->mode_above_average-above_average = space. + ELSE. + io_style_conditional->mode_above_average-above_average = 'X'. " Not present or <> 0 --> we use above average + ENDIF. + +*--------------------------------------------------------------------* +* Equal average also? +*--------------------------------------------------------------------* + CLEAR val. + val = io_ixml_rule->get_attribute_ns( 'equalAverage' ). + IF val = '1'. " 0 = below average + io_style_conditional->mode_above_average-equal_average = 'X'. + ELSE. + io_style_conditional->mode_above_average-equal_average = ' '. " Not present or <> 1 --> we use not equal average + ENDIF. + +*--------------------------------------------------------------------* +* Standard deviation instead of value ( 2nd stddev, 3rd stdev ) +*--------------------------------------------------------------------* + CLEAR val. + val = io_ixml_rule->get_attribute_ns( 'stdDev' ). + CASE val. + WHEN 1 + OR 2 + OR 3. " These seem to be supported by excel - don't try anything more + io_style_conditional->mode_above_average-standard_deviation = val. + ENDCASE. + +*--------------------------------------------------------------------* +* Cell formatting for top10 +*--------------------------------------------------------------------* + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_above_average-cell_style = <ls_dxf_style>-guid. + ENDIF. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_ci. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element, + lv_dxf_style_index TYPE i, + lo_excel_style LIKE LINE OF me->styles. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + + io_style_conditional->mode_cellis-operator = io_ixml_rule->get_attribute_ns( 'operator' ). + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_cellis-cell_style = <ls_dxf_style>-guid. + ENDIF. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'formula' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_cellis-formula = lo_ixml->get_value( ). + + WHEN 2. + io_style_conditional->mode_cellis-formula2 = lo_ixml->get_value( ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_cs. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element. + + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'cfvo' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_colorscale-cfvo1_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_colorscale-cfvo1_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 2. + io_style_conditional->mode_colorscale-cfvo2_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_colorscale-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 3. + io_style_conditional->mode_colorscale-cfvo3_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_colorscale-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'color' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_colorscale-colorrgb1 = lo_ixml->get_attribute_ns( 'rgb' ). + + WHEN 2. + io_style_conditional->mode_colorscale-colorrgb2 = lo_ixml->get_attribute_ns( 'rgb' ). + + WHEN 3. + io_style_conditional->mode_colorscale-colorrgb3 = lo_ixml->get_attribute_ns( 'rgb' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_db. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element. + + lo_ixml ?= io_ixml_rule->find_from_name( 'color' ). + IF lo_ixml IS BOUND. + io_style_conditional->mode_databar-colorrgb = lo_ixml->get_attribute_ns( 'rgb' ). + ENDIF. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'cfvo' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_databar-cfvo1_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_databar-cfvo1_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 2. + io_style_conditional->mode_databar-cfvo2_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_databar-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_ex. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element, + lv_dxf_style_index TYPE i, + lo_excel_style LIKE LINE OF me->styles. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_expression-cell_style = <ls_dxf_style>-guid. + ENDIF. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'formula' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_expression-formula = lo_ixml->get_value( ). + + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_is. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element, + lo_ixml_rule_iconset TYPE REF TO if_ixml_element. + + lo_ixml_rule_iconset ?= io_ixml_rule->get_first_child( ). + io_style_conditional->mode_iconset-iconset = lo_ixml_rule_iconset->get_attribute_ns( 'iconSet' ). + io_style_conditional->mode_iconset-showvalue = lo_ixml_rule_iconset->get_attribute_ns( 'showValue' ). + lo_ixml_nodes ?= lo_ixml_rule_iconset->get_elements_by_tag_name( 'cfvo' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_iconset-cfvo1_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo1_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 2. + io_style_conditional->mode_iconset-cfvo2_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 3. + io_style_conditional->mode_iconset-cfvo3_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo3_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 4. + io_style_conditional->mode_iconset-cfvo4_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo4_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 5. + io_style_conditional->mode_iconset-cfvo5_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo5_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_t10. + DATA: lv_dxf_style_index TYPE i. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + + io_style_conditional->mode_top10-topxx_count = io_ixml_rule->get_attribute_ns( 'rank' ). " Top10, Top20, Top 50... + + io_style_conditional->mode_top10-percent = io_ixml_rule->get_attribute_ns( 'percent' ). " Top10 percent instead of Top10 values + if io_style_conditional->mode_top10-percent = '1'. + io_style_conditional->mode_top10-percent = 'X'. + else. + io_style_conditional->mode_top10-percent = ' '. + endif. + + io_style_conditional->mode_top10-bottom = io_ixml_rule->get_attribute_ns( 'bottom' ). " Bottom10 instead of Top10 + if io_style_conditional->mode_top10-bottom = '1'. + io_style_conditional->mode_top10-bottom = 'X'. + else. + io_style_conditional->mode_top10-bottom = ' '. + endif. +*--------------------------------------------------------------------* +* Cell formatting for top10 +*--------------------------------------------------------------------* + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_top10-cell_style = <ls_dxf_style>-guid. + ENDIF. + +ENDMETHOD. + + + + + + method LOAD_WORKSHEET_DRAWING. + + TYPES: BEGIN OF t_c_nv_pr, + name TYPE string, + id TYPE string, + END OF t_c_nv_pr. + + TYPES: BEGIN OF t_blip, + cstate TYPE string, + embed TYPE string, + END OF t_blip. + + TYPES: BEGIN OF t_chart, + id TYPE string, + END OF t_chart. + + CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_true_int TYPE string VALUE '1'. + CONSTANTS: lc_rel_chart TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', + lc_rel_image TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'. + + DATA: drawing TYPE REF TO if_ixml_document, + anchors TYPE REF TO if_ixml_node_collection, + node TYPE REF TO if_ixml_element, + coll_length TYPE i, + iterator TYPE REF TO if_ixml_node_iterator, + anchor_elem TYPE REF TO if_ixml_element, + + relationship TYPE t_relationship, + rel_drawings TYPE t_rel_drawings, + rel_drawing TYPE t_rel_drawing, + rels_drawing TYPE REF TO if_ixml_document, + rels_drawing_path TYPE string, + stripped_name TYPE chkfile, + dirname TYPE string, + + path TYPE string, + path2 TYPE text255, + file_ext2 TYPE char10. + + " Read Workbook Relationships + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = ip_path + IMPORTING + stripped_name = stripped_name + file_path = dirname. + CONCATENATE dirname '_rels/' stripped_name '.rels' + INTO rels_drawing_path. + rels_drawing_path = resolve_path( rels_drawing_path ). + rels_drawing = me->get_ixml_from_zip_archive( rels_drawing_path ). + node ?= rels_drawing->find_from_name( 'Relationship' ). + WHILE node IS BOUND. + fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). + + rel_drawing-id = relationship-id. + + CONCATENATE dirname relationship-target INTO path. + path = resolve_path( path ). + rel_drawing-content = me->get_from_zip_archive( path ). "------------> This is for template usage + + path2 = path. + zcl_excel_common=>split_file( EXPORTING ip_file = path2 + IMPORTING ep_extension = file_ext2 ). + rel_drawing-file_ext = file_ext2. + + "-------------Added by Alessandro Iannacci - Should load graph xml + CASE relationship-type. + WHEN lc_rel_chart. + "Read chart xml + rel_drawing-content_xml = me->get_ixml_from_zip_archive( path ). + WHEN OTHERS. + ENDCASE. + "---------------------------- + + + APPEND rel_drawing TO rel_drawings. + + node ?= node->get_next( ). + ENDWHILE. + + drawing = me->get_ixml_from_zip_archive( ip_path ). + +* one-cell anchor ************** + anchors = drawing->get_elements_by_tag_name( name = 'oneCellAnchor' namespace = 'xdr' ). + coll_length = anchors->get_length( ). + iterator = anchors->create_iterator( ). + DO coll_length TIMES. + anchor_elem ?= iterator->get_next( ). + + CALL METHOD me->load_drawing_anchor + EXPORTING + io_anchor_element = anchor_elem + io_worksheet = io_worksheet + it_related_drawings = rel_drawings. + + ENDDO. + +* two-cell anchor ****************** + anchors = drawing->get_elements_by_tag_name( name = 'twoCellAnchor' namespace = 'xdr' ). + coll_length = anchors->get_length( ). + iterator = anchors->create_iterator( ). + DO coll_length TIMES. + anchor_elem ?= iterator->get_next( ). + + CALL METHOD me->load_drawing_anchor + EXPORTING + io_anchor_element = anchor_elem + io_worksheet = io_worksheet + it_related_drawings = rel_drawings. + + ENDDO. + + endmethod. + + + + + + + METHOD load_worksheet_hyperlinks. + + DATA: lo_ixml_hyperlinks TYPE REF TO if_ixml_node_collection, + lo_ixml_hyperlink TYPE REF TO if_ixml_element, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lv_row TYPE zexcel_cell_row, + lv_column TYPE zexcel_cell_column_alpha, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + lv_value TYPE zexcel_cell_value. + + DATA: BEGIN OF ls_hyperlink, + ref TYPE string, + display TYPE string, + location TYPE string, + tooltip TYPE string, + r_id TYPE string, + END OF ls_hyperlink. + + FIELD-SYMBOLS: <ls_external_hyperlink> LIKE LINE OF it_external_hyperlinks. + + lo_ixml_hyperlinks = io_ixml_worksheet->get_elements_by_tag_name( name = 'hyperlink' ). + lo_ixml_iterator = lo_ixml_hyperlinks->create_iterator( ). + lo_ixml_hyperlink ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_hyperlink IS BOUND. + + CLEAR ls_hyperlink. + CLEAR lo_hyperlink. + + ls_hyperlink-ref = lo_ixml_hyperlink->get_attribute_ns( 'ref' ). + ls_hyperlink-display = lo_ixml_hyperlink->get_attribute_ns( 'display' ). + ls_hyperlink-location = lo_ixml_hyperlink->get_attribute_ns( 'location' ). + ls_hyperlink-tooltip = lo_ixml_hyperlink->get_attribute_ns( 'tooltip' ). + ls_hyperlink-r_id = lo_ixml_hyperlink->get_attribute( name = 'id' + namespace = 'r' ). + IF ls_hyperlink-r_id IS INITIAL. " Internal link + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = ls_hyperlink-location ). + ELSE. " External link + READ TABLE it_external_hyperlinks ASSIGNING <ls_external_hyperlink> WITH TABLE KEY id = ls_hyperlink-r_id. + IF sy-subrc = 0. + lo_hyperlink = zcl_excel_hyperlink=>create_external_link( iv_url = <ls_external_hyperlink>-target ). + ENDIF. + ENDIF. + IF lo_hyperlink IS BOUND. " because of unsupported external links + + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_hyperlink-ref + IMPORTING + e_row = lv_row + e_column = lv_column ). +* Currently it is not allowed to pass a hyperlink w/o text, but text has already been read. +* So just reread it and be done with it + io_worksheet->get_cell( EXPORTING + ip_column = lv_column + ip_row = lv_row + IMPORTING + ep_value = lv_value ). + io_worksheet->set_cell( ip_column = lv_column + ip_row = lv_row + ip_value = lv_value + ip_hyperlink = lo_hyperlink ). + ENDIF. + + lo_ixml_hyperlink ?= lo_ixml_iterator->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + + METHOD load_worksheet_pagebreaks. + + DATA: lo_node TYPE REF TO if_ixml_element, + lo_ixml_rowbreaks TYPE REF TO if_ixml_node_collection, + lo_ixml_colbreaks TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml_rowbreak TYPE REF TO if_ixml_element, + lo_ixml_colbreak TYPE REF TO if_ixml_element, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lv_count TYPE i. + + + DATA: lt_pagebreaks TYPE STANDARD TABLE OF zcl_excel_worksheet_pagebreaks=>ts_pagebreak_at, + lo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks. + + FIELD-SYMBOLS: <ls_pagebreak_row> LIKE LINE OF lt_pagebreaks. + FIELD-SYMBOLS: <ls_pagebreak_col> LIKE LINE OF lt_pagebreaks. + +*--------------------------------------------------------------------* +* Get minimal number of cells where to add pagebreaks +* Since rows and columns are handled in separate nodes +* Build table to identify these cells +*--------------------------------------------------------------------* + lo_node ?= io_ixml_worksheet->find_from_name( 'rowBreaks' ). + lo_ixml_rowbreaks = lo_node->get_elements_by_tag_name( name = 'brk' ). + lo_ixml_iterator = lo_ixml_rowbreaks->create_iterator( ). + lo_ixml_rowbreak ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_rowbreak IS BOUND. + APPEND INITIAL LINE TO lt_pagebreaks ASSIGNING <ls_pagebreak_row>. + <ls_pagebreak_row>-cell_row = lo_ixml_rowbreak->get_attribute_ns( 'id' ). + + lo_ixml_rowbreak ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + CHECK <ls_pagebreak_row> IS ASSIGNED. + + lo_node ?= io_ixml_worksheet->find_from_name( 'colBreaks' ). + lo_ixml_colbreaks = lo_node->get_elements_by_tag_name( name = 'brk' ). + lo_ixml_iterator = lo_ixml_colbreaks->create_iterator( ). + lo_ixml_colbreak ?= lo_ixml_iterator->get_next( ). + CLEAR lv_count. + WHILE lo_ixml_colbreak IS BOUND. + ADD 1 TO lv_count. + READ TABLE lt_pagebreaks INDEX lv_count ASSIGNING <ls_pagebreak_col>. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO lt_pagebreaks ASSIGNING <ls_pagebreak_col>. + <ls_pagebreak_col>-cell_row = <ls_pagebreak_row>-cell_row. + ENDIF. + <ls_pagebreak_col>-cell_column = lo_ixml_colbreak->get_attribute_ns( 'id' ). + + lo_ixml_colbreak ?= lo_ixml_iterator->get_next( ). + ENDWHILE. +*--------------------------------------------------------------------* +* Finally add each pagebreak +*--------------------------------------------------------------------* + lo_pagebreaks = io_worksheet->get_pagebreaks( ). + LOOP AT lt_pagebreaks ASSIGNING <ls_pagebreak_row>. + lo_pagebreaks->add_pagebreak( ip_column = <ls_pagebreak_row>-cell_column + ip_row = <ls_pagebreak_row>-cell_row ). + ENDLOOP. + + +ENDMETHOD. + + + + + + METHOD load_worksheet_pagemargins. + + TYPES: BEGIN OF lty_page_margins, + footer TYPE string, + header TYPE string, + bottom TYPE string, + top TYPE string, + right TYPE string, + left TYPE string, + END OF lty_page_margins. + + DATA:lo_ixml_pagemargins_elem TYPE REF TO if_ixml_element, + ls_pagemargins TYPE lty_page_margins. + + + lo_ixml_pagemargins_elem = io_ixml_worksheet->find_from_name( 'pageMargins' ). + IF lo_ixml_pagemargins_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_pagemargins_elem + CHANGING + cp_structure = ls_pagemargins ). + io_worksheet->sheet_setup->margin_bottom = zcl_excel_common=>excel_string_to_number( ls_pagemargins-bottom ). + io_worksheet->sheet_setup->margin_footer = zcl_excel_common=>excel_string_to_number( ls_pagemargins-footer ). + io_worksheet->sheet_setup->margin_header = zcl_excel_common=>excel_string_to_number( ls_pagemargins-header ). + io_worksheet->sheet_setup->margin_left = zcl_excel_common=>excel_string_to_number( ls_pagemargins-left ). + io_worksheet->sheet_setup->margin_right = zcl_excel_common=>excel_string_to_number( ls_pagemargins-right ). + io_worksheet->sheet_setup->margin_top = zcl_excel_common=>excel_string_to_number( ls_pagemargins-top ). + ENDIF. + +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. + + + + + method RESOLVE_PATH. +*--------------------------------------------------------------------* +* ToDos: +* 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 +* +* Please don't just delete these ToDos if they are not +* needed but leave a comment that states this +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - 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 +* The output should be a resolved path without relative references +* Example: Input xl/worksheets/../drawings/drawing1.xml +* Output xl/drawings/drawing1.xml +*--------------------------------------------------------------------* + + rp_result = ip_path. +*--------------------------------------------------------------------* +* §1 Remove relative pathnames +*--------------------------------------------------------------------* +* Regular expression [^/]*/\.\./ +* [^/]* --> any number of characters other than / +* followed by /\.\./ --> the sequence /../ +* ==> worksheets/../ will be found in the example +*--------------------------------------------------------------------* + REPLACE REGEX '[^/]*/\.\./' IN rp_result WITH ``. + + + endmethod. + + + method RESOLVE_REFERENCED_FORMULAE. + TYPES: BEGIN OF ty_referenced_cells, + sheet TYPE REF TO zcl_excel_worksheet, + si TYPE i, + row_from TYPE i, + row_to TYPE i, + col_from TYPE i, + col_to TYPE i, + formula TYPE string, + ref_cell TYPE char10, + END OF ty_referenced_cells. + + DATA: ls_ref_formula LIKE LINE OF me->mt_ref_formulae, + lts_referenced_cells TYPE SORTED TABLE OF ty_referenced_cells WITH NON-UNIQUE KEY sheet si row_from row_to col_from col_to, + ls_referenced_cell LIKE LINE OF lts_referenced_cells, + lv_col_from TYPE zexcel_cell_column_alpha, + lv_col_to TYPE zexcel_cell_column_alpha, + lv_resulting_formula TYPE string, + lv_current_cell TYPE char10. + + + me->mt_ref_formulae = me->mt_ref_formulae. + +*--------------------------------------------------------------------* +* Get referenced Cells, Build ranges for easy lookup +*--------------------------------------------------------------------* + LOOP AT me->mt_ref_formulae INTO ls_ref_formula WHERE ref <> space. + + CLEAR ls_referenced_cell. + ls_referenced_cell-sheet = ls_ref_formula-sheet. + ls_referenced_cell-si = ls_ref_formula-si. + ls_referenced_cell-formula = ls_ref_formula-formula. + + TRY. + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = ls_ref_formula-ref + IMPORTING e_column_start = lv_col_from + e_column_end = lv_col_to + e_row_start = ls_referenced_cell-row_from + e_row_end = ls_referenced_cell-row_to ). + ls_referenced_cell-col_from = zcl_excel_common=>convert_column2int( lv_col_from ). + ls_referenced_cell-col_to = zcl_excel_common=>convert_column2int( lv_col_to ). + + + CLEAR ls_referenced_cell-ref_cell. + TRY. + ls_referenced_cell-ref_cell(3) = zcl_excel_common=>convert_column2alpha( ls_ref_formula-column ). + ls_referenced_cell-ref_cell+3 = ls_ref_formula-row. + CONDENSE ls_referenced_cell-ref_cell NO-GAPS. + CATCH zcx_excel. + ENDTRY. + + INSERT ls_referenced_cell INTO TABLE lts_referenced_cells. + CATCH zcx_excel. + ENDTRY. + + ENDLOOP. + +* break x0009004. +*--------------------------------------------------------------------* +* For each referencing cell determine the referenced cell +* and resolve the formula +*--------------------------------------------------------------------* + LOOP AT me->mt_ref_formulae INTO ls_ref_formula WHERE ref = space. + + + CLEAR lv_current_cell. + TRY. + lv_current_cell(3) = zcl_excel_common=>convert_column2alpha( ls_ref_formula-column ). + lv_current_cell+3 = ls_ref_formula-row. + CONDENSE lv_current_cell NO-GAPS. + CATCH zcx_excel. + ENDTRY. + + LOOP AT lts_referenced_cells INTO ls_referenced_cell WHERE sheet = ls_ref_formula-sheet + AND si = ls_ref_formula-si + AND row_from <= ls_ref_formula-row + AND row_to >= ls_ref_formula-row + AND col_from <= ls_ref_formula-column + AND col_to >= ls_ref_formula-column. + + TRY. + + lv_resulting_formula = zcl_excel_common=>determine_resulting_formula( iv_reference_cell = ls_referenced_cell-ref_cell + iv_reference_formula = ls_referenced_cell-formula + iv_current_cell = lv_current_cell ). + + ls_referenced_cell-sheet->set_cell_formula( ip_column = ls_ref_formula-column + ip_row = ls_ref_formula-row + ip_formula = lv_resulting_formula ). + CATCH zcx_excel. + ENDTRY. + EXIT. + + ENDLOOP. + + ENDLOOP. + 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. + + + + *"* 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 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' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = me->guid. + me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call +* 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. + + + + *"* 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. + 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. + + + + *"* 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_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 create_new_arbg_int. + DATA: lv_red TYPE int1, + lv_green TYPE int1, + lv_blue TYPE int1, + lv_hex TYPE x, + lv_char_red TYPE zexcel_style_color_component, + lv_char_green TYPE zexcel_style_color_component, + lv_char_blue TYPE zexcel_style_color_component. + + lv_red = iv_red MOD 256. + lv_green = iv_green MOD 256. + lv_blue = iv_blue MOD 256. + + lv_hex = lv_red. + lv_char_red = lv_hex. + + lv_hex = lv_green. + lv_char_green = lv_hex. + + lv_hex = lv_blue. + lv_char_blue = lv_hex. + + + concatenate zcl_excel_style_color=>c_alpha lv_char_red lv_char_green lv_char_blue into rv_color_argb. + + +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 factory_cond_style_iconset. + +*--------------------------------------------------------------------* +* Work in progress +* Missing: LE or LT may be specified --> extend structure ZEXCEL_CONDITIONAL_ICONSET to hold this information as well +*--------------------------------------------------------------------* + +* DATA: lv_needed_values TYPE i. +* CASE icon_type. +* +* WHEN 'C_ICONSET_3ARROWS' +* OR 'C_ICONSET_3ARROWSGRAY' +* OR 'C_ICONSET_3FLAGS' +* OR 'C_ICONSET_3SIGNS' +* OR 'C_ICONSET_3SYMBOLS' +* OR 'C_ICONSET_3SYMBOLS2' +* OR 'C_ICONSET_3TRAFFICLIGHTS' +* OR 'C_ICONSET_3TRAFFICLIGHTS2'. +* lv_needed_values = 3. +* +* WHEN 'C_ICONSET_4ARROWS' +* OR 'C_ICONSET_4ARROWSGRAY' +* OR 'C_ICONSET_4RATING' +* OR 'C_ICONSET_4REDTOBLACK' +* OR 'C_ICONSET_4TRAFFICLIGHTS'. +* lv_needed_values = 4. +* +* WHEN 'C_ICONSET_5ARROWS' +* OR 'C_ICONSET_5ARROWSGRAY' +* OR 'C_ICONSET_5QUARTERS' +* OR 'C_ICONSET_5RATING'. +* lv_needed_values = 5. +* +* WHEN OTHERS. +* RETURN. +* ENDCASE. + +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 + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method build_gradient. + check check_filltype_is_gradient( ) eq abap_true. + clear gradtype. + case filltype. + when c_fill_gradient_horizontal90. + gradtype-degree = '90'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_horizontal270. + gradtype-degree = '270'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_horizontalb. + gradtype-degree = '90'. + gradtype-position1 = '0'. + gradtype-position2 = '0.5'. + gradtype-position3 = '1'. + when c_fill_gradient_vertical. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_fromcenter. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-bottom = '0.5'. + gradtype-top = '0.5'. + gradtype-left = '0.5'. + gradtype-right = '0.5'. + when c_fill_gradient_diagonal45. + gradtype-degree = '45'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_diagonal45b. + gradtype-degree = '45'. + gradtype-position1 = '0'. + gradtype-position2 = '0.5'. + gradtype-position3 = '1'. + when c_fill_gradient_diagonal135. + gradtype-degree = '135'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_diagonal135b. + gradtype-degree = '135'. + gradtype-position1 = '0'. + gradtype-position2 = '0.5'. + gradtype-position3 = '1'. + when c_fill_gradient_cornerlt. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_cornerlb. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-bottom = '1'. + gradtype-top = '1'. + when c_fill_gradient_cornerrt. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-left = '1'. + gradtype-right = '1'. + when c_fill_gradient_cornerrb. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-bottom = '0.5'. + gradtype-top = '0.5'. + gradtype-left = '0.5'. + gradtype-right = '0.5'. + endcase. + + endmethod. "build_gradient + + + + method check_filltype_is_gradient. + case filltype. + when c_fill_gradient_horizontal90 or + c_fill_gradient_horizontal270 or + c_fill_gradient_horizontalb or + c_fill_gradient_vertical or + c_fill_gradient_fromcenter or + c_fill_gradient_diagonal45 or + c_fill_gradient_diagonal45b or + c_fill_gradient_diagonal135 or + c_fill_gradient_diagonal135b or + c_fill_gradient_cornerlt or + c_fill_gradient_cornerlb or + c_fill_gradient_cornerrt or + c_fill_gradient_cornerrb. + rv_is_gradient = abap_true. + endcase. + endmethod. "check_filltype_is_gradient + + + 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. "CONSTRUCTOR + + + + method get_structure. + es_fill-rotation = me->rotation. + es_fill-filltype = me->filltype. + es_fill-fgcolor = me->fgcolor. + es_fill-bgcolor = me->bgcolor. + me->build_gradient( ). + es_fill-gradtype = me->gradtype. + endmethod. "GET_STRUCTURE + + + + *"* 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 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. + + DATA lr_temp TYPE REF TO data. + + FIELD-SYMBOLS: <lt_table_temp> TYPE ANY TABLE, + <lt_table> TYPE ANY TABLE. + + GET REFERENCE OF ir_data INTO lr_temp. + ASSIGN lr_temp->* TO <lt_table_temp>. + CREATE DATA table_data LIKE <lt_table_temp>. + ASSIGN me->table_data->* TO <lt_table>. + <lt_table> = <lt_table_temp>. + +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. + +* use prefix notation for signed numbers + + translate contentsitem-value using '- '. + condense contentsitem-value no-gaps. + concatenate '-' contentsitem-value + into contentsitem-value. + else. + concatenate '-' contentsitem-value + into contentsitem-value. + endif. + endif. + set country space. +* Hier wird nur die korrekte Kommaseparatierung gemacht, wenn die +* Zeichen einer +* Zahl enthalten sind. Das ist für Timestamps, die auch ":" enthalten. +* Für die +* darf keine Kommaseparierung stattfinden. +* Changing for correction request - Y6BK041073 + if contentsitem-value co '0123456789.,-+E '. + translate contentsitem-value using comma_elim. + endif. + else. + clear contentsitem-value. + +* if type is not numeric -> dun display with zero + + write <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_value_lowercase 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. + lv_value_lowercase = lv_value. + TRANSLATE lv_value_lowercase TO LOWER CASE. + READ TABLE lt_column_name_buffer TRANSPORTING NO FIELDS WITH KEY table_line = lv_value_lowercase BINARY SEARCH. + IF sy-subrc <> 0. + <ls_field_catalog>-scrtext_l = lv_value. + INSERT lv_value_lowercase 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. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> + ip_abap_type = <ls_field_catalog>-abap_type + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ENDIF. + ELSE. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + + ip_formula = <fs_fldval> + ip_abap_type = <ls_field_catalog>-abap_type ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> ). + ENDIF. + ENDIF. + ELSE. + IF <ls_field_catalog>-style IS NOT INITIAL. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> + ip_abap_type = <ls_field_catalog>-abap_type + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ENDIF. + ELSE. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_abap_type = <ls_field_catalog>-abap_type + ip_value = <fs_fldval> ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> ). + ENDIF. + 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. + + + + + + + *--------------------------------------------------------------------* +* issue #293 - Roberto Bianco +* - Christian Assig 2014-03-14 +* +* changes: - Calculate widths using SAPscript font metrics +* (transaction SE73) +* - Calculate the width of dates +* - Add additional width for auto filter buttons +* - Add cell padding to simulate Excel behavior +*--------------------------------------------------------------------* +METHOD calculate_cell_width. + + CONSTANTS: + lc_default_font_name TYPE zexcel_style_font_name VALUE 'Calibri', "#EC NOTEXT + lc_default_font_height TYPE tdfontsize VALUE '110', + lc_excel_cell_padding TYPE float VALUE '0.75'. + + DATA: ld_cell_value TYPE zexcel_cell_value, + ld_current_character TYPE c LENGTH 1, + ld_style_guid TYPE zexcel_cell_style, + ls_stylemapping TYPE zexcel_s_stylemapping, + lo_table_object TYPE REF TO object, + lo_table TYPE REF TO zcl_excel_table, + ld_table_top_left_column TYPE zexcel_cell_column, + ld_table_bottom_right_column TYPE zexcel_cell_column, + ld_flag_contains_auto_filter TYPE abap_bool VALUE abap_false, + ld_flag_bold TYPE abap_bool VALUE abap_false, + ld_flag_italic TYPE abap_bool VALUE abap_false, + ld_date TYPE d, + ld_date_char TYPE c LENGTH 50, + ld_font_height TYPE tdfontsize VALUE lc_default_font_height, + lt_itcfc TYPE STANDARD TABLE OF itcfc, + ld_offset TYPE i, + ld_length TYPE i, + ld_uccp TYPE i, + ls_font_metric TYPE mty_s_font_metric, + ld_width_from_font_metrics TYPE i, + ld_font_family TYPE itcfh-tdfamily, + ld_font_name TYPE zexcel_style_font_name VALUE lc_default_font_name, + lt_font_families LIKE STANDARD TABLE OF ld_font_family, + ls_font_cache TYPE mty_s_font_cache. + + FIELD-SYMBOLS: <ls_font_cache> TYPE mty_s_font_cache, + <ls_font_metric> TYPE mty_s_font_metric, + <ls_itcfc> TYPE itcfc. + + " Determine cell content and cell style + me->get_cell( EXPORTING ip_column = ip_column + ip_row = ip_row + IMPORTING ep_value = ld_cell_value + ep_guid = ld_style_guid ). + + " ABAP2XLSX uses tables to define areas containing headers and + " auto-filters. Find out if the current cell is in the header + " of one of these tables. + LOOP AT me->tables->collection INTO lo_table_object. + " Downcast: OBJECT -> ZCL_EXCEL_TABLE + lo_table ?= lo_table_object. + + " Convert column letters to corresponding integer values + ld_table_top_left_column = + zcl_excel_common=>convert_column2int( + lo_table->settings-top_left_column ). + + ld_table_bottom_right_column = + zcl_excel_common=>convert_column2int( + lo_table->settings-bottom_right_column ). + + " Is the current cell part of the table header? + IF ip_column BETWEEN ld_table_top_left_column AND + ld_table_bottom_right_column AND + ip_row EQ lo_table->settings-top_left_row. + " Current cell is part of the table header + " -> Assume that an auto filter is present and that the font is + " bold + ld_flag_contains_auto_filter = abap_true. + ld_flag_bold = abap_true. + ENDIF. + ENDLOOP. + + " If a style GUID is present, read style attributes + IF ld_style_guid IS NOT INITIAL. + TRY. + " Read style attributes + ls_stylemapping = me->excel->get_style_to_guid( ld_style_guid ). + + " If the current cell contains the default date format, + " convert the cell value to a date and calculate its length + IF ls_stylemapping-complete_style-number_format-format_code = + zcl_excel_style_number_format=>c_format_date_std. + + " Convert excel date to ABAP date + ld_date = + zcl_excel_common=>excel_string_to_date( ld_cell_value ). + + " Format ABAP date using user's formatting settings + WRITE ld_date TO ld_date_char. + + " Remember the formatted date to calculate the cell size + ld_cell_value = ld_date_char. + + ENDIF. + + " Read the font size and convert it to the font height + " used by SAPscript (multiplication by 10) + IF ls_stylemapping-complete_stylex-font-size = abap_true. + ld_font_height = ls_stylemapping-complete_style-font-size * 10. + ENDIF. + + " If set, remember the font name + IF ls_stylemapping-complete_stylex-font-name = abap_true. + ld_font_name = ls_stylemapping-complete_style-font-name. + ENDIF. + + " If set, remember whether font is bold and italic. + IF ls_stylemapping-complete_stylex-font-bold = abap_true. + ld_flag_bold = ls_stylemapping-complete_style-font-bold. + ENDIF. + + IF ls_stylemapping-complete_stylex-font-italic = abap_true. + ld_flag_italic = ls_stylemapping-complete_style-font-italic. + ENDIF. + + CATCH zcx_excel. "#EC NO_HANDLER + " Style GUID is present, but style was not found + " Continue with default values + + ENDTRY. + ENDIF. + + " Check if the same font (font name and font attributes) was already + " used before + READ TABLE mth_font_cache + WITH TABLE KEY + font_name = ld_font_name + font_height = ld_font_height + flag_bold = ld_flag_bold + flag_italic = ld_flag_italic + ASSIGNING <ls_font_cache>. + + IF sy-subrc <> 0. + " Font is used for the first time + " Add the font to our local font cache + ls_font_cache-font_name = ld_font_name. + ls_font_cache-font_height = ld_font_height. + ls_font_cache-flag_bold = ld_flag_bold. + ls_font_cache-flag_italic = ld_flag_italic. + INSERT ls_font_cache INTO TABLE mth_font_cache + ASSIGNING <ls_font_cache>. + + " Determine the SAPscript font family name from the Excel + " font name + SELECT tdfamily + FROM tfo01 + INTO TABLE lt_font_families + UP TO 1 ROWS + WHERE tdtext = ld_font_name. + + " Check if a matching font family was found + " Fonts can be uploaded from TTF files using transaction SE73 + IF lines( lt_font_families ) > 0. + READ TABLE lt_font_families INDEX 1 INTO ld_font_family. + + " Load font metrics (returns a table with the size of each letter + " in the font) + CALL FUNCTION 'LOAD_FONT' + EXPORTING + family = ld_font_family + height = ld_font_height + printer = 'SWIN' + bold = ld_flag_bold + italic = ld_flag_italic + TABLES + metric = lt_itcfc + EXCEPTIONS + font_family = 1 + codepage = 2 + device_type = 3 + OTHERS = 4. + IF sy-subrc <> 0. + CLEAR lt_itcfc. + ENDIF. + + " For faster access, convert each character number to the actual + " character, and store the characters and their sizes in a hash + " table + LOOP AT lt_itcfc ASSIGNING <ls_itcfc>. + ld_uccp = <ls_itcfc>-cpcharno. + ls_font_metric-char = + cl_abap_conv_in_ce=>uccpi( ld_uccp ). + ls_font_metric-char_width = <ls_itcfc>-tdcwidths. + INSERT ls_font_metric + INTO TABLE <ls_font_cache>-th_font_metrics. + ENDLOOP. + + ENDIF. + ENDIF. + + " Calculate the cell width + " If available, use font metrics + IF lines( <ls_font_cache>-th_font_metrics ) = 0. + " Font metrics are not available + " -> Calculate the cell width using only the font size + ld_length = strlen( ld_cell_value ). + ep_width = ld_length * ld_font_height / lc_default_font_height + lc_excel_cell_padding. + + ELSE. + " Font metrics are available + + " Calculate the size of the text by adding the sizes of each + " letter + ld_length = strlen( ld_cell_value ). + DO ld_length TIMES. + " Subtract 1, because the first character is at offset 0 + ld_offset = sy-index - 1. + + " Read the current character from the cell value + ld_current_character = ld_cell_value+ld_offset(1). + + " Look up the size of the current letter + READ TABLE <ls_font_cache>-th_font_metrics + WITH TABLE KEY char = ld_current_character + ASSIGNING <ls_font_metric>. + IF sy-subrc = 0. + " The size of the letter is known + " -> Add the actual size of the letter + ADD <ls_font_metric>-char_width TO ld_width_from_font_metrics. + ELSE. + " The size of the letter is unknown + " -> Add the font height as the default letter size + ADD ld_font_height TO ld_width_from_font_metrics. + ENDIF. + ENDDO. + + " Add cell padding (Excel makes columns a bit wider than the space + " that is needed for the text itself) and convert unit + " (division by 100) + ep_width = ld_width_from_font_metrics / 100 + lc_excel_cell_padding. + ENDIF. + + " If the current cell contains an auto filter, make it a bit wider. + " The size used by the auto filter button does not depend on the font + " size. + IF ld_flag_contains_auto_filter = abap_true. + ADD 2 TO ep_width. + 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 float. + + 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. +* Do not check merged cells + IF is_cell_merged( + ip_column = <auto_size>-col_index + ip_row = count ) = abap_false. +* 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. + 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_protection TO complete_style-protection. + IF ip_xprotection IS SUPPLIED. + MOVE-CORRESPONDING ip_xprotection TO complete_stylex-protection. + ELSE. + IF ip_protection-hidden IS NOT INITIAL. + complete_stylex-protection-hidden = 'X'. + ENDIF. + IF ip_protection-locked IS NOT INITIAL. + complete_stylex-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, + + fill_gradtype_type fill-gradtype-TYPE, + fill_gradtype_degree fill-gradtype-DEGREE, + fill_gradtype_bottom fill-gradtype-BOTTOM, + fill_gradtype_left fill-gradtype-LEFT, + fill_gradtype_top fill-gradtype-TOP, + fill_gradtype_right fill-gradtype-RIGHT, + fill_gradtype_position1 fill-gradtype-POSITION1, + fill_gradtype_position2 fill-gradtype-POSITION2, + fill_gradtype_position3 fill-gradtype-POSITION3, + + + + 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' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = me->guid. + me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call + + 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 mo_pagebreaks. + 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. + + FIELD-SYMBOLS: <ls_merged_cell> LIKE LINE OF me->mt_merged_cells. + DATA: is_merged TYPE abap_bool. +*--------------------------------------------------------------------* +* If cell information is passed delete merge including this cell, +* otherwise delete all merges +*--------------------------------------------------------------------* + IF ip_cell_column IS INITIAL + OR ip_cell_row IS INITIAL. + CLEAR me->mt_merged_cells. + ELSE. + LOOP AT me->mt_merged_cells ASSIGNING <ls_merged_cell>. + + is_merged = me->is_cell_merged( ip_column = ip_cell_column + ip_row = ip_cell_row ). + IF is_merged = abap_true. + DELETE me->mt_merged_cells. " Delete this merge, that includes this cell + EXIT. + ENDIF. + + ENDLOOP. + ENDIF. + +ENDMETHOD. + + + + + + METHOD delete_row_outline. + + DELETE me->mt_row_outlines WHERE row_from = iv_row_from + AND row_to = iv_row_to. + IF sy-subrc <> 0. " didn't find outline that was to be deleted + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Row outline to be deleted does not exist'. + ENDIF. + +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. + + FIELD-SYMBOLS: <ls_merged_cell> LIKE LINE OF me->mt_merged_cells. + + DATA: lv_col_from TYPE string, + lv_col_to TYPE string, + lv_row_from TYPE string, + lv_row_to TYPE string, + lv_merge_range TYPE string. + + LOOP AT me->mt_merged_cells ASSIGNING <ls_merged_cell>. + + lv_col_from = zcl_excel_common=>convert_column2alpha( <ls_merged_cell>-col_from ). + lv_col_to = zcl_excel_common=>convert_column2alpha( <ls_merged_cell>-col_to ). + lv_row_from = <ls_merged_cell>-row_from. + lv_row_to = <ls_merged_cell>-row_to . + CONCATENATE lv_col_from lv_row_from ':' lv_col_to lv_row_to + INTO lv_merge_range. + CONDENSE lv_merge_range NO-GAPS. + APPEND lv_merge_range TO merge_range. + + ENDLOOP. + +ENDMETHOD. + + + + + method GET_PAGEBREAKS. + ro_pagebreaks = mo_pagebreaks. +endmethod. + + + + method GET_RANGES_ITERATOR. + + eo_iterator = me->ranges->get_iterator( ). + + endmethod. + + + + + METHOD GET_ROW_DIMENSION. + + FIELD-SYMBOLS: <ls_row_dimension> LIKE LINE OF me->row_dimensions. + + DATA: ls_row_dimension LIKE LINE OF me->row_dimensions. + + READ TABLE me->row_dimensions ASSIGNING <ls_row_dimension> + WITH TABLE KEY row = ip_row. + + IF NOT <ls_row_dimension> IS ASSIGNED. + CREATE OBJECT r_row_dimension + EXPORTING + ip_index = ip_row. + ls_row_dimension-row = ip_row. + ls_row_dimension-row_dimension = r_row_dimension. + INSERT ls_row_dimension INTO TABLE me->row_dimensions. + ELSE. + r_row_dimension = <ls_row_dimension>-row_dimension. + ENDIF. + +ENDMETHOD. + + + + METHOD get_row_dimensions. + + r_row_dimension[] = me->row_dimensions[]. + +ENDMETHOD. + + + + METHOD get_row_outlines. + + rt_row_outlines = me->mt_row_outlines. + +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. + TRY. + ep_value = l_value. + CATCH cx_root. + ep_value = ip_value. + ENDTRY. + ENDIF. + ENDIF. + ENDIF. + ELSE. + ep_value_type = lo_addit->get_data_type_kind( ip_value ). + ENDIF. + ENDIF. + +ENDMETHOD. + + + + + + + METHOD is_cell_merged. + + DATA: lv_column TYPE i. + + FIELD-SYMBOLS: <ls_merged_cell> LIKE LINE OF me->mt_merged_cells. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + rp_is_merged = abap_false. " Assume not in merged area + + LOOP AT me->mt_merged_cells ASSIGNING <ls_merged_cell>. + + IF <ls_merged_cell>-col_from <= lv_column + AND <ls_merged_cell>-col_to >= lv_column + AND <ls_merged_cell>-row_from <= ip_row + AND <ls_merged_cell>-row_to >= ip_row. + rp_is_merged = abap_true. " until we are proven different + RETURN. + ENDIF. + + ENDLOOP. + +ENDMETHOD. + + + method PRINT_TITLE_SET_RANGE. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmoecker, 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: ls_merge TYPE mty_merge, + lv_errormessage TYPE string. + + FIELD-SYMBOLS: <ls_merge> LIKE LINE OF me->mt_merged_cells. + +*--------------------------------------------------------------------* +* Build new range area to insert into range table +*--------------------------------------------------------------------* + ls_merge-row_from = ip_row. + IF ip_row IS SUPPLIED AND ip_row IS NOT INITIAL AND ip_row_to IS NOT SUPPLIED. + ls_merge-row_to = ls_merge-row_from. + ELSE. + ls_merge-row_to = ip_row_to. + ENDIF. + IF ls_merge-row_from > ls_merge-row_to. + lv_errormessage = 'Merge: First row larger then last row'(405). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ls_merge-col_from = zcl_excel_common=>convert_column2int( ip_column_start ). + IF ip_column_start IS SUPPLIED AND ip_column_start IS NOT INITIAL AND ip_column_end IS NOT SUPPLIED. + ls_merge-col_to = ls_merge-col_from. + ELSE. + ls_merge-col_to = zcl_excel_common=>convert_column2int( ip_column_end ). + ENDIF. + IF ls_merge-col_from > ls_merge-col_to. + lv_errormessage = 'Merge: First column larger then last column'(406). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Check merge not overlapping with existing merges +*--------------------------------------------------------------------* + LOOP AT me->mt_merged_cells TRANSPORTING NO FIELDS WHERE NOT ( row_from > ls_merge-row_to + OR row_to < ls_merge-row_from + OR col_from > ls_merge-col_to + OR col_to < ls_merge-col_from ). + lv_errormessage = 'Overlapping merges'(404). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + + ENDLOOP. + +*--------------------------------------------------------------------* +* Everything seems ok --> add to merge table +*--------------------------------------------------------------------* + INSERT ls_merge INTO TABLE me->mt_merged_cells. + +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_row_outline. + + DATA: ls_row_outline LIKE LINE OF me->mt_row_outlines. + FIELD-SYMBOLS: <ls_row_outline> LIKE LINE OF me->mt_row_outlines. + + READ TABLE me->mt_row_outlines ASSIGNING <ls_row_outline> WITH TABLE KEY row_from = iv_row_from + row_to = iv_row_to. + IF sy-subrc <> 0. + IF iv_row_from <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'First row of outline must be a positive number'. + ENDIF. + IF iv_row_to < iv_row_from. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Last row of outline may not be less than first line of outline'. + ENDIF. + ls_row_outline-row_from = iv_row_from. + ls_row_outline-row_to = iv_row_to. + INSERT ls_row_outline INTO TABLE me->mt_row_outlines ASSIGNING <ls_row_outline>. + ENDIF. + + CASE iv_collapsed. + + WHEN abap_true + OR abap_false. + <ls_row_outline>-collapsed = iv_collapsed. + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unknown collapse state'. + + ENDCASE. +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 Schmoecker, (wip ) 2012-12-08 +* - ... +* changes: aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue#243 - ' is not allowed as first character in sheet title +* - Stefan Schmoecker, 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. + + DATA: lt_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + lv_previous_row TYPE i, + lv_following_row TYPE i. + + r_collapsed = me->collapsed. + + CHECK r_collapsed = abap_false. " Maybe new method for outlines is being used + CHECK io_worksheet IS BOUND. + +* If an outline is collapsed ( even inside an outer outline ) the line following the last line +* of the group gets the flag "collapsed" + IF io_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_off. + lv_following_row = me->row_index + 1. + lt_row_outlines = io_worksheet->get_row_outlines( ). + READ TABLE lt_row_outlines TRANSPORTING NO FIELDS WITH KEY row_from = lv_following_row " first line of an outline + collapsed = abap_true. " that is collapsed + ELSE. + lv_previous_row = me->row_index - 1. + lt_row_outlines = io_worksheet->get_row_outlines( ). + READ TABLE lt_row_outlines TRANSPORTING NO FIELDS WITH KEY row_to = lv_previous_row " last line of an outline + collapsed = abap_true. " that is collapsed + ENDIF. + CHECK sy-subrc = 0. " ok - we found it + r_collapsed = abap_true. + + +ENDMETHOD. + + + + + METHOD get_outline_level. + + DATA: lt_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row. + FIELD-SYMBOLS: <ls_row_outline> LIKE LINE OF lt_row_outlines. + +* if someone has set the outline level explicitly - just use that + IF me->outline_level IS NOT INITIAL. + r_outline_level = me->outline_level. + RETURN. + ENDIF. +* Maybe we can use the outline information in the worksheet + CHECK io_worksheet IS BOUND. + + lt_row_outlines = io_worksheet->get_row_outlines( ). + LOOP AT lt_row_outlines ASSIGNING <ls_row_outline> WHERE row_from <= me->row_index + AND row_to >= me->row_index. + + ADD 1 TO r_outline_level. + + ENDLOOP. + +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. + + DATA: lt_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row. + FIELD-SYMBOLS: <ls_row_outline> LIKE LINE OF lt_row_outlines. + + r_visible = me->visible. + CHECK r_visible = 'X'. " Currently visible --> but maybe the new outline methodology will hide it implicitly + CHECK io_worksheet IS BOUND. " But we have to see the worksheet to make sure + + lt_row_outlines = io_worksheet->get_row_outlines( ). + LOOP AT lt_row_outlines ASSIGNING <ls_row_outline> WHERE row_from <= me->row_index + AND row_to >= me->row_index + AND collapsed = abap_true. " row is in a collapsed outline --> not visible + CLEAR r_visible. + RETURN. " one hit is enough to ensure invisibility + + ENDLOOP. + +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 + *"* 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_WRITER~WRITE_FILE. + me->excel = io_excel. + + ep_file = me->create( ). + endmethod. + + + + METHOD add_further_data_to_zip. +* Can be used by child classes like xlsm-writer to write additional data to zip archive +ENDMETHOD. + + + + 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( ). + + "-------------Added by Alessandro Iannacci - Only if template exist + IF lv_content IS NOT INITIAL AND me->excel->use_template EQ abap_true. + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/charts/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ELSE. "ADD CUSTOM CHART!!!! + lv_content = me->create_xl_charts( lo_drawing ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/charts/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDIF. + "------------------------------------------------- + ENDWHILE. + +* Second to last step: Allow further information put into the zip archive by child classes + me->add_further_data_to_zip( lo_zip ). + +********************************************************************** +* Last step: Create the final zip + ep_excel = lo_zip->save( ). + + endmethod. + + + + method CREATE_CONTENT_TYPES. + + +** Constant node name + DATA: lc_xml_node_types TYPE string VALUE 'Types', + lc_xml_node_override TYPE string VALUE 'Override', + 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', + " Node namespace + lc_xml_node_types_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/content-types', + " Node extension + lc_xml_node_rels_ext TYPE string VALUE 'rels', + lc_xml_node_xml_ext TYPE string VALUE 'xml', + " Node partnumber + lc_xml_node_theme_pn TYPE string VALUE '/xl/theme/theme1.xml', + lc_xml_node_styles_pn TYPE string VALUE '/xl/styles.xml', + lc_xml_node_workb_pn TYPE string VALUE '/xl/workbook.xml', + lc_xml_node_props_pn TYPE string VALUE '/docProps/app.xml', + lc_xml_node_worksheet_pn TYPE string VALUE '/xl/worksheets/sheet#.xml', + lc_xml_node_strings_pn TYPE string VALUE '/xl/sharedStrings.xml', + lc_xml_node_core_pn TYPE string VALUE '/docProps/core.xml', + lc_xml_node_chart_pn TYPE string VALUE '/xl/charts/chart#.xml', + " Node contentType + lc_xml_node_theme_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.theme+xml', + lc_xml_node_styles_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml', + lc_xml_node_workb_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml', + lc_xml_node_rels_ct TYPE string VALUE 'application/vnd.openxmlformats-package.relationships+xml', + lc_xml_node_xml_ct TYPE string VALUE 'application/xml', + lc_xml_node_props_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.extended-properties+xml', + lc_xml_node_worksheet_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml', + lc_xml_node_strings_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml', + lc_xml_node_core_ct TYPE string VALUE 'application/vnd.openxmlformats-package.core-properties+xml', + lc_xml_node_table_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml', + lc_xml_node_drawings_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.drawing+xml', + lc_xml_node_chart_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml'. + + 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 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_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. + + DATA: lv_worksheets_num TYPE i, + lv_worksheets_numc TYPE numc3, + lv_xml_node_worksheet_pn TYPE string, + lv_xml_size TYPE i, + lv_value TYPE string, + lv_drawing_index TYPE i VALUE 1, + lv_index_str TYPE string. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node types + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_types + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_types_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + " rels 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_rels_ext ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_rels_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " 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_xml_ext ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_xml_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Theme node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_theme_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_theme_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Styles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_styles_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_styles_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Workbook node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_workb_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_workb_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Properties node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_props_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_props_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Worksheet node + lv_worksheets_num = excel->get_worksheets_size( ). + DO lv_worksheets_num TIMES. + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + + MOVE sy-index TO lv_worksheets_numc. + SHIFT lv_worksheets_numc LEFT DELETING LEADING '0'. + lv_xml_node_worksheet_pn = lc_xml_node_worksheet_pn. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_worksheet_pn WITH lv_worksheets_numc. + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_xml_node_worksheet_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_worksheet_ct ). + lo_element_root->append_child( new_child = lo_element ). + ENDDO. + + lo_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + + 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_value = lo_table->get_name( ). + CONCATENATE '/xl/tables/' lv_value '.xml' INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_table_ct ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + + " Drawings + DATA: lo_drawings TYPE REF TO zcl_excel_drawings. + + lo_drawings = lo_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + lv_index_str = lv_drawing_index. + CONDENSE lv_index_str NO-GAPS. + CONCATENATE '/' me->c_xl_drawings INTO lv_value. + REPLACE '#' WITH lv_index_str INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_drawings_ct ). + lo_element_root->append_child( new_child = lo_element ). + + ADD 1 TO lv_drawing_index. + ENDIF. + ENDWHILE. + + " media mimes + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + lt_media_type TYPE TABLE OF mimetypes-extension, + lv_media_type TYPE mimetypes-extension, + lv_mime_type TYPE mimetypes-type. + + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_image ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) = abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_media_type = lo_drawing->get_media_type( ). + COLLECT lv_media_type INTO lt_media_type. + ENDWHILE. + + LOOP AT lt_media_type INTO lv_media_type. + CALL FUNCTION 'SDOK_MIMETYPE_GET' + EXPORTING + extension = lv_media_type + IMPORTING + mimetype = lv_mime_type. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_default + parent = lo_document ). + lv_value = lv_media_type. + lo_element->set_attribute_ns( name = lc_xml_attr_extension + value = lv_value ). + lv_value = lv_mime_type. + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDLOOP. + + " Charts + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_chart ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) = abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lv_index_str = lo_drawing->get_index( ). + CONDENSE lv_index_str. + lv_value = lc_xml_node_chart_pn. + REPLACE ALL OCCURRENCES OF '#' IN lv_value WITH lv_index_str. + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_chart_ct ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + + " Strings node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_strings_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_strings_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Strings node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_core_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_core_ct ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* 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( ). + + endmethod. + + + + method CREATE_DOCPROPS_APP. + + +** Constant node name + DATA: lc_xml_node_properties TYPE string VALUE 'Properties', + lc_xml_node_application TYPE string VALUE 'Application', + lc_xml_node_docsecurity TYPE string VALUE 'DocSecurity', + lc_xml_node_scalecrop TYPE string VALUE 'ScaleCrop', + lc_xml_node_headingpairs TYPE string VALUE 'HeadingPairs', + lc_xml_node_vector TYPE string VALUE 'vector', + lc_xml_node_variant TYPE string VALUE 'variant', + lc_xml_node_lpstr TYPE string VALUE 'lpstr', + lc_xml_node_i4 TYPE string VALUE 'i4', + lc_xml_node_titlesofparts TYPE string VALUE 'TitlesOfParts', + lc_xml_node_company TYPE string VALUE 'Company', + lc_xml_node_linksuptodate TYPE string VALUE 'LinksUpToDate', + lc_xml_node_shareddoc TYPE string VALUE 'SharedDoc', + lc_xml_node_hyperlinkschanged TYPE string VALUE 'HyperlinksChanged', + lc_xml_node_appversion TYPE string VALUE 'AppVersion', + " Namespace prefix + lc_vt_ns TYPE string VALUE 'vt', + lc_xml_node_props_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties', + lc_xml_node_props_vt_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes', + " Node attributes + lc_xml_attr_size TYPE string VALUE 'size', + lc_xml_attr_basetype TYPE string VALUE 'baseType'. + + 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 TYPE REF TO if_ixml_element, + lo_sub_element_vector TYPE REF TO if_ixml_element, + lo_sub_element_variant TYPE REF TO if_ixml_element, + lo_sub_element_lpstr TYPE REF TO if_ixml_element, + lo_sub_element_i4 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_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: lv_value TYPE string. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node properties + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_properties + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_props_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:vt' + value = lc_xml_node_props_vt_ns ). + +********************************************************************** +* STEP 4: Create subnodes + " Application + lo_element = lo_document->create_simple_element( name = lc_xml_node_application + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~application. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " DocSecurity + lo_element = lo_document->create_simple_element( name = lc_xml_node_docsecurity + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~docsecurity. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " ScaleCrop + lo_element = lo_document->create_simple_element( name = lc_xml_node_scalecrop + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~scalecrop ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " HeadingPairs + lo_element = lo_document->create_simple_element( name = lc_xml_node_headingpairs + parent = lo_document ). + + + " * vector node + lo_sub_element_vector = lo_document->create_simple_element_ns( name = lc_xml_node_vector + prefix = lc_vt_ns + parent = lo_document ). + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_size + value = '2' ). + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_basetype + value = lc_xml_node_variant ). + + " ** variant node + lo_sub_element_variant = lo_document->create_simple_element_ns( name = lc_xml_node_variant + prefix = lc_vt_ns + parent = lo_document ). + + " *** lpstr node + lo_sub_element_lpstr = lo_document->create_simple_element_ns( name = lc_xml_node_lpstr + prefix = lc_vt_ns + parent = lo_document ). + lv_value = excel->get_worksheets_name( ). + lo_sub_element_lpstr->set_value( value = lv_value ). + lo_sub_element_variant->append_child( new_child = lo_sub_element_lpstr ). " lpstr node + + lo_sub_element_vector->append_child( new_child = lo_sub_element_variant ). " variant node + + " ** variant node + lo_sub_element_variant = lo_document->create_simple_element_ns( name = lc_xml_node_variant + prefix = lc_vt_ns + parent = lo_document ). + + " *** i4 node + lo_sub_element_i4 = lo_document->create_simple_element_ns( name = lc_xml_node_i4 + prefix = lc_vt_ns + parent = lo_document ). + lv_value = excel->get_worksheets_size( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_i4->set_value( value = lv_value ). + lo_sub_element_variant->append_child( new_child = lo_sub_element_i4 ). " lpstr node + + lo_sub_element_vector->append_child( new_child = lo_sub_element_variant ). " variant node + + lo_element->append_child( new_child = lo_sub_element_vector ). " vector node + + lo_element_root->append_child( new_child = lo_element ). " HeadingPairs + + + " TitlesOfParts + lo_element = lo_document->create_simple_element( name = lc_xml_node_titlesofparts + parent = lo_document ). + + + " * vector node + lo_sub_element_vector = lo_document->create_simple_element_ns( name = lc_xml_node_vector + prefix = lc_vt_ns + parent = lo_document ). + lv_value = excel->get_worksheets_size( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_size + value = lv_value ). + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_basetype + value = lc_xml_node_lpstr ). + + lo_iterator = excel->get_worksheets_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + " ** lpstr node + lo_sub_element_lpstr = lo_document->create_simple_element_ns( name = lc_xml_node_lpstr + prefix = lc_vt_ns + parent = lo_document ). + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_value = lo_worksheet->get_title( ). + lo_sub_element_lpstr->set_value( value = lv_value ). + lo_sub_element_vector->append_child( new_child = lo_sub_element_lpstr ). " lpstr node + ENDWHILE. + + lo_element->append_child( new_child = lo_sub_element_vector ). " vector node + + lo_element_root->append_child( new_child = lo_element ). " TitlesOfParts + + + + " Company + IF excel->zif_excel_book_properties~company IS NOT INITIAL. + lo_element = lo_document->create_simple_element( name = lc_xml_node_company + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~company. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + " LinksUpToDate + lo_element = lo_document->create_simple_element( name = lc_xml_node_linksuptodate + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~linksuptodate ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " SharedDoc + lo_element = lo_document->create_simple_element( name = lc_xml_node_shareddoc + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~shareddoc ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " HyperlinksChanged + lo_element = lo_document->create_simple_element( name = lc_xml_node_hyperlinkschanged + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~hyperlinkschanged ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " AppVersion + lo_element = lo_document->create_simple_element( name = lc_xml_node_appversion + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~appversion. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* 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( ). + + endmethod. + + + + method CREATE_DOCPROPS_CORE. + + +** Constant node name + DATA: lc_xml_node_coreproperties TYPE string VALUE 'coreProperties', + lc_xml_node_creator TYPE string VALUE 'creator', + lc_xml_node_description TYPE string VALUE 'description', + lc_xml_node_lastmodifiedby TYPE string VALUE 'lastModifiedBy', + lc_xml_node_created TYPE string VALUE 'created', + lc_xml_node_modified TYPE string VALUE 'modified', + " Node attributes + lc_xml_attr_type TYPE string VALUE 'type', + lc_xml_attr_target TYPE string VALUE 'dcterms:W3CDTF', + " Node namespace + lc_cp_ns TYPE string VALUE 'cp', + lc_dc_ns TYPE string VALUE 'dc', + lc_dcterms_ns TYPE string VALUE 'dcterms', +* lc_dcmitype_ns TYPE string VALUE 'dcmitype', + lc_xsi_ns TYPE string VALUE 'xsi', + lc_xml_node_cp_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties', + lc_xml_node_dc_ns TYPE string VALUE 'http://purl.org/dc/elements/1.1/', + lc_xml_node_dcterms_ns TYPE string VALUE 'http://purl.org/dc/terms/', + lc_xml_node_dcmitype_ns TYPE string VALUE 'http://purl.org/dc/dcmitype/', + lc_xml_node_xsi_ns TYPE string VALUE 'http://www.w3.org/2001/XMLSchema-instance'. + + 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 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. + + DATA: lv_value TYPE string, + lv_date TYPE sydatum, + lv_time TYPE syuzeit. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node coreProperties + lo_element_root = lo_document->create_simple_element_ns( name = lc_xml_node_coreproperties + prefix = lc_cp_ns + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns:cp' + value = lc_xml_node_cp_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:dc' + value = lc_xml_node_dc_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:dcterms' + value = lc_xml_node_dcterms_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:dcmitype' + value = lc_xml_node_dcmitype_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:xsi' + value = lc_xml_node_xsi_ns ). + +********************************************************************** +* STEP 4: Create subnodes + " Creator node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_creator + prefix = lc_dc_ns + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~creator. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " Description node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_description + prefix = lc_dc_ns + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~description. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " lastModifiedBy node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_lastmodifiedby + prefix = lc_cp_ns + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~lastmodifiedby. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " Created node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_created + prefix = lc_dcterms_ns + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + prefix = lc_xsi_ns + value = lc_xml_attr_target ). + + CONVERT TIME STAMP excel->zif_excel_book_properties~created TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time. + CONCATENATE lv_date lv_time INTO lv_value RESPECTING BLANKS. + REPLACE ALL OCCURRENCES OF REGEX '([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})' IN lv_value WITH '$1-$2-$3T$4:$5:$6Z'. +* lv_value = excel->zif_excel_book_properties~created. +* lv_value = '2010-07-04T14:58:53Z'. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " Modified node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_modified + prefix = lc_dcterms_ns + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + prefix = lc_xsi_ns + value = lc_xml_attr_target ). + CONVERT TIME STAMP excel->zif_excel_book_properties~modified TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time. + CONCATENATE lv_date lv_time INTO lv_value RESPECTING BLANKS. + REPLACE ALL OCCURRENCES OF REGEX '([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})' IN lv_value WITH '$1-$2-$3T$4:$5:$6Z'. +* lv_value = excel->zif_excel_book_properties~modified. +* lv_value = '2010-07-04T14:58:53Z'. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* 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( ). + + endmethod. + + + + + + + + + + METHOD create_dxf_style. + + CONSTANTS: lc_xml_node_dxf TYPE string VALUE 'dxf', + 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_attr_val TYPE string VALUE 'val', + lc_xml_node_fill TYPE string VALUE 'fill', + lc_xml_node_patternfill TYPE string VALUE 'patternFill', + lc_xml_attr_patterntype TYPE string VALUE 'patternType', + lc_xml_node_fgcolor TYPE string VALUE 'fgColor', + lc_xml_node_bgcolor TYPE string VALUE 'bgColor', + y TYPE i VALUE 0. + + DATA: ls_styles_mapping TYPE zexcel_s_styles_mapping, + ls_cellxfs TYPE zexcel_s_cellxfs, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + lo_sub_element TYPE REF TO if_ixml_element, + lo_sub_element_2 TYPE REF TO if_ixml_element, + lv_index TYPE i, + ls_font TYPE zexcel_s_style_font, + lo_element_font TYPE REF TO if_ixml_element, + lv_value TYPE string, + ls_fill TYPE zexcel_s_style_fill, + lo_element_fill TYPE REF TO if_ixml_element, + x. + + CHECK iv_cell_style IS NOT INITIAL. + + READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = iv_cell_style. + ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 + READ TABLE it_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 = iv_cell_style. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ELSE. + ls_style_cond_mapping-guid = iv_cell_style. + ls_style_cond_mapping-style = ls_styles_mapping-style. + ls_style_cond_mapping-dxf = cv_dfx_count. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ADD 1 TO cv_dfx_count. + + " dxf node + lo_sub_element = io_ixml_document->create_simple_element( name = lc_xml_node_dxf + parent = io_ixml_document ). + + "Conditional formatting font style correction by Alessandro Iannacci START + lv_index = ls_cellxfs-fontid + 1. + READ TABLE it_fonts INTO ls_font INDEX lv_index. + IF ls_font IS NOT INITIAL. + lo_element_font = io_ixml_document->create_simple_element( name = lc_xml_node_font + parent = io_ixml_document ). + IF ls_font-bold EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_b + parent = io_ixml_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-italic EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_i + parent = io_ixml_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-underline EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_u + parent = io_ixml_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 = io_ixml_document->create_simple_element( name = lc_xml_node_strike + parent = io_ixml_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + "color + create_xl_styles_color_node( + io_document = io_ixml_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 it_fills INTO ls_fill INDEX ls_cellxfs-fillid. + IF ls_fill IS NOT INITIAL. + " fill properties + lo_element_fill = io_ixml_document->create_simple_element( name = lc_xml_node_fill + parent = io_ixml_document ). + "pattern + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_patternfill + parent = io_ixml_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 = io_ixml_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + IF ls_fill-fgcolor-rgb IS INITIAL AND + ls_fill-fgcolor-indexed EQ zcl_excel_style_color=>c_indexed_not_set AND + ls_fill-fgcolor-theme EQ zcl_excel_style_color=>c_theme_not_set AND + ls_fill-fgcolor-tint IS INITIAL AND ls_fill-bgcolor-indexed EQ zcl_excel_style_color=>c_indexed_sys_foreground. + + " bgcolor + create_xl_styles_color_node( + io_document = io_ixml_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + ENDIF. + + lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern + + lo_sub_element->append_child( new_child = lo_element_fill ). + ENDIF. + ENDIF. + + io_dxf_element->append_child( new_child = lo_sub_element ). +ENDMETHOD. + + + + method CREATE_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 namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + " Node id + lc_xml_node_rId1_id TYPE string VALUE 'rId1', + lc_xml_node_rId2_id TYPE string VALUE 'rId2', + lc_xml_node_rId3_id TYPE string VALUE 'rId3', + " Node type + lc_xml_node_rId1_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', + lc_xml_node_rId2_tp TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + lc_xml_node_rId3_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', + " Node target + lc_xml_node_rId1_tg TYPE string VALUE 'xl/workbook.xml', + lc_xml_node_rId2_tg TYPE string VALUE 'docProps/core.xml', + lc_xml_node_rId3_tg TYPE string VALUE 'docProps/app.xml'. + + 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 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. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + " Theme node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lc_xml_node_rId3_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rId3_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rId3_tg ). + lo_element_root->append_child( new_child = lo_element ). + + " Styles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lc_xml_node_rId2_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rId2_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rId2_tg ). + lo_element_root->append_child( new_child = lo_element ). + + " rels node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lc_xml_node_rId1_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rId1_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rId1_tg ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* 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( ). + + endmethod. + + + + + method CREATE_XL_CHARTS. + + +** Constant node name + CONSTANTS: lc_xml_node_chartspace TYPE string VALUE 'c:chartSpace', + lc_xml_node_ns_c TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/chart', + lc_xml_node_ns_a TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/main', + lc_xml_node_ns_r TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + lc_xml_node_date1904 TYPE string VALUE 'c:date1904', + lc_xml_node_lang TYPE string VALUE 'c:lang', + lc_xml_node_roundedcorners TYPE string VALUE 'c:roundedCorners', + lc_xml_node_altcont TYPE string VALUE 'mc:AlternateContent', + lc_xml_node_altcont_ns_mc TYPE string VALUE 'http://schemas.openxmlformats.org/markup-compatibility/2006', + lc_xml_node_choice TYPE string VALUE 'mc:Choice', + lc_xml_node_choice_ns_requires TYPE string VALUE 'c14', + lc_xml_node_choice_ns_c14 TYPE string VALUE 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart', + lc_xml_node_style TYPE string VALUE 'c14:style', + lc_xml_node_fallback TYPE string VALUE 'mc:Fallback', + lc_xml_node_style2 TYPE string VALUE 'c:style', + + "---------------------------CHART + lc_xml_node_chart TYPE string VALUE 'c:chart', + lc_xml_node_autotitledeleted TYPE string VALUE 'c:autoTitleDeleted', + "plotArea + lc_xml_node_plotarea TYPE string VALUE 'c:plotArea', + lc_xml_node_layout TYPE string VALUE 'c:layout', + lc_xml_node_varycolors TYPE string VALUE 'c:varyColors', + lc_xml_node_ser TYPE string VALUE 'c:ser', + lc_xml_node_idx TYPE string VALUE 'c:idx', + lc_xml_node_order TYPE string VALUE 'c:order', + lc_xml_node_tx TYPE string VALUE 'c:tx', + lc_xml_node_v TYPE string VALUE 'c:v', + lc_xml_node_val TYPE string VALUE 'c:val', + lc_xml_node_cat TYPE string VALUE 'c:cat', + lc_xml_node_numref TYPE string VALUE 'c:numRef', + lc_xml_node_strref TYPE string VALUE 'c:strRef', + lc_xml_node_f TYPE string VALUE 'c:f', "this is the range + "note: numcache avoided + lc_xml_node_dlbls TYPE string VALUE 'c:dLbls', + lc_xml_node_showlegendkey TYPE string VALUE 'c:showLegendKey', + lc_xml_node_showval TYPE string VALUE 'c:showVal', + lc_xml_node_showcatname TYPE string VALUE 'c:showCatName', + lc_xml_node_showsername TYPE string VALUE 'c:showSerName', + lc_xml_node_showpercent TYPE string VALUE 'c:showPercent', + lc_xml_node_showbubblesize TYPE string VALUE 'c:showBubbleSize', + "plotArea->pie + lc_xml_node_piechart TYPE string VALUE 'c:pieChart', + lc_xml_node_showleaderlines TYPE string VALUE 'c:showLeaderLines', + lc_xml_node_firstsliceang TYPE string VALUE 'c:firstSliceAng', + "plotArea->line + lc_xml_node_linechart TYPE string VALUE 'c:lineChart', + lc_xml_node_symbol TYPE string VALUE 'c:symbol', + lc_xml_node_marker TYPE string VALUE 'c:marker', + lc_xml_node_smooth TYPE string VALUE 'c:smooth', + "plotArea->bar + lc_xml_node_invertifnegative TYPE string VALUE 'c:invertIfNegative', + lc_xml_node_barchart TYPE string VALUE 'c:barChart', + lc_xml_node_bardir TYPE string VALUE 'c:barDir', + lc_xml_node_gapwidth TYPE string VALUE 'c:gapWidth', + "plotArea->line + plotArea->bar + lc_xml_node_grouping TYPE string VALUE 'c:grouping', + lc_xml_node_axid TYPE string VALUE 'c:axId', + lc_xml_node_catax TYPE string VALUE 'c:catAx', + lc_xml_node_valax TYPE string VALUE 'c:valAx', + lc_xml_node_scaling TYPE string VALUE 'c:scaling', + lc_xml_node_orientation TYPE string VALUE 'c:orientation', + lc_xml_node_delete TYPE string VALUE 'c:delete', + lc_xml_node_axpos TYPE string VALUE 'c:axPos', + lc_xml_node_numfmt TYPE string VALUE 'c:numFmt', + lc_xml_node_majorgridlines TYPE string VALUE 'c:majorGridlines', + lc_xml_node_majortickmark TYPE string VALUE 'c:majorTickMark', + lc_xml_node_minortickmark TYPE string VALUE 'c:minorTickMark', + lc_xml_node_ticklblpos TYPE string VALUE 'c:tickLblPos', + lc_xml_node_crossax TYPE string VALUE 'c:crossAx', + lc_xml_node_crosses TYPE string VALUE 'c:crosses', + lc_xml_node_auto TYPE string VALUE 'c:auto', + lc_xml_node_lblalgn TYPE string VALUE 'c:lblAlgn', + lc_xml_node_lbloffset TYPE string VALUE 'c:lblOffset', + lc_xml_node_nomultilvllbl TYPE string VALUE 'c:noMultiLvlLbl', + lc_xml_node_crossbetween TYPE string VALUE 'c:crossBetween', + "legend + lc_xml_node_legend TYPE string VALUE 'c:legend', + "legend->pie + lc_xml_node_legendpos TYPE string VALUE 'c:legendPos', +* lc_xml_node_layout TYPE string VALUE 'c:layout', "already exist + lc_xml_node_overlay TYPE string VALUE 'c:overlay', + lc_xml_node_txpr TYPE string VALUE 'c:txPr', + lc_xml_node_bodypr TYPE string VALUE 'a:bodyPr', + lc_xml_node_lststyle TYPE string VALUE 'a:lstStyle', + lc_xml_node_p TYPE string VALUE 'a:p', + lc_xml_node_ppr TYPE string VALUE 'a:pPr', + lc_xml_node_defrpr TYPE string VALUE 'a:defRPr', + lc_xml_node_endpararpr TYPE string VALUE 'a:endParaRPr', + "legend->bar + legend->line + lc_xml_node_plotvisonly TYPE string VALUE 'c:plotVisOnly', + lc_xml_node_dispblanksas TYPE string VALUE 'c:dispBlanksAs', + lc_xml_node_showdlblsovermax TYPE string VALUE 'c:showDLblsOverMax', + "---------------------------END OF CHART + + lc_xml_node_printsettings TYPE string VALUE 'c:printSettings', + lc_xml_node_headerfooter TYPE string VALUE 'c:headerFooter', + lc_xml_node_pagemargins TYPE string VALUE 'c:pageMargins', + lc_xml_node_pagesetup TYPE string VALUE 'c:pageSetup'. + + + 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_cellanchor 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. + DATA: lv_rel_id TYPE i. + + DATA lo_element TYPE REF TO if_ixml_element. + DATA lo_element2 TYPE REF TO if_ixml_element. + DATA lo_element3 TYPE REF TO if_ixml_element. + DATA lo_el_rootchart TYPE REF TO if_ixml_element. + DATA lo_element4 TYPE REF TO if_ixml_element. + DATA lo_element5 TYPE REF TO if_ixml_element. + DATA lo_element6 TYPE REF TO if_ixml_element. + DATA lo_element7 TYPE REF TO if_ixml_element. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_chartspace + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns:c' + value = lc_xml_node_ns_c ). + lo_element_root->set_attribute_ns( name = 'xmlns:a' + value = lc_xml_node_ns_a ). + lo_element_root->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_ns_r ). + +********************************************************************** +* STEP 4: Create chart + + DATA lo_chartb TYPE REF TO zcl_excel_graph_bars. + DATA lo_chartp TYPE REF TO zcl_excel_graph_pie. + DATA lo_chartl TYPE REF TO zcl_excel_graph_line. + DATA lo_chart TYPE REF TO zcl_excel_graph. + + DATA ls_serie TYPE zcl_excel_graph=>s_series. + DATA ls_ax TYPE zcl_excel_graph_bars=>s_ax. + DATA lv_str TYPE string. + + "Identify chart type + CASE io_drawing->graph_type. + WHEN zcl_excel_drawing=>c_graph_bars. + lo_chartb ?= io_drawing->graph. + WHEN zcl_excel_drawing=>c_graph_pie. + lo_chartp ?= io_drawing->graph. + WHEN zcl_excel_drawing=>c_graph_line. + lo_chartl ?= io_drawing->graph. + WHEN OTHERS. + ENDCASE. + + + lo_chart = io_drawing->graph. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_date1904 + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'val' + value = lo_chart->ns_1904val ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_lang + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'val' + value = lo_chart->ns_langval ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_roundedcorners + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'val' + value = lo_chart->ns_roundedcornersval ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_altcont + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'xmlns:mc' + value = lc_xml_node_altcont_ns_mc ). + + "Choice + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_choice + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'Requires' + value = lc_xml_node_choice_ns_requires ). + lo_element2->set_attribute_ns( name = 'xmlns:c14' + value = lc_xml_node_choice_ns_c14 ). + + "C14:style + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_style + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chart->ns_c14styleval ). + + "Fallback + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_fallback + parent = lo_element ). + + "C:style + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_style2 + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chart->ns_styleval ). + + "---------------------------CHART + lo_element = lo_document->create_simple_element( name = lc_xml_node_chart + parent = lo_element_root ). + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_autotitledeleted + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_autotitledeletedval ). + + "plotArea + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_plotarea + parent = lo_element ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + CASE io_drawing->graph_type. + WHEN zcl_excel_drawing=>c_graph_bars. + "----bar + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_barchart + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_bardir + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_bardirval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_grouping + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_groupingval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_varycolors + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_varycolorsval ). + + "series + LOOP AT lo_chartb->series INTO ls_serie. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ser + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_idx + parent = lo_element4 ). + IF ls_serie-idx IS NOT INITIAL. + lv_str = ls_serie-idx. + ELSE. + lv_str = sy-tabix - 1. + ENDIF. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_order + parent = lo_element4 ). + lv_str = ls_serie-order. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + IF ls_serie-sername IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_tx + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_element5 ). + lo_element6->set_value( value = ls_serie-sername ). + ENDIF. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_invertifnegative + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_serie-invertifnegative ). + IF ls_serie-lbl IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_cat + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_strref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-lbl ). + ENDIF. + IF ls_serie-ref IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_val + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_numref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-ref ). + ENDIF. + ENDLOOP. + "endseries + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_dlbls + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showlegendkey + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showlegendkeyval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showval + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showvalval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showcatname + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showcatnameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showsername + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showsernameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showpercent + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showpercentval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showbubblesize + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showbubblesizeval ). + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_gapwidth + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_gapwidthval ). + + "axes + lo_el_rootchart = lo_element3. + LOOP AT lo_chartb->axes INTO ls_ax. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_el_rootchart ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + CASE ls_ax-type. + WHEN zcl_excel_graph_bars=>c_catax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_catax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'formatCode' + value = ls_ax-formatcode ). + lo_element4->set_attribute_ns( name = 'sourceLinked' + value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_auto + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-auto ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lblalgn + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lblalgn ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lbloffset + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lbloffset ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_nomultilvllbl + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-nomultilvllbl ). + WHEN zcl_excel_graph_bars=>c_valax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_valax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majorgridlines + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'formatCode' + value = ls_ax-formatcode ). + lo_element4->set_attribute_ns( name = 'sourceLinked' + value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossbetween + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossbetween ). + WHEN OTHERS. + ENDCASE. + ENDLOOP. + "endaxes + + WHEN zcl_excel_drawing=>c_graph_pie. + "----pie + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_piechart + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_varycolors + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartp->ns_varycolorsval ). + + "series + LOOP AT lo_chartp->series INTO ls_serie. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ser + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_idx + parent = lo_element4 ). + IF ls_serie-idx IS NOT INITIAL. + lv_str = ls_serie-idx. + ELSE. + lv_str = sy-tabix - 1. + ENDIF. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_order + parent = lo_element4 ). + lv_str = ls_serie-order. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + IF ls_serie-sername IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_tx + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_element5 ). + lo_element6->set_value( value = ls_serie-sername ). + ENDIF. + IF ls_serie-lbl IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_cat + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_strref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-lbl ). + ENDIF. + IF ls_serie-ref IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_val + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_numref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-ref ). + ENDIF. + ENDLOOP. + "endseries + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_dlbls + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showlegendkey + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showlegendkeyval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showval + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showvalval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showcatname + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showcatnameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showsername + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showsernameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showpercent + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showpercentval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showbubblesize + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showbubblesizeval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showleaderlines + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showleaderlinesval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_firstsliceang + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartp->ns_firstsliceangval ). + WHEN zcl_excel_drawing=>c_graph_line. + "----line + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_linechart + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_grouping + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->ns_groupingval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_varycolors + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->ns_varycolorsval ). + + "series + LOOP AT lo_chartl->series INTO ls_serie. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ser + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_idx + parent = lo_element4 ). + IF ls_serie-idx IS NOT INITIAL. + lv_str = ls_serie-idx. + ELSE. + lv_str = sy-tabix - 1. + ENDIF. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_order + parent = lo_element4 ). + lv_str = ls_serie-order. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + IF ls_serie-sername IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_tx + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_element5 ). + lo_element6->set_value( value = ls_serie-sername ). + ENDIF. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_marker + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_symbol + parent = lo_element5 ). + lo_element6->set_attribute_ns( name = 'val' + value = ls_serie-symbol ). + IF ls_serie-lbl IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_cat + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_strref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-lbl ). + ENDIF. + IF ls_serie-ref IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_val + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_numref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-ref ). + ENDIF. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_smooth + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_serie-smooth ). + ENDLOOP. + "endseries + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_dlbls + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showlegendkey + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showlegendkeyval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showval + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showvalval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showcatname + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showcatnameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showsername + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showsernameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showpercent + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showpercentval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showbubblesize + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showbubblesizeval ). + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_marker + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->NS_MARKERVAL ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_smooth + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->NS_SMOOTHVAL ). + + "axes + lo_el_rootchart = lo_element3. + LOOP AT lo_chartl->axes INTO ls_ax. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_el_rootchart ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + CASE ls_ax-type. + WHEN zcl_excel_graph_line=>c_catax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_catax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). +* lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt +* parent = lo_element3 ). +* lo_element4->set_attribute_ns( name = 'formatCode' +* value = ls_ax-formatcode ). +* lo_element4->set_attribute_ns( name = 'sourceLinked' +* value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_auto + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-auto ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lblalgn + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lblalgn ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lbloffset + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lbloffset ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_nomultilvllbl + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-nomultilvllbl ). + WHEN zcl_excel_graph_line=>c_valax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_valax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majorgridlines + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'formatCode' + value = ls_ax-formatcode ). + lo_element4->set_attribute_ns( name = 'sourceLinked' + value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossbetween + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossbetween ). + WHEN OTHERS. + ENDCASE. + ENDLOOP. + "endaxes + + WHEN OTHERS. + ENDCASE. + + "legend + IF lo_chart->print_label EQ abap_true. + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_legend + parent = lo_element ). + CASE io_drawing->graph_type. + WHEN zcl_excel_drawing=>c_graph_bars. + "----bar + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_legendpos + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartb->ns_legendposval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_overlay + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartb->ns_overlayval ). + WHEN zcl_excel_drawing=>c_graph_line. + "----line + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_legendpos + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartl->ns_legendposval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_overlay + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartl->ns_overlayval ). + WHEN zcl_excel_drawing=>c_graph_pie. + "----pie + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_legendpos + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartp->ns_legendposval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_overlay + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartp->ns_overlayval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_txpr + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_bodypr + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lststyle + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_p + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_ppr + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'rtl' + value = lo_chartp->ns_pprrtl ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_defrpr + parent = lo_element5 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_endpararpr + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'lang' + value = lo_chartp->ns_endpararprlang ). + WHEN OTHERS. + ENDCASE. + ENDIF. + + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_plotvisonly + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_plotvisonlyval ). + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_dispblanksas + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_dispblanksasval ). + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_showdlblsovermax + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_showdlblsovermaxval ). + "---------------------------END OF CHART + + "printSettings + lo_element = lo_document->create_simple_element( name = lc_xml_node_printsettings + parent = lo_element_root ). + "headerFooter + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_headerfooter + parent = lo_element ). + "pageMargins + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_pagemargins + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'b' + value = lo_chart->pagemargins-b ). + lo_element2->set_attribute_ns( name = 'l' + value = lo_chart->pagemargins-l ). + lo_element2->set_attribute_ns( name = 'r' + value = lo_chart->pagemargins-r ). + lo_element2->set_attribute_ns( name = 't' + value = lo_chart->pagemargins-t ). + lo_element2->set_attribute_ns( name = 'header' + value = lo_chart->pagemargins-header ). + lo_element2->set_attribute_ns( name = 'footer' + value = lo_chart->pagemargins-footer ). + "pageSetup + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_pagesetup + parent = lo_element ). + +********************************************************************** +* 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( ). + + endmethod. + + + + + method CREATE_XL_DRAWINGS. + + +** Constant node name + CONSTANTS: lc_xml_node_wsdr TYPE string VALUE 'xdr:wsDr', + lc_xml_node_ns_xdr TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing', + lc_xml_node_ns_a TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/main'. + + CONSTANTS: lc_on TYPE string VALUE '1', + lc_off TYPE string VALUE '0'. + + 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_cellanchor 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_drawings TYPE REF TO zcl_excel_drawings, + lo_drawing TYPE REF TO zcl_excel_drawing. + DATA: lv_rel_id TYPE i. + + + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_wsdr + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns:xdr' + value = lc_xml_node_ns_xdr ). + lo_element_root->set_attribute_ns( name = 'xmlns:a' + value = lc_xml_node_ns_a ). + +********************************************************************** +* STEP 4: Create drawings + + CLEAR: lv_rel_id. + + lo_drawings = io_worksheet->get_drawings( ). + + lo_iterator = lo_drawings->get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + ADD 1 TO lv_rel_id. + lo_element_cellanchor = me->create_xl_drawing_anchor( + io_drawing = lo_drawing + io_document = lo_document + ip_index = lv_rel_id ). + + lo_element_root->append_child( new_child = lo_element_cellanchor ). + + ENDWHILE. + +********************************************************************** +* 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( ). + + endmethod. + + + + + method CREATE_XL_DRAWINGS_RELS. + +** 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 namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + lc_xml_node_rid_image_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + lc_xml_node_rid_chart_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart'. + + 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 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_drawings TYPE REF TO zcl_excel_drawings, + lo_drawing TYPE REF TO zcl_excel_drawing. + + DATA: lv_value TYPE string, + lv_counter TYPE i. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + " Add sheet Relationship nodes here + lv_counter = 0. + lo_drawings = io_worksheet->get_drawings( ). + lo_iterator = lo_drawings->get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + ADD 1 TO lv_counter. + + lv_value = lv_counter. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + + lv_value = lo_drawing->get_media_name( ). + CASE lo_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. + CONCATENATE '../media/' lv_value INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_image_tp ). + + WHEN zcl_excel_drawing=>type_chart. + CONCATENATE '../charts/' lv_value INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_chart_tp ). + + ENDCASE. + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + + +********************************************************************** +* 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( ). + + endmethod. + + + + + + + method CREATE_XL_DRAWING_ANCHOR. + +** Constant node name + CONSTANTS: lc_xml_node_onecellanchor TYPE string VALUE 'xdr:oneCellAnchor', + lc_xml_node_twocellanchor TYPE string VALUE 'xdr:twoCellAnchor', + lc_xml_node_from TYPE string VALUE 'xdr:from', + lc_xml_node_to TYPE string VALUE 'xdr:to', + lc_xml_node_pic TYPE string VALUE 'xdr:pic', + lc_xml_node_ext TYPE string VALUE 'xdr:ext', + lc_xml_node_clientdata TYPE string VALUE 'xdr:clientData', + + lc_xml_node_col TYPE string VALUE 'xdr:col', + lc_xml_node_coloff TYPE string VALUE 'xdr:colOff', + lc_xml_node_row TYPE string VALUE 'xdr:row', + lc_xml_node_rowoff TYPE string VALUE 'xdr:rowOff', + + lc_xml_node_nvpicpr TYPE string VALUE 'xdr:nvPicPr', + lc_xml_node_cnvpr TYPE string VALUE 'xdr:cNvPr', + lc_xml_node_cnvpicpr TYPE string VALUE 'xdr:cNvPicPr', + lc_xml_node_piclocks TYPE string VALUE 'a:picLocks', + + lc_xml_node_sppr TYPE string VALUE 'xdr:spPr', + lc_xml_node_apgeom TYPE string VALUE 'a:prstGeom', + lc_xml_node_aavlst TYPE string VALUE 'a:avLst', + + lc_xml_node_graphicframe TYPE string VALUE 'xdr:graphicFrame', + lc_xml_node_nvgraphicframepr TYPE string VALUE 'xdr:nvGraphicFramePr', + lc_xml_node_cnvgraphicframepr TYPE string VALUE 'xdr:cNvGraphicFramePr', + lc_xml_node_graphicframelocks TYPE string VALUE 'a:graphicFrameLocks', + lc_xml_node_xfrm TYPE string VALUE 'xdr:xfrm', + lc_xml_node_aoff TYPE string VALUE 'a:off', + lc_xml_node_aext TYPE string VALUE 'a:ext', + lc_xml_node_agraphic TYPE string VALUE 'a:graphic', + lc_xml_node_agraphicdata TYPE string VALUE 'a:graphicData', + + lc_xml_node_ns_c TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/chart', + lc_xml_node_cchart TYPE string VALUE 'c:chart', + + lc_xml_node_blipfill TYPE string VALUE 'xdr:blipFill', + lc_xml_node_ablip TYPE string VALUE 'a:blip', + lc_xml_node_astretch TYPE string VALUE 'a:stretch', + lc_xml_node_ns_r TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'. + + + CONSTANTS: lc_on TYPE string VALUE '1', + lc_off TYPE string VALUE '0'. + + DATA: lo_element_graphicframe TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_element2 TYPE REF TO if_ixml_element, + lo_element3 TYPE REF TO if_ixml_element, + lo_element_from TYPE REF TO if_ixml_element, + lo_element_to TYPE REF TO if_ixml_element, + lo_element_ext TYPE REF TO if_ixml_element, + lo_element_pic TYPE REF TO if_ixml_element, + lo_element_clientdata TYPE REF TO if_ixml_element, + + ls_position TYPE zexcel_drawing_position, + + lv_col TYPE string, " zexcel_cell_column, + lv_row TYPE string, " zexcel_cell_row. + lv_col_offset TYPE string, + lv_row_offset TYPE string, + lv_value TYPE string. + + ls_position = io_drawing->get_position( ). + + IF ls_position-anchor = 'ONE'. + ep_anchor = io_document->create_simple_element( name = lc_xml_node_onecellanchor + parent = io_document ). + ELSE. + ep_anchor = io_document->create_simple_element( name = lc_xml_node_twocellanchor + parent = io_document ). + ENDIF. + +* from cell ****************************** + lo_element_from = io_document->create_simple_element( name = lc_xml_node_from + parent = io_document ). + + lv_col = ls_position-from-col. + lv_row = ls_position-from-row. + lv_col_offset = ls_position-from-col_offset. + lv_row_offset = ls_position-from-row_offset. + CONDENSE lv_col NO-GAPS. + CONDENSE lv_row NO-GAPS. + CONDENSE lv_col_offset NO-GAPS. + CONDENSE lv_row_offset NO-GAPS. + + lo_element = io_document->create_simple_element( name = lc_xml_node_col + parent = io_document ). + lo_element->set_value( value = lv_col ). + lo_element_from->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_coloff + parent = io_document ). + lo_element->set_value( value = lv_col_offset ). + lo_element_from->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_row + parent = io_document ). + lo_element->set_value( value = lv_row ). + lo_element_from->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_rowoff + parent = io_document ). + lo_element->set_value( value = lv_row_offset ). + lo_element_from->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_from ). + + IF ls_position-anchor = 'ONE'. + +* ext ****************************** + lo_element_ext = io_document->create_simple_element( name = lc_xml_node_ext + parent = io_document ). + + lv_value = io_drawing->get_width_emu_str( ). + lo_element_ext->set_attribute_ns( name = 'cx' + value = lv_value ). + lv_value = io_drawing->get_height_emu_str( ). + lo_element_ext->set_attribute_ns( name = 'cy' + value = lv_value ). + ep_anchor->append_child( new_child = lo_element_ext ). + + ELSEIF ls_position-anchor = 'TWO'. + +* to cell ****************************** + lo_element_to = io_document->create_simple_element( name = lc_xml_node_to + parent = io_document ). + + lv_col = ls_position-to-col. + lv_row = ls_position-to-row. + lv_col_offset = ls_position-to-col_offset. + lv_row_offset = ls_position-to-row_offset. + CONDENSE lv_col NO-GAPS. + CONDENSE lv_row NO-GAPS. + CONDENSE lv_col_offset NO-GAPS. + CONDENSE lv_row_offset NO-GAPS. + + lo_element = io_document->create_simple_element( name = lc_xml_node_col + parent = io_document ). + lo_element->set_value( value = lv_col ). + lo_element_to->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_coloff + parent = io_document ). + lo_element->set_value( value = lv_col_offset ). + lo_element_to->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_row + parent = io_document ). + lo_element->set_value( value = lv_row ). + lo_element_to->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_rowoff + parent = io_document ). + lo_element->set_value( value = lv_row_offset ). + lo_element_to->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_to ). + + ENDIF. + + CASE io_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. +* pic ********************************** + lo_element_pic = io_document->create_simple_element( name = lc_xml_node_pic + parent = io_document ). +* nvPicPr + lo_element = io_document->create_simple_element( name = lc_xml_node_nvpicpr + parent = io_document ). +* cNvPr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvpr + parent = io_document ). + lv_value = sy-index. + CONDENSE lv_value. + lo_element2->set_attribute_ns( name = 'id' + value = lv_value ). + lo_element2->set_attribute_ns( name = 'name' + value = io_drawing->title ). + lo_element->append_child( new_child = lo_element2 ). + +* cNvPicPr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvpicpr + parent = io_document ). + +* picLocks + lo_element3 = io_document->create_simple_element( name = lc_xml_node_piclocks + parent = io_document ). + lo_element3->set_attribute_ns( name = 'noChangeAspect' + value = '1' ). + + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_pic->append_child( new_child = lo_element ). + +* blipFill + lv_value = ip_index. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = io_document->create_simple_element( name = lc_xml_node_blipfill + parent = io_document ). + lo_element2 = io_document->create_simple_element( name = lc_xml_node_ablip + parent = io_document ). + lo_element2->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_ns_r ). + lo_element2->set_attribute_ns( name = 'r:embed' + value = lv_value ). + lo_element->append_child( new_child = lo_element2 ). + + lo_element2 = io_document->create_simple_element( name = lc_xml_node_astretch + parent = io_document ). + lo_element->append_child( new_child = lo_element2 ). + + lo_element_pic->append_child( new_child = lo_element ). + +* spPr + lo_element = io_document->create_simple_element( name = lc_xml_node_sppr + parent = io_document ). + + lo_element2 = io_document->create_simple_element( name = lc_xml_node_apgeom + parent = io_document ). + lo_element2->set_attribute_ns( name = 'prst' + value = 'rect' ). + lo_element3 = io_document->create_simple_element( name = lc_xml_node_aavlst + parent = io_document ). + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + + lo_element_pic->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_pic ). + WHEN zcl_excel_drawing=>type_chart. +* graphicFrame ********************************** + lo_element_graphicframe = io_document->create_simple_element( name = lc_xml_node_graphicframe + parent = io_document ). +* nvGraphicFramePr + lo_element = io_document->create_simple_element( name = lc_xml_node_nvgraphicframepr + parent = io_document ). +* cNvPr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvpr + parent = io_document ). + lv_value = sy-index. + CONDENSE lv_value. + lo_element2->set_attribute_ns( name = 'id' + value = lv_value ). + lo_element2->set_attribute_ns( name = 'name' + value = io_drawing->title ). + lo_element->append_child( new_child = lo_element2 ). +* cNvGraphicFramePr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvgraphicframepr + parent = io_document ). + lo_element3 = io_document->create_simple_element( name = lc_xml_node_graphicframelocks + parent = io_document ). + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_graphicframe->append_child( new_child = lo_element ). + +* xfrm + lo_element = io_document->create_simple_element( name = lc_xml_node_xfrm + parent = io_document ). +* off + lo_element2 = io_document->create_simple_element( name = lc_xml_node_aoff + parent = io_document ). + lo_element2->set_attribute_ns( name = 'y' value = '0' ). + lo_element2->set_attribute_ns( name = 'x' value = '0' ). + lo_element->append_child( new_child = lo_element2 ). +* ext + lo_element2 = io_document->create_simple_element( name = lc_xml_node_aext + parent = io_document ). + lo_element2->set_attribute_ns( name = 'cy' value = '0' ). + lo_element2->set_attribute_ns( name = 'cx' value = '0' ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_graphicframe->append_child( new_child = lo_element ). + +* graphic + lo_element = io_document->create_simple_element( name = lc_xml_node_agraphic + parent = io_document ). +* graphicData + lo_element2 = io_document->create_simple_element( name = lc_xml_node_agraphicdata + parent = io_document ). + lo_element2->set_attribute_ns( name = 'uri' value = lc_xml_node_ns_c ). + +* chart + lo_element3 = io_document->create_simple_element( name = lc_xml_node_cchart + parent = io_document ). + + lo_element3->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_ns_r ). + lo_element3->set_attribute_ns( name = 'xmlns:c' + value = lc_xml_node_ns_c ). + + lv_value = ip_index. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element3->set_attribute_ns( name = 'r:id' + value = lv_value ). + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_graphicframe->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_graphicframe ). + + ENDCASE. + +* client data *************************** + lo_element_clientdata = io_document->create_simple_element( name = lc_xml_node_clientdata + parent = io_document ). + ep_anchor->append_child( new_child = lo_element_clientdata ). + + 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 namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#', + " Node type + lc_xml_node_rid_sheet_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', + lc_xml_node_rid_theme_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', + lc_xml_node_rid_styles_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + lc_xml_node_rid_shared_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', + " Node target + lc_xml_node_ridx_tg TYPE string VALUE 'worksheets/sheet#.xml', + lc_xml_node_rid_shared_tg TYPE string VALUE 'sharedStrings.xml', + lc_xml_node_rid_styles_tg TYPE string VALUE 'styles.xml', + lc_xml_node_rid_theme_tg TYPE string VALUE 'theme/theme1.xml'. + + 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 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. + + DATA: lv_xml_node_ridx_tg TYPE string, + lv_xml_node_ridx_id TYPE string, + lv_size TYPE i, + lv_syindex(3) TYPE c. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + lv_size = excel->get_worksheets_size( ). + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lv_size = lv_size + 2. + 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_styles_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_styles_tg ). + lo_element_root->append_child( new_child = lo_element ). + + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lv_size = lv_size - 1. + 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_theme_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_theme_tg ). + lo_element_root->append_child( new_child = lo_element ). + + lv_size = excel->get_worksheets_size( ). + + DO lv_size TIMES. + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + lv_xml_node_ridx_tg = lc_xml_node_ridx_tg. + lv_syindex = sy-index. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_tg 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_sheet_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_xml_node_ridx_tg ). + lo_element_root->append_child( new_child = lo_element ). + ENDDO. + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + ADD 3 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_shared_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_shared_tg ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* 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( ). + + endmethod. + + + + METHOD create_xl_sharedstrings. + + +** Constant node name + DATA: lc_xml_node_sst TYPE string VALUE 'sst', + lc_xml_node_si TYPE string VALUE 'si', + lc_xml_node_t TYPE string VALUE 't', + " Node attributes + lc_xml_attr_count TYPE string VALUE 'count', + lc_xml_attr_uniquecount TYPE string VALUE 'uniqueCount', + " 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 TYPE REF TO if_ixml_element, + lo_sub_element 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_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: lt_cell_data TYPE zexcel_t_cell_data_unsorted, + ls_shared_string TYPE zexcel_s_shared_string, + lv_value TYPE string, + lv_count_str TYPE string, + lv_uniquecount_str TYPE string, + lv_sytabix TYPE sytabix, + lv_count TYPE i, + lv_uniquecount TYPE i. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data, + <fs_sheet_string> TYPE zexcel_s_shared_string. + +********************************************************************** +* STEP 1: Collect strings from each worksheet + lo_iterator = excel->get_worksheets_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + APPEND LINES OF lo_worksheet->sheet_content TO lt_cell_data. + ENDWHILE. + + DELETE lt_cell_data WHERE cell_formula IS NOT INITIAL. " delete formula content + + DESCRIBE TABLE lt_cell_data LINES lv_count. + MOVE lv_count TO lv_count_str. + + SHIFT lv_count_str RIGHT DELETING TRAILING space. + SHIFT lv_count_str LEFT DELETING LEADING space. + + SORT lt_cell_data BY cell_value. + DELETE ADJACENT DUPLICATES FROM lt_cell_data COMPARING cell_value. + + DESCRIBE TABLE lt_cell_data LINES lv_uniquecount. + MOVE lv_uniquecount TO lv_uniquecount_str. + + SHIFT lv_uniquecount_str RIGHT DELETING TRAILING space. + SHIFT lv_uniquecount_str LEFT DELETING LEADING space. + + LOOP AT lt_cell_data ASSIGNING <fs_sheet_content>. + lv_sytabix = sy-tabix - 1. + MOVE lv_sytabix TO ls_shared_string-string_no. + MOVE <fs_sheet_content>-cell_value TO ls_shared_string-string_value. + MOVE <fs_sheet_content>-data_type TO ls_shared_string-string_type. + APPEND ls_shared_string TO shared_strings. + ENDLOOP. + + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_sst + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_count + value = lv_count_str ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_uniquecount + value = lv_uniquecount_str ). + +********************************************************************** +* STEP 4: Create subnode + LOOP AT shared_strings ASSIGNING <fs_sheet_string>. + lo_element = lo_document->create_simple_element( name = lc_xml_node_si + parent = lo_document ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_t + parent = lo_document ). +* if <fs_sheet_string>-string_type EQ 's_leading_blanks'. + IF <fs_sheet_string>-string_value IS NOT INITIAL AND <fs_sheet_string>-string_value(1) EQ ` `. + lo_sub_element->set_attribute( name = 'space' namespace = 'xml' value = 'preserve' ). + ENDIF. + lo_sub_element->set_value( value = <fs_sheet_string>-string_value ). + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + ENDLOOP. + +********************************************************************** +* 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( ). + +ENDMETHOD. + + + + + + + METHOD create_xl_sheet. +*--------------------------------------------------------------------* +* issue #330 - Adding ColorScale conditional formatting +* - Ivan Femia, 2014-08-25 +*--------------------------------------------------------------------* + + TYPES: BEGIN OF colors, + colorrgb TYPE zexcel_color, + END OF colors. + +*--------------------------------------------------------------------* +* issue #237 - Error writing column-style +* - Stefan Schmöcker, 2012-11-01 +*--------------------------------------------------------------------* + + TYPES: BEGIN OF cfvo, + value TYPE zexcel_conditional_value, + type TYPE zexcel_conditional_type, + END OF cfvo. + +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 1 - start +*--------------------------------------------------------------------* + TYPES: BEGIN OF lty_table_area, + left TYPE i, + right TYPE i, + top TYPE i, + bottom TYPE i, + END OF lty_table_area. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 1 - end +*--------------------------------------------------------------------* +** Constants + CONSTANTS: + lc_dummy_cell_content TYPE zexcel_s_cell_data-cell_value VALUE '})~~~ This is a dummy value for ABAP2XLSX and you should never find this in a real excelsheet Ihope'. + + +** Constant node name + DATA: lc_xml_node_worksheet TYPE string VALUE 'worksheet', + lc_xml_node_sheetpr TYPE string VALUE 'sheetPr', + lc_xml_node_tabcolor TYPE string VALUE 'tabColor', + lc_xml_node_outlinepr TYPE string VALUE 'outlinePr', + lc_xml_node_dimension TYPE string VALUE 'dimension', + lc_xml_node_sheetviews TYPE string VALUE 'sheetViews', + lc_xml_node_sheetview TYPE string VALUE 'sheetView', + lc_xml_node_selection TYPE string VALUE 'selection', + lc_xml_node_pane TYPE string VALUE 'pane', + lc_xml_node_sheetformatpr TYPE string VALUE 'sheetFormatPr', + lc_xml_node_cols TYPE string VALUE 'cols', + lc_xml_node_col TYPE string VALUE 'col', + lc_xml_node_sheetdata TYPE string VALUE 'sheetData', + lc_xml_node_row TYPE string VALUE 'row', + lc_xml_node_c TYPE string VALUE 'c', + lc_xml_node_v TYPE string VALUE 'v', + lc_xml_node_f TYPE string VALUE 'f', + lc_xml_node_sheetprotection TYPE string VALUE 'sheetProtection', + lc_xml_node_pagemargins TYPE string VALUE 'pageMargins', + lc_xml_node_pagesetup TYPE string VALUE 'pageSetup', + lc_xml_node_pagesetuppr TYPE string VALUE 'pageSetUpPr', + lc_xml_node_condformatting TYPE string VALUE 'conditionalFormatting', + lc_xml_node_cfrule TYPE string VALUE 'cfRule', + lc_xml_node_color TYPE string VALUE 'color', " Databar by Albert Lladanosa + lc_xml_node_databar TYPE string VALUE 'dataBar', " Databar by Albert Lladanosa + lc_xml_node_colorscale TYPE string VALUE 'colorScale', + lc_xml_node_iconset TYPE string VALUE 'iconSet', + lc_xml_node_cfvo TYPE string VALUE 'cfvo', + lc_xml_node_formula TYPE string VALUE 'formula', + lc_xml_node_datavalidations TYPE string VALUE 'dataValidations', + lc_xml_node_datavalidation TYPE string VALUE 'dataValidation', + lc_xml_node_formula1 TYPE string VALUE 'formula1', + lc_xml_node_formula2 TYPE string VALUE 'formula2', + lc_xml_node_mergecell TYPE string VALUE 'mergeCell', + lc_xml_node_mergecells TYPE string VALUE 'mergeCells', + lc_xml_node_drawing TYPE string VALUE 'drawing', + lc_xml_node_headerfooter TYPE string VALUE 'headerFooter', + lc_xml_node_oddheader TYPE string VALUE 'oddHeader', + lc_xml_node_oddfooter TYPE string VALUE 'oddFooter', + lc_xml_node_evenheader TYPE string VALUE 'evenHeader', + lc_xml_node_evenfooter TYPE string VALUE 'evenFooter', + lc_xml_node_autofilter TYPE string VALUE 'autoFilter', + lc_xml_node_filtercolumn TYPE string VALUE 'filterColumn', + lc_xml_node_filters TYPE string VALUE 'filters', + lc_xml_node_filter TYPE string VALUE 'filter', + " Node attributes + lc_xml_attr_ref TYPE string VALUE 'ref', + lc_xml_attr_summarybelow TYPE string VALUE 'summaryBelow', + lc_xml_attr_summaryright TYPE string VALUE 'summaryRight', + lc_xml_attr_tabselected TYPE string VALUE 'tabSelected', + lc_xml_attr_showzeros TYPE string VALUE 'showZeros', + lc_xml_attr_zoomscale TYPE string VALUE 'zoomScale', + lc_xml_attr_zoomscalenormal TYPE string VALUE 'zoomScaleNormal', + lc_xml_attr_zoomscalepageview TYPE string VALUE 'zoomScalePageLayoutView', + lc_xml_attr_zoomscalesheetview TYPE string VALUE 'zoomScaleSheetLayoutView', + lc_xml_attr_workbookviewid TYPE string VALUE 'workbookViewId', + lc_xml_attr_showgridlines TYPE string VALUE 'showGridLines', + lc_xml_attr_gridlines TYPE string VALUE 'gridLines', + lc_xml_attr_showrowcolheaders TYPE string VALUE 'showRowColHeaders', + lc_xml_attr_activecell TYPE string VALUE 'activeCell', + lc_xml_attr_sqref TYPE string VALUE 'sqref', + lc_xml_attr_min TYPE string VALUE 'min', + lc_xml_attr_max TYPE string VALUE 'max', + lc_xml_attr_hidden TYPE string VALUE 'hidden', + lc_xml_attr_width TYPE string VALUE 'width', + lc_xml_attr_defaultwidth TYPE string VALUE '9.10', + lc_xml_attr_style TYPE string VALUE 'style', + lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_bestfit TYPE string VALUE 'bestFit', + lc_xml_attr_customheight TYPE string VALUE 'customHeight', + lc_xml_attr_customwidth TYPE string VALUE 'customWidth', + lc_xml_attr_collapsed TYPE string VALUE 'collapsed', + lc_xml_attr_defaultrowheight TYPE string VALUE 'defaultRowHeight', + lc_xml_attr_defaultcolwidth TYPE string VALUE 'defaultColWidth', + lc_xml_attr_outlinelevelrow TYPE string VALUE 'x14ac:outlineLevelRow', + lc_xml_attr_outlinelevelcol TYPE string VALUE 'x14ac:outlineLevelCol', + lc_xml_attr_outlinelevel TYPE string VALUE 'outlineLevel', + lc_xml_attr_r TYPE string VALUE 'r', + lc_xml_attr_s TYPE string VALUE 's', + lc_xml_attr_spans TYPE string VALUE 'spans', + lc_xml_attr_t TYPE string VALUE 't', + lc_xml_attr_password TYPE string VALUE 'password', + lc_xml_attr_sheet TYPE string VALUE 'sheet', + lc_xml_attr_objects TYPE string VALUE 'objects', + lc_xml_attr_scenarios TYPE string VALUE 'scenarios', + lc_xml_attr_autofilter TYPE string VALUE 'autoFilter', + lc_xml_attr_deletecolumns TYPE string VALUE 'deleteColumns', + lc_xml_attr_deleterows TYPE string VALUE 'deleteRows', + lc_xml_attr_formatcells TYPE string VALUE 'formatCells', + lc_xml_attr_formatcolumns TYPE string VALUE 'formatColumns', + lc_xml_attr_formatrows TYPE string VALUE 'formatRows', + lc_xml_attr_insertcolumns TYPE string VALUE 'insertColumns', + lc_xml_attr_inserthyperlinks TYPE string VALUE 'insertHyperlinks', + lc_xml_attr_insertrows TYPE string VALUE 'insertRows', + lc_xml_attr_pivottables TYPE string VALUE 'pivotTables', + lc_xml_attr_selectlockedcells TYPE string VALUE 'selectLockedCells', + lc_xml_attr_selectunlockedcell TYPE string VALUE 'selectUnlockedCells', + lc_xml_attr_sort TYPE string VALUE 'sort', + lc_xml_attr_left TYPE string VALUE 'left', + lc_xml_attr_right TYPE string VALUE 'right', + lc_xml_attr_top TYPE string VALUE 'top', + lc_xml_attr_bottom TYPE string VALUE 'bottom', + lc_xml_attr_header TYPE string VALUE 'header', + lc_xml_attr_footer TYPE string VALUE 'footer', + lc_xml_attr_type TYPE string VALUE 'type', + lc_xml_attr_iconset TYPE string VALUE 'iconSet', + lc_xml_attr_showvalue TYPE string VALUE 'showValue', + lc_xml_attr_val TYPE string VALUE 'val', + lc_xml_attr_dxfid TYPE string VALUE 'dxfId', + lc_xml_attr_priority TYPE string VALUE 'priority', + lc_xml_attr_operator TYPE string VALUE 'operator', + lc_xml_attr_allowblank TYPE string VALUE 'allowBlank', + lc_xml_attr_showinputmessage TYPE string VALUE 'showInputMessage', + lc_xml_attr_showerrormessage TYPE string VALUE 'showErrorMessage', + lc_xml_attr_errortitle TYPE string VALUE 'errorTitle', + lc_xml_attr_error TYPE string VALUE 'error', + lc_xml_attr_prompttitle TYPE string VALUE 'promptTitle', + lc_xml_attr_prompt TYPE string VALUE 'prompt', + lc_xml_attr_count TYPE string VALUE 'count', + lc_xml_attr_blackandwhite TYPE string VALUE 'blackAndWhite', + lc_xml_attr_cellcomments TYPE string VALUE 'cellComments', + lc_xml_attr_copies TYPE string VALUE 'copies', + lc_xml_attr_draft TYPE string VALUE 'draft', + lc_xml_attr_errors TYPE string VALUE 'errors', + lc_xml_attr_firstpagenumber TYPE string VALUE 'firstPageNumber', + lc_xml_attr_fittopage TYPE string VALUE 'fitToPage', + lc_xml_attr_fittoheight TYPE string VALUE 'fitToHeight', + lc_xml_attr_fittowidth TYPE string VALUE 'fitToWidth', + lc_xml_attr_horizontaldpi TYPE string VALUE 'horizontalDpi', + lc_xml_attr_orientation TYPE string VALUE 'orientation', + lc_xml_attr_pageorder TYPE string VALUE 'pageOrder', + lc_xml_attr_paperheight TYPE string VALUE 'paperHeight', + lc_xml_attr_papersize TYPE string VALUE 'paperSize', + lc_xml_attr_paperwidth TYPE string VALUE 'paperWidth', + lc_xml_attr_scale TYPE string VALUE 'scale', + lc_xml_attr_usefirstpagenumber TYPE string VALUE 'useFirstPageNumber', + lc_xml_attr_useprinterdefaults TYPE string VALUE 'usePrinterDefaults', + lc_xml_attr_verticaldpi TYPE string VALUE 'verticalDpi', + lc_xml_attr_differentoddeven TYPE string VALUE 'differentOddEven', + lc_xml_attr_colid TYPE string VALUE 'colId', + lc_xml_attr_filtermode TYPE string VALUE 'filterMode', + lc_xml_attr_tabcolor_rgb TYPE string VALUE 'rgb', + lc_xml_attr_tabcolor_theme TYPE string VALUE 'theme', + " Node namespace + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + lc_xml_node_r_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + lc_xml_node_comp_ns TYPE string VALUE 'http://schemas.openxmlformats.org/markup-compatibility/2006', + lc_xml_node_comp_pref TYPE string VALUE 'x14ac', + lc_xml_node_ig_ns TYPE string VALUE 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac'. + + 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 TYPE REF TO if_ixml_element, + lo_element_2 TYPE REF TO if_ixml_element, + lo_element_3 TYPE REF TO if_ixml_element, + lo_element_4 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_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_table TYPE REF TO zcl_excel_table, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + lo_row_dim_empty TYPE REF TO zcl_excel_worksheet_rowdimensi, + default_col_dimension TYPE REF TO zcl_excel_worksheet_columndime, + default_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + + DATA: lv_value TYPE string, + lt_range_merge TYPE string_table, + lv_merge TYPE string, + lv_column_p TYPE zexcel_cell_column_alpha, + lv_column TYPE zexcel_cell_column, + lv_cell_value TYPE zexcel_cell_value, + lv_style_guid TYPE zexcel_cell_style, + lv_flag TYPE c, + ls_databar TYPE zexcel_conditional_databar, " Databar by Albert Lladanosa + ls_colorscale TYPE zexcel_conditional_colorscale, + ls_iconset TYPE zexcel_conditional_iconset, + ls_cellis TYPE zexcel_conditional_cellis, + ls_expression TYPE zexcel_conditional_expression, + ls_conditional_top10 TYPE zexcel_conditional_top10, + ls_conditional_above_avg TYPE zexcel_conditional_above_avg, + lt_cfvo TYPE TABLE OF cfvo, + ls_cfvo TYPE cfvo, + lt_colors TYPE TABLE OF colors, + ls_colors TYPE colors, + lv_cell_row_s TYPE string, + ls_last_row TYPE zexcel_s_cell_data, + ls_style_mapping TYPE zexcel_s_styles_mapping, + lv_freeze_cell_row TYPE zexcel_cell_row, + lv_freeze_cell_column TYPE zexcel_cell_column, + lv_freeze_cell_column_alpha TYPE zexcel_cell_column_alpha, + column_dimensions TYPE zexcel_t_worksheet_columndime, + row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + lv_relation_id TYPE i VALUE 0, + outline_level_row TYPE i VALUE 0, + outline_level_col TYPE i VALUE 0, + lv_current_row TYPE i, + lv_next_row TYPE i, + ls_sheet_content LIKE LINE OF io_worksheet->sheet_content, + ls_sheet_content_empty LIKE LINE OF io_worksheet->sheet_content, + lv_last_row TYPE i, + lts_row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + lts_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + col_count TYPE int4, + merge_count TYPE int4, + write_current_row TYPE boolean, + lt_values TYPE zexcel_t_autofilter_values, + ls_values TYPE zexcel_s_autofilter_values, +* lv_guid TYPE uuid, + lo_autofilters TYPE REF TO zcl_excel_autofilters, + lo_autofilter TYPE REF TO zcl_excel_autofilter, + l_autofilter_hidden TYPE flag, + ls_area TYPE zexcel_s_autofilter_area, + lv_ref TYPE string, + lv_style_index TYPE i. " issue #237 + + + FIELD-SYMBOLS: <ls_sheet_content> TYPE zexcel_s_cell_data, + <fs_range_merge> LIKE LINE OF lt_range_merge, + <column_dimension> TYPE zexcel_s_worksheet_columndime, + <row_dimension> TYPE zexcel_s_worksheet_rowdimensio, + <ls_row_outline> LIKE LINE OF lts_row_outlines. + +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 2 - start +*--------------------------------------------------------------------* + DATA: lt_table_areas TYPE SORTED TABLE OF lty_table_area WITH NON-UNIQUE KEY left right top bottom, + ls_table_area LIKE LINE OF lt_table_areas. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 2 - end +*--------------------------------------------------------------------* + + + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_worksheet + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_r_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:mc' + value = lc_xml_node_comp_ns ). + lo_element_root->set_attribute_ns( name = 'mc:Ignorable' + value = lc_xml_node_comp_pref ). + lo_element_root->set_attribute_ns( name = 'xmlns:x14ac' + value = lc_xml_node_ig_ns ). + + +********************************************************************** +* STEP 4: Create subnodes + " sheetPr + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetpr + parent = lo_document ). + " TODO tabColor + IF io_worksheet->tabcolor IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_tabcolor + parent = lo_element ). +* Theme not supported yet - start with RGB + lv_value = io_worksheet->tabcolor-rgb. + lo_element_2->set_attribute_ns( name = lc_xml_attr_tabcolor_rgb + value = lv_value ). + ENDIF. + + " outlinePr + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_outlinepr + parent = lo_document ). + + lv_value = io_worksheet->zif_excel_sheet_properties~summarybelow. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_summarybelow + value = lv_value ). + + lv_value = io_worksheet->zif_excel_sheet_properties~summaryright. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_summaryright + value = lv_value ). + + lo_element->append_child( new_child = lo_element_2 ). + + IF io_worksheet->sheet_setup->fit_to_page IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_pagesetuppr + parent = lo_document ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_fittopage + value = `1` ). + lo_element->append_child( new_child = lo_element_2 ). " pageSetupPr node + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). + + " dimension node + lo_element = lo_document->create_simple_element( name = lc_xml_node_dimension + parent = lo_document ). + lv_value = io_worksheet->get_dimension_range( ). + lo_element->set_attribute_ns( name = lc_xml_attr_ref + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " sheetViews node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetviews + parent = lo_document ). + " sheetView node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_sheetview + parent = lo_document ). + IF io_worksheet->zif_excel_sheet_properties~show_zeros EQ abap_false. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showzeros + value = '0' ). + ENDIF. + IF iv_active = abap_true + OR io_worksheet->zif_excel_sheet_properties~selected EQ abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_tabselected + value = '1' ). + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_tabselected + value = '0' ). + ENDIF. + " Zoom scale + IF io_worksheet->zif_excel_sheet_properties~zoomscale GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscale + value = lv_value ). + IF io_worksheet->zif_excel_sheet_properties~zoomscale_normal NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_normal GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_normal = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_normal LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_normal = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale_normal. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscalenormal + value = lv_value ). + ENDIF. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscalepageview + value = lv_value ). + ENDIF. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscalesheetview + value = lv_value ). + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_workbookviewid + value = '0' ). + " showGridLines attribute + IF io_worksheet->show_gridlines = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showgridlines + value = '1' ). + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showgridlines + value = '0' ). + ENDIF. + + " showRowColHeaders attribute + IF io_worksheet->show_rowcolheaders = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showrowcolheaders + value = '1' ). + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showrowcolheaders + value = '0' ). + ENDIF. + + + " freeze panes + io_worksheet->get_freeze_cell( IMPORTING ep_row = lv_freeze_cell_row + ep_column = lv_freeze_cell_column ). + + IF lv_freeze_cell_row IS NOT INITIAL AND lv_freeze_cell_column IS NOT INITIAL. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_pane + parent = lo_element_2 ). + + IF lv_freeze_cell_row > 1. + lv_value = lv_freeze_cell_row - 1. + CONDENSE lv_value. + lo_element_3->set_attribute_ns( name = 'ySplit' + value = lv_value ). + ENDIF. + + IF lv_freeze_cell_column > 1. + lv_value = lv_freeze_cell_column - 1. + CONDENSE lv_value. + lo_element_3->set_attribute_ns( name = 'xSplit' + value = lv_value ). + ENDIF. + + lv_freeze_cell_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column = lv_freeze_cell_column ). + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_freeze_cell_row ). + CONCATENATE lv_freeze_cell_column_alpha lv_value INTO lv_value. + lo_element_3->set_attribute_ns( name = 'topLeftCell' + value = lv_value ). + + lo_element_3->set_attribute_ns( name = 'activePane' + value = 'bottomRight' ). + + lo_element_3->set_attribute_ns( name = 'state' + value = 'frozen' ). + + lo_element_2->append_child( new_child = lo_element_3 ). + ENDIF. + " selection node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_selection + parent = lo_document ). + lv_value = io_worksheet->get_active_cell( ). + lo_element_3->set_attribute_ns( name = lc_xml_attr_activecell + value = lv_value ). + + lo_element_3->set_attribute_ns( name = lc_xml_attr_sqref + value = lv_value ). + + lo_element_2->append_child( new_child = lo_element_3 ). " sheetView node + + lo_element->append_child( new_child = lo_element_2 ). " sheetView node + + lo_element_root->append_child( new_child = lo_element ). " sheetViews node + + + column_dimensions[] = io_worksheet->get_column_dimensions( ). + " Calculate col + IF NOT column_dimensions IS INITIAL. + io_worksheet->calculate_column_widths( ). + column_dimensions[] = io_worksheet->get_column_dimensions( ). + ENDIF. + row_dimensions[] = io_worksheet->get_row_dimensions( ). + " sheetFormatPr node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetformatpr + parent = lo_document ). + " defaultRowHeight + default_row_dimension = io_worksheet->get_default_row_dimension( ). + IF default_row_dimension IS BOUND. + IF default_row_dimension->get_row_height( ) >= 0. + lo_element->set_attribute_ns( name = lc_xml_attr_customheight + value = lc_xml_attr_true ). + lv_value = default_row_dimension->get_row_height( ). + ELSE. + lv_value = '12.75'. + ENDIF. + ELSE. + lv_value = '12.75'. + ENDIF. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_defaultrowheight + value = lv_value ). + " defaultColWidth + default_col_dimension = io_worksheet->get_default_column_dimension( ). + IF default_col_dimension IS BOUND. + IF default_col_dimension->get_width( ) >= 0. + lv_value = default_col_dimension->get_width( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_defaultcolwidth + value = lv_value ). + ENDIF. + ENDIF. + " outlineLevelRow +* Excel is recalculating the outlinelevel on startup from the outline levels found in the rows +* If we place anything incorrect here it gets corrected, if don't place anything it gets added +* So no need to calculate the outlinelevel here ( at least for rows - probably for columns as well but I haven't tested yet +* LOOP AT row_dimensions ASSIGNING <row_dimension>. +* IF <row_dimension>-row_dimension->get_outline_level( ) > outline_level_row. +* outline_level_row = <row_dimension>-row_dimension->get_outline_level( ). +* ENDIF. +* ENDLOOP. +* lv_value = outline_level_row. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element->set_attribute_ns( name = lc_xml_attr_outlinelevelrow +* value = lv_value ). + " outlineLevelCol + LOOP AT column_dimensions ASSIGNING <column_dimension>. + IF <column_dimension>-column_dimension->get_outline_level( ) > outline_level_col. + outline_level_col = <column_dimension>-column_dimension->get_outline_level( ). + ENDIF. + ENDLOOP. + lv_value = outline_level_col. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_outlinelevelcol + value = lv_value ). +* lv_value = 0. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element->set_attribute_ns( name = lc_xml_attr_dydescent +* value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). " sheetFormatPr node + + IF io_worksheet->zif_excel_sheet_properties~get_style( ) IS NOT INITIAL OR NOT column_dimensions IS INITIAL. + " cols node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cols + parent = lo_document ). + " This code have to be enhanced in order to manage also column style properties + " Now it is an out/out + IF NOT column_dimensions IS INITIAL. + LOOP AT column_dimensions ASSIGNING <column_dimension>. + " col node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_col + parent = lo_document ). + lv_value = <column_dimension>-column_dimension->get_column_index( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_min + value = lv_value ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_max + value = lv_value ). + " Width + IF <column_dimension>-column_dimension->get_width( ) < 0. + lo_element_2->set_attribute_ns( name = lc_xml_attr_width + value = lc_xml_attr_defaultwidth ). + ELSE. + lv_value = <column_dimension>-column_dimension->get_width( ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_width + value = lv_value ). + ENDIF. + " Column visibility + IF <column_dimension>-column_dimension->get_visible( ) = abap_false. + lo_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = lc_xml_attr_true ). + ENDIF. + " Auto size? + IF <column_dimension>-column_dimension->get_auto_size( ) = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_bestfit + value = lc_xml_attr_true ). + ENDIF. + " Custom width? + IF default_col_dimension IS BOUND. + IF <column_dimension>-column_dimension->get_width( ) + <> default_col_dimension->get_width( ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_customwidth + value = lc_xml_attr_true ). + + ENDIF. + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_customwidth + value = lc_xml_attr_true ). + ENDIF. + " Collapsed + IF <column_dimension>-column_dimension->get_collapsed( ) = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_collapsed + value = lc_xml_attr_true ). + ENDIF. + " outlineLevel + IF <column_dimension>-column_dimension->get_outline_level( ) > 0. + lv_value = <column_dimension>-column_dimension->get_outline_level( ). + + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_outlinelevel + value = lv_value ). + ENDIF. + " Style +* lv_value = <column_dimension>-column_dimension->get_xf_index( ). "del issue #157 - set column style + lv_style_guid = <column_dimension>-column_dimension->get_column_style_guid( ). "ins issue #157 - set column style +* lv_value = me->excel->get_style_index_in_styles( lv_style_guid ). "del issue #237 + CLEAR ls_style_mapping. + READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. +* lv_style_index = ls_style_mapping-style. "del issue #295 +* IF lv_style_index > 0. "ins issue #237 - del issue #295 +* lv_value = lv_style_index - 1. "ins issue #237 - del issue #295 + IF sy-subrc = 0. "ins issue #295 + lv_value = ls_style_mapping-style. "ins issue #295 + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. "ins issue #237 + + lo_element->append_child( new_child = lo_element_2 ). " col node + ENDLOOP. +* ELSE. "del issue #157 - set sheet style ( add missing columns +* IF io_worksheet->zif_excel_sheet_properties~get_style( ) IS NOT INITIAL. "del issue #157 - set sheet style ( add missing columns +* Begin of insertion issue #157 - set sheet style ( add missing columns + ENDIF. +* Always pass through this coding + IF io_worksheet->zif_excel_sheet_properties~get_style( ) IS NOT INITIAL. + DATA: lts_sorted_columns TYPE SORTED TABLE OF zexcel_cell_column WITH UNIQUE KEY table_line. + TYPES: BEGIN OF ty_missing_columns, + first_column TYPE zexcel_cell_column, + last_column TYPE zexcel_cell_column, + END OF ty_missing_columns. + DATA: t_missing_columns TYPE STANDARD TABLE OF ty_missing_columns WITH NON-UNIQUE DEFAULT KEY, + missing_column LIKE LINE OF t_missing_columns. + +* First collect columns that were already handled before. The rest has to be inserted now + LOOP AT column_dimensions ASSIGNING <column_dimension>. + lv_column = zcl_excel_common=>convert_column2int( <column_dimension>-column ). + INSERT lv_column INTO TABLE lts_sorted_columns. + ENDLOOP. + +* Now find all columns that were missing so far + missing_column-first_column = 1. + LOOP AT lts_sorted_columns INTO lv_column. + IF lv_column > missing_column-first_column. + missing_column-last_column = lv_column - 1. + APPEND missing_column TO t_missing_columns. + ENDIF. + missing_column-first_column = lv_column + 1. + ENDLOOP. + missing_column-last_column = zcl_excel_common=>c_excel_sheet_max_col. + APPEND missing_column TO t_missing_columns. +* Now apply stylesetting ( and other defaults - I copy it from above. Whoever programmed that seems to know what to do :o) + LOOP AT t_missing_columns INTO missing_column. +* End of insertion issue #157 - set column style + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_col + parent = lo_document ). +* lv_value = zcl_excel_common=>c_excel_sheet_min_col."del issue #157 - set sheet style ( add missing columns + lv_value = missing_column-first_column. "ins issue #157 - set sheet style ( add missing columns + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_min + value = lv_value ). +* lv_value = zcl_excel_common=>c_excel_sheet_max_col."del issue #157 - set sheet style ( add missing columns + lv_value = missing_column-last_column. "ins issue #157 - set sheet style ( add missing columns + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_max + value = lv_value ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_width + value = lc_xml_attr_defaultwidth ). + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. + lv_value = ls_style_mapping-style. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). " col node + ENDLOOP. "ins issue #157 - set sheet style ( add missing columns + + ENDIF. +*--------------------------------------------------------------------* +* issue #367 add feature hide columns from +*--------------------------------------------------------------------* + IF io_worksheet->zif_excel_sheet_properties~hide_columns_from IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_col + parent = lo_document ). + lv_value = zcl_excel_common=>convert_column2int( io_worksheet->zif_excel_sheet_properties~hide_columns_from ). + CONDENSE lv_value NO-GAPS. + lo_element_2->set_attribute_ns( name = lc_xml_attr_min + value = lv_value ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_max + value = '16384' ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = '1' ). + lo_element->append_child( new_child = lo_element_2 ). " col node + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). " cols node + ENDIF. + " sheetData node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetdata + parent = lo_document ). + " Get column count + col_count = io_worksheet->get_highest_column( ). + " Get autofilter +* lv_guid = io_worksheet->get_guid( ) . + lo_autofilters = excel->get_autofilters_reference( ). + lo_autofilter = lo_autofilters->get( i_sheet_guid = io_worksheet->get_guid( ) ) . + IF lo_autofilter IS BOUND. + lt_values = lo_autofilter->get_values( ) . + ls_area = lo_autofilter->get_filter_area( ) . + l_autofilter_hidden = abap_true. " First defautl is not showing + ENDIF. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 1 - start +*--------------------------------------------------------------------* +* Build table to hold all table-areas attached to this sheet + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ls_table_area-left = zcl_excel_common=>convert_column2int( lo_table->settings-top_left_column ). + ls_table_area-right = lo_table->get_right_column_integer( ). + ls_table_area-top = lo_table->settings-top_left_row. + ls_table_area-bottom = lo_table->get_bottom_row_integer( ). + INSERT ls_table_area INTO TABLE lt_table_areas. + ENDWHILE. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 1 - end +*--------------------------------------------------------------------* +* We have problems when the first rows or trailing rows are not set but we have rowinformation +* to solve this we add dummycontent into first and last line that will not be set +* Set first line if necessary + READ TABLE io_worksheet->sheet_content TRANSPORTING NO FIELDS WITH KEY cell_row = 1. + IF sy-subrc <> 0. + ls_sheet_content_empty-cell_row = 1. + ls_sheet_content_empty-cell_column = 1. + ls_sheet_content_empty-cell_value = lc_dummy_cell_content. + INSERT ls_sheet_content_empty INTO TABLE io_worksheet->sheet_content. + ENDIF. +* Set last line if necessary +* Last row with cell content + lv_last_row = io_worksheet->get_highest_row( ). +* Last line with row-information set directly ( like line height, hidden-status ... ) + lts_row_dimensions = io_worksheet->get_row_dimensions( ). + SORT lts_row_dimensions BY row DESCENDING. + READ TABLE lts_row_dimensions INDEX 1 ASSIGNING <row_dimension>. + IF sy-subrc = 0 AND <row_dimension>-row > lv_last_row. + lv_last_row = <row_dimension>-row. + ENDIF. +* Last line with row-information set indirectly by row outline + lts_row_outlines = io_worksheet->get_row_outlines( ). + LOOP AT lts_row_outlines ASSIGNING <ls_row_outline>. + IF <ls_row_outline>-collapsed = 'X'. + lv_current_row = <ls_row_outline>-row_to + 1. " collapsed-status may be set on following row + ELSE. + lv_current_row = <ls_row_outline>-row_to. " collapsed-status may be set on following row + ENDIF. + IF lv_current_row > lv_last_row. + lv_last_row = lv_current_row. + ENDIF. + ENDLOOP. + READ TABLE io_worksheet->sheet_content TRANSPORTING NO FIELDS WITH KEY cell_row = lv_last_row. + IF sy-subrc <> 0. + ls_sheet_content_empty-cell_row = lv_last_row. + ls_sheet_content_empty-cell_column = 1. + ls_sheet_content_empty-cell_value = lc_dummy_cell_content. + INSERT ls_sheet_content_empty INTO TABLE io_worksheet->sheet_content. + ENDIF. + + + CLEAR ls_sheet_content. + LOOP AT io_worksheet->sheet_content INTO ls_sheet_content. + IF lt_values IS INITIAL. " no values attached to autofilter " issue #368 autofilter filtering too much + CLEAR l_autofilter_hidden. + ELSE. + READ TABLE lt_values INTO ls_values WITH KEY column = ls_last_row-cell_column. + IF sy-subrc = 0 AND ls_values-value = ls_last_row-cell_value. + CLEAR l_autofilter_hidden. + ENDIF. + ENDIF. + CLEAR ls_style_mapping. +* Create row element +* issues #346,#154, #195 - problems when we have information in row_dimension but no cell content in that row +* Get next line that may have to be added. If we have empty lines this is the next line after previous cell content +* Otherwise it is the line of the current cell content + lv_current_row = ls_last_row-cell_row + 1. + IF lv_current_row > ls_sheet_content-cell_row. + lv_current_row = ls_sheet_content-cell_row. + ENDIF. +* Fill in empty lines if necessary - assign an emtpy sheet content + lv_next_row = lv_current_row. + WHILE lv_next_row <= ls_sheet_content-cell_row. + lv_current_row = lv_next_row. + lv_next_row = lv_current_row + 1. + IF lv_current_row = ls_sheet_content-cell_row. " cell value found in this row + ASSIGN ls_sheet_content TO <ls_sheet_content>. + ELSE. +* Check if empty row is really necessary - this is basically the case when we have information in row_dimension + lo_row_dim_empty = io_worksheet->get_row_dimension( lv_current_row ). + CHECK lo_row_dim_empty->get_row_height( ) >= 0 OR + lo_row_dim_empty->get_collapsed( io_worksheet ) = abap_true OR + lo_row_dim_empty->get_outline_level( io_worksheet ) > 0 OR + lo_row_dim_empty->get_xf_index( ) <> 0. + " Dummyentry A1 + ls_sheet_content_empty-cell_row = lv_current_row. + ls_sheet_content_empty-cell_column = 1. + ASSIGN ls_sheet_content_empty TO <ls_sheet_content>. + ENDIF. + + IF ls_last_row-cell_row NE <ls_sheet_content>-cell_row. + IF lo_autofilter IS BOUND. + IF ls_area-row_start >= ls_last_row-cell_row OR " One less for header + ls_area-row_end < ls_last_row-cell_row . + CLEAR l_autofilter_hidden. + ENDIF. + ELSE. + CLEAR l_autofilter_hidden. + ENDIF. + IF ls_last_row-cell_row IS NOT INITIAL. + " Row visibility of previos row. + IF row_dimension->get_visible( io_worksheet ) = abap_false OR + l_autofilter_hidden = abap_true. + lo_element_2->set_attribute_ns( name = 'hidden' value = 'true'). + ENDIF. + lo_element->append_child( new_child = lo_element_2 ). " row node + ENDIF. + " Add new row + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_row + parent = lo_document ). + " r + lv_value = <ls_sheet_content>-cell_row. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + + lo_element_2->set_attribute_ns( name = lc_xml_attr_r + value = lv_value ). + " Spans + lv_value = col_count. + CONCATENATE '1:' lv_value INTO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_spans + value = lv_value ). + row_dimension = io_worksheet->get_row_dimension( <ls_sheet_content>-cell_row ). + " Do we need the row dimension attributes? + IF row_dimension->get_row_height( ) >= 0 OR + row_dimension->get_collapsed( io_worksheet ) = abap_true OR + row_dimension->get_outline_level( io_worksheet ) > 0 OR + row_dimension->get_xf_index( ) <> 0 OR + l_autofilter_hidden = abap_true. + " Row dimensions + IF row_dimension->get_row_height( ) >= 0. + lo_element_2->set_attribute_ns( name = 'customHeight' value = '1'). + lv_value = row_dimension->get_row_height( ). + lo_element_2->set_attribute_ns( name = 'ht' value = lv_value ). + ENDIF. + " Collapsed + IF row_dimension->get_collapsed( io_worksheet ) = abap_true. + lo_element_2->set_attribute_ns( name = 'collapsed' value = 'true'). + ENDIF. + " Outline level + IF row_dimension->get_outline_level( io_worksheet ) > 0. + lv_value = row_dimension->get_outline_level( io_worksheet ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = 'outlineLevel' value = lv_value ). + ENDIF. + " Style + IF row_dimension->get_xf_index( ) <> 0. + lv_value = row_dimension->get_xf_index( ). + lo_element_2->set_attribute_ns( name = 's' value = lv_value ). + lo_element_2->set_attribute_ns( name = 'customFormat' value = '1'). + ENDIF. + ENDIF. + IF lt_values IS INITIAL. " no values attached to autofilter " issue #368 autofilter filtering too much + CLEAR l_autofilter_hidden. + ELSE. + l_autofilter_hidden = abap_true. " First default is not showing + ENDIF. + ELSE. + + ENDIF. + ENDWHILE. + + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_c + parent = lo_document ). + + lo_element_3->set_attribute_ns( name = lc_xml_attr_r + value = <ls_sheet_content>-cell_coords ). + +* begin of change issue #157 - allow column cellstyle +* if no cellstyle is set, look into column, then into sheet + IF <ls_sheet_content>-cell_style IS NOT INITIAL. + lv_style_guid = <ls_sheet_content>-cell_style. + ELSE. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 2 - start +*--------------------------------------------------------------------* +* Check if cell in any of the table areas + LOOP AT lt_table_areas TRANSPORTING NO FIELDS WHERE top <= <ls_sheet_content>-cell_row + AND bottom >= <ls_sheet_content>-cell_row + AND left <= <ls_sheet_content>-cell_column + AND right >= <ls_sheet_content>-cell_column. + EXIT. + ENDLOOP. + IF sy-subrc = 0. + CLEAR lv_style_guid. " No style --> EXCEL will use built-in-styles as declared in the tables-section + ELSE. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 2 - end +*--------------------------------------------------------------------* + lv_column_p = zcl_excel_common=>convert_column2alpha( <ls_sheet_content>-cell_column ). + READ TABLE column_dimensions WITH KEY column = lv_column_p ASSIGNING <column_dimension>. + IF sy-subrc = 0. + lv_style_guid = <column_dimension>-column_dimension->get_column_style_guid( ). + IF lv_style_guid IS INITIAL. + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. + ELSE. + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 3 - start +*--------------------------------------------------------------------* + ENDIF. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 3 - end +*--------------------------------------------------------------------* + ENDIF. +* IF <ls_sheet_content>-cell_style IS NOT INITIAL. +* READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = <ls_sheet_content>-cell_style. + IF lv_style_guid IS NOT INITIAL. + READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. +* end of change issue #157 - allow column cellstyles + lv_value = ls_style_mapping-style. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_3->set_attribute_ns( name = lc_xml_attr_s + value = lv_value ). + ENDIF. + + " For cells with formula ignore the value - Excel will calculate it + IF <ls_sheet_content>-cell_formula IS NOT INITIAL. + " fomula node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_document ). + lv_value = <ls_sheet_content>-cell_formula. + CONDENSE lv_value. + lo_element_4->set_value( value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " fomula node + ELSEIF <ls_sheet_content>-cell_value IS NOT INITIAL "cell can have just style or formula + AND <ls_sheet_content>-cell_value <> lc_dummy_cell_content. + IF <ls_sheet_content>-data_type IS NOT INITIAL. + IF <ls_sheet_content>-data_type EQ 's_leading_blanks'. + lo_element_3->set_attribute_ns( name = lc_xml_attr_t + value = 's' ). + ELSE. + lo_element_3->set_attribute_ns( name = lc_xml_attr_t + value = <ls_sheet_content>-data_type ). + ENDIF. + ENDIF. + + " value node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_document ). + + IF <ls_sheet_content>-data_type EQ 's' OR <ls_sheet_content>-data_type EQ 's_leading_blanks'. + lv_value = me->get_shared_string_index( <ls_sheet_content>-cell_value ). + CONDENSE lv_value. + lo_element_4->set_value( value = lv_value ). + ELSE. + lv_value = <ls_sheet_content>-cell_value. + CONDENSE lv_value. + lo_element_4->set_value( value = lv_value ). + ENDIF. + + lo_element_3->append_child( new_child = lo_element_4 ). " value node + ENDIF. + + lo_element_2->append_child( new_child = lo_element_3 ). " column node + ls_last_row = <ls_sheet_content>. + ENDLOOP. + IF sy-subrc = 0. + READ TABLE lt_values INTO ls_values WITH KEY column = ls_last_row-cell_column. + IF sy-subrc = 0 AND ls_values-value = ls_last_row-cell_value. + CLEAR l_autofilter_hidden. + ENDIF. + IF lo_autofilter IS BOUND. + IF ls_area-row_start >= ls_last_row-cell_row OR " One less for header + ls_area-row_end < ls_last_row-cell_row . + CLEAR l_autofilter_hidden. + ENDIF. + ELSE. + CLEAR l_autofilter_hidden. + ENDIF. + " Row visibility of previos row. + IF row_dimension->get_visible( ) = abap_false OR + l_autofilter_hidden = abap_true. + lo_element_2->set_attribute_ns( name = 'hidden' value = 'true'). + ENDIF. + lo_element->append_child( new_child = lo_element_2 ). " row node + ENDIF. + DELETE io_worksheet->sheet_content WHERE cell_value = lc_dummy_cell_content. " Get rid of dummyentries + + lo_element_root->append_child( new_child = lo_element ). " sheetData node + + IF lo_autofilter IS BOUND. +* Create node autofilter + lo_element = lo_document->create_simple_element( name = lc_xml_node_autofilter + parent = lo_document ). + lv_ref = lo_autofilter->get_filter_range( ) . + CONDENSE lv_ref NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_ref + value = lv_ref ). + lt_values = lo_autofilter->get_values( ) . + IF lt_values IS NOT INITIAL. +* If we filter we need to set the filter mode to 1. + lo_element_2 = lo_document->find_from_name( name = lc_xml_node_sheetpr ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_filtermode + value = '1' ). +* Create node filtercolumn + CLEAR lv_column. + LOOP AT lt_values INTO ls_values. + IF ls_values-column <> lv_column. + IF lv_column IS NOT INITIAL. + lo_element_2->append_child( new_child = lo_element_3 ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_filtercolumn + parent = lo_element ). + lv_column = ls_values-column - lo_autofilter->filter_area-col_start. + lv_value = lv_column. + CONDENSE lv_value NO-GAPS. + lo_element_2->set_attribute_ns( name = lc_xml_attr_colid + value = lv_value ). + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_filters + parent = lo_element_2 ). + lv_column = ls_values-column. + ENDIF. + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_filter + parent = lo_element_3 ). + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = ls_values-value ). + lo_element_3->append_child( new_child = lo_element_4 ). " value node + ENDLOOP. + lo_element_2->append_child( new_child = lo_element_3 ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + IF io_worksheet->zif_excel_sheet_protection~protected EQ abap_true. + " sheetProtection node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetprotection + parent = lo_document ). + MOVE io_worksheet->zif_excel_sheet_protection~password TO lv_value. + IF lv_value IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_password + value = lv_value ). + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_protection~auto_filter. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_autofilter + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~delete_columns. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_deletecolumns + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~delete_rows. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_deleterows + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~format_cells. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_formatcells + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~format_columns. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_formatcolumns + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~format_rows. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_formatrows + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~insert_columns. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_insertcolumns + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~insert_hyperlinks. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_inserthyperlinks + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~insert_rows. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_insertrows + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~objects. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_objects + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~pivot_tables. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_pivottables + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~scenarios. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_scenarios + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~select_locked_cells. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_selectlockedcells + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~select_unlocked_cells. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_selectunlockedcell + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~sheet. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_sheet + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~sort. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_sort + value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + " Merged cells + lt_range_merge = io_worksheet->get_merge( ). + IF lt_range_merge IS NOT INITIAL. + lo_element = lo_document->create_simple_element( name = lc_xml_node_mergecells + parent = lo_document ). + DESCRIBE TABLE lt_range_merge LINES merge_count. + lv_value = merge_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + LOOP AT lt_range_merge ASSIGNING <fs_range_merge>. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_mergecell + parent = lo_document ). + + lo_element_2->set_attribute_ns( name = lc_xml_attr_ref + value = <fs_range_merge> ). + lo_element->append_child( new_child = lo_element_2 ). + lo_element_root->append_child( new_child = lo_element ). + io_worksheet->delete_merge( ). + ENDLOOP. + ENDIF. + + " Conditional formatting node + lo_iterator = io_worksheet->get_cond_styles_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style_conditional ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF lo_style_conditional->rule IS INITIAL. + CONTINUE. + ENDIF. + lo_element = lo_document->create_simple_element( name = lc_xml_node_condformatting + parent = lo_document ). + lv_value = lo_style_conditional->get_dimension_range( ) . + lo_element->set_attribute_ns( name = lc_xml_attr_sqref + value = lv_value ). + + " cfRule node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_cfrule + parent = lo_document ). + lv_value = lo_style_conditional->rule. + lo_element_2->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = lo_style_conditional->priority. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_priority + value = lv_value ). + + CASE lo_style_conditional->rule. + " Start >> Databar by Albert Lladanosa + WHEN zcl_excel_style_conditional=>c_rule_databar. + + ls_databar = lo_style_conditional->mode_databar. + + CLEAR lt_cfvo. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_databar + parent = lo_document ). + + MOVE ls_databar-cfvo1_value TO ls_cfvo-value. + MOVE ls_databar-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + MOVE ls_databar-cfvo2_value TO ls_cfvo-value. + MOVE ls_databar-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + LOOP AT lt_cfvo INTO ls_cfvo. + " cfvo node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_cfvo + parent = lo_document ). + lv_value = ls_cfvo-type. + lo_element_4->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = ls_cfvo-value. + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " cfvo node + ENDLOOP. + + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_color + parent = lo_document ). + lv_value = ls_databar-colorrgb. + lo_element_4->set_attribute_ns( name = lc_xml_attr_tabcolor_rgb + value = lv_value ). + + lo_element_3->append_child( new_child = lo_element_4 ). " color node + + lo_element_2->append_child( new_child = lo_element_3 ). " databar node + " End << Databar by Albert Lladanosa + + WHEN zcl_excel_style_conditional=>c_rule_colorscale. + + ls_colorscale = lo_style_conditional->mode_colorscale. + + CLEAR: lt_cfvo, lt_colors. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_colorscale + parent = lo_document ). + + MOVE ls_colorscale-cfvo1_value TO ls_cfvo-value. + MOVE ls_colorscale-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + MOVE ls_colorscale-cfvo2_value TO ls_cfvo-value. + MOVE ls_colorscale-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + MOVE ls_colorscale-cfvo3_value TO ls_cfvo-value. + MOVE ls_colorscale-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + APPEND ls_colorscale-colorrgb1 TO lt_colors. + APPEND ls_colorscale-colorrgb2 TO lt_colors. + APPEND ls_colorscale-colorrgb3 TO lt_colors. + + LOOP AT lt_cfvo INTO ls_cfvo. + + IF ls_cfvo IS INITIAL. + CONTINUE. + ENDIF. + + " cfvo node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_cfvo + parent = lo_document ). + lv_value = ls_cfvo-type. + lo_element_4->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = ls_cfvo-value. + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " cfvo node + ENDLOOP. + LOOP AT lt_colors INTO ls_colors. + + IF ls_colors IS INITIAL. + CONTINUE. + ENDIF. + + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_color + parent = lo_document ). + lv_value = ls_colors-colorrgb. + lo_element_4->set_attribute_ns( name = lc_xml_attr_tabcolor_rgb + value = lv_value ). + + lo_element_3->append_child( new_child = lo_element_4 ). " color node + ENDLOOP. + + lo_element_2->append_child( new_child = lo_element_3 ). " databar node + + WHEN zcl_excel_style_conditional=>c_rule_iconset. + + ls_iconset = lo_style_conditional->mode_iconset. + + CLEAR lt_cfvo. + " iconset node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_iconset + parent = lo_document ). + IF ls_iconset-iconset NE zcl_excel_style_conditional=>c_iconset_3trafficlights. + lv_value = ls_iconset-iconset. + lo_element_3->set_attribute_ns( name = lc_xml_attr_iconset + value = lv_value ). + ENDIF. + + " Set the showValue attribute + lv_value = ls_iconset-showvalue. + lo_element_3->set_attribute_ns( name = lc_xml_attr_showvalue + value = lv_value ). + + CASE ls_iconset-iconset. + WHEN zcl_excel_style_conditional=>c_iconset_3trafficlights2 OR + zcl_excel_style_conditional=>c_iconset_3arrows OR + zcl_excel_style_conditional=>c_iconset_3arrowsgray OR + zcl_excel_style_conditional=>c_iconset_3flags OR + zcl_excel_style_conditional=>c_iconset_3signs OR + zcl_excel_style_conditional=>c_iconset_3symbols OR + zcl_excel_style_conditional=>c_iconset_3symbols2 OR + zcl_excel_style_conditional=>c_iconset_3trafficlights OR + zcl_excel_style_conditional=>c_iconset_3trafficlights2. + MOVE ls_iconset-cfvo1_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo2_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo3_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + WHEN zcl_excel_style_conditional=>c_iconset_4arrows OR + zcl_excel_style_conditional=>c_iconset_4arrowsgray OR + zcl_excel_style_conditional=>c_iconset_4rating OR + zcl_excel_style_conditional=>c_iconset_4redtoblack OR + zcl_excel_style_conditional=>c_iconset_4trafficlights. + MOVE ls_iconset-cfvo1_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo2_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo3_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo4_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo4_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + WHEN zcl_excel_style_conditional=>c_iconset_5arrows OR + zcl_excel_style_conditional=>c_iconset_5arrowsgray OR + zcl_excel_style_conditional=>c_iconset_5quarters OR + zcl_excel_style_conditional=>c_iconset_5rating. + MOVE ls_iconset-cfvo1_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo2_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo3_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo4_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo4_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo5_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo5_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + WHEN OTHERS. + CLEAR lt_cfvo. + ENDCASE. + + LOOP AT lt_cfvo INTO ls_cfvo. + " cfvo node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_cfvo + parent = lo_document ). + lv_value = ls_cfvo-type. + lo_element_4->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = ls_cfvo-value. + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " cfvo node + ENDLOOP. + + + lo_element_2->append_child( new_child = lo_element_3 ). " iconset node + + WHEN zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis = lo_style_conditional->mode_cellis. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_cellis-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + lv_value = ls_cellis-operator. + lo_element_2->set_attribute_ns( name = lc_xml_attr_operator + value = lv_value ). + " formula node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lv_value = ls_cellis-formula. + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " formula node + IF ls_cellis-formula2 IS NOT INITIAL. + lv_value = ls_cellis-formula2. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " 2nd formula node + ENDIF. + + WHEN zcl_excel_style_conditional=>c_rule_expression. + ls_expression = lo_style_conditional->mode_expression. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_expression-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + " formula node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lv_value = ls_expression-formula. + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " formula node + +* begin of ins issue #366 - missing conditional rules: top10 + WHEN zcl_excel_style_conditional=>c_rule_top10. + ls_conditional_top10 = lo_style_conditional->mode_top10. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_conditional_top10-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + lv_value = ls_conditional_top10-topxx_count. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = 'rank' + value = lv_value ). + IF ls_conditional_top10-bottom = 'X'. + lo_element_2->set_attribute_ns( name = 'bottom' + value = '1' ). + ENDIF. + IF ls_conditional_top10-percent = 'X'. + lo_element_2->set_attribute_ns( name = 'percent' + value ='1' ). + ENDIF. + + WHEN zcl_excel_style_conditional=>c_rule_above_average. + ls_conditional_above_avg = lo_style_conditional->mode_above_average. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_conditional_above_avg-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + + IF ls_conditional_above_avg-above_average IS INITIAL. " = below average + lo_element_2->set_attribute_ns( name = 'aboveAverage' + value = '0' ). + ENDIF. + IF ls_conditional_above_avg-equal_average = 'X'. " = equal average also + lo_element_2->set_attribute_ns( name = 'equalAverage' + value = '1' ). + ENDIF. + IF ls_conditional_above_avg-standard_deviation <> 0. " standard deviation instead of value + lv_value = ls_conditional_above_avg-standard_deviation. + lo_element_2->set_attribute_ns( name = 'stdDev' + value = lv_value ). + ENDIF. + +* end of ins issue #366 - missing conditional rules: top10 + + ENDCASE. + + lo_element->append_child( new_child = lo_element_2 ). " cfRule node + + lo_element_root->append_child( new_child = lo_element ). " Conditional formatting node + ENDWHILE. + + IF io_worksheet->get_data_validations_size( ) GT 0. + " dataValidations node + lo_element = lo_document->create_simple_element( name = lc_xml_node_datavalidations + parent = lo_document ). + " Conditional formatting node + lo_iterator = io_worksheet->get_data_validations_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_data_validation ?= lo_iterator->if_object_collection_iterator~get_next( ). + " dataValidation node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_datavalidation + parent = lo_document ). + lv_value = lo_data_validation->type. + lo_element_2->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + IF NOT lo_data_validation->operator IS INITIAL. + lv_value = lo_data_validation->operator. + lo_element_2->set_attribute_ns( name = lc_xml_attr_operator + value = lv_value ). + ENDIF. + IF lo_data_validation->allowblank EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_allowblank + value = lv_value ). + IF lo_data_validation->showinputmessage EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showinputmessage + value = lv_value ). + IF lo_data_validation->showerrormessage EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showerrormessage + value = lv_value ). + IF NOT lo_data_validation->errortitle IS INITIAL. + lv_value = lo_data_validation->errortitle. + lo_element_2->set_attribute_ns( name = lc_xml_attr_errortitle + value = lv_value ). + ENDIF. + IF NOT lo_data_validation->error IS INITIAL. + lv_value = lo_data_validation->error. + lo_element_2->set_attribute_ns( name = lc_xml_attr_error + value = lv_value ). + ENDIF. + IF NOT lo_data_validation->prompttitle IS INITIAL. + lv_value = lo_data_validation->prompttitle. + lo_element_2->set_attribute_ns( name = lc_xml_attr_prompttitle + value = lv_value ). + ENDIF. + IF NOT lo_data_validation->prompt IS INITIAL. + lv_value = lo_data_validation->prompt. + lo_element_2->set_attribute_ns( name = lc_xml_attr_prompt + value = lv_value ). + ENDIF. + lv_cell_row_s = lo_data_validation->cell_row. + CONDENSE lv_cell_row_s. + CONCATENATE lo_data_validation->cell_column lv_cell_row_s INTO lv_value. + IF lo_data_validation->cell_row_to IS NOT INITIAL. + lv_cell_row_s = lo_data_validation->cell_row_to. + CONDENSE lv_cell_row_s. + CONCATENATE lv_value ':' lo_data_validation->cell_column_to lv_cell_row_s INTO lv_value. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_sqref + value = lv_value ). + " formula1 node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula1 + parent = lo_document ). + lv_value = lo_data_validation->formula1. + lo_element_3->set_value( value = lv_value ). + + lo_element_2->append_child( new_child = lo_element_3 ). " formula1 node + " formula2 node + IF NOT lo_data_validation->formula2 IS INITIAL. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula2 + parent = lo_document ). + lv_value = lo_data_validation->formula2. + lo_element_3->set_value( value = lv_value ). + + lo_element_2->append_child( new_child = lo_element_3 ). " formula2 node + ENDIF. + + lo_element->append_child( new_child = lo_element_2 ). " dataValidation node + ENDWHILE. + lo_element_root->append_child( new_child = lo_element ). " dataValidations node + ENDIF. + + " Hyperlinks + DATA: lv_hyperlinks_count TYPE i, + lo_link TYPE REF TO zcl_excel_hyperlink. + + lv_hyperlinks_count = io_worksheet->get_hyperlinks_size( ). + IF lv_hyperlinks_count > 0. + lo_element = lo_document->create_simple_element( name = 'hyperlinks' + parent = lo_document ). + + lo_iterator = io_worksheet->get_hyperlinks_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_link ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lo_element_2 = lo_document->create_simple_element( name = 'hyperlink' + parent = lo_element ). + + lv_value = lo_link->get_ref( ). + lo_element_2->set_attribute_ns( name = 'ref' + value = lv_value ). + + IF lo_link->is_internal( ) = abap_true. + lv_value = lo_link->get_url( ). + lo_element_2->set_attribute_ns( name = 'location' + value = lv_value ). + ELSE. + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element_2->set_attribute_ns( name = 'r:id' + value = lv_value ). + + ENDIF. + + lo_element->append_child( new_child = lo_element_2 ). + ENDWHILE. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + + " PrintOptions + IF io_worksheet->print_gridlines = abap_true OR + io_worksheet->sheet_setup->vertical_centered = abap_true OR + io_worksheet->sheet_setup->horizontal_centered = abap_true. + lo_element = lo_document->create_simple_element( name = 'printOptions' + parent = lo_document ). + + IF io_worksheet->print_gridlines = abap_true. + lo_element->set_attribute_ns( name = lc_xml_attr_gridlines + value = 'true' ). + ENDIF. + + IF io_worksheet->sheet_setup->horizontal_centered = abap_true. + lo_element->set_attribute_ns( name = 'horizontalCentered' + value = 'true' ). + ENDIF. + + IF io_worksheet->sheet_setup->vertical_centered = abap_true. + lo_element->set_attribute_ns( name = 'verticalCentered' + value = 'true' ). + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + " pageMargins node + lo_element = lo_document->create_simple_element( name = lc_xml_node_pagemargins + parent = lo_document ). + + lv_value = io_worksheet->sheet_setup->margin_left. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_left + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_right. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_right + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_top. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_top + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_bottom. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_bottom + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_header. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_header + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_footer. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_footer + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). " pageMargins node + +* pageSetup node + lo_element = lo_document->create_simple_element( name = lc_xml_node_pagesetup + parent = lo_document ). + + IF io_worksheet->sheet_setup->black_and_white IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_blackandwhite + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->cell_comments IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_cellcomments + value = io_worksheet->sheet_setup->cell_comments ). + ENDIF. + + IF io_worksheet->sheet_setup->copies IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->copies. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_copies + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->draft IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_draft + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->errors IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_errors + value = io_worksheet->sheet_setup->errors ). + ENDIF. + + IF io_worksheet->sheet_setup->first_page_number IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->first_page_number. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_firstpagenumber + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->fit_to_page IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->fit_to_height. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_fittoheight + value = lv_value ). + lv_value = io_worksheet->sheet_setup->fit_to_width. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_fittowidth + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->horizontal_dpi IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->horizontal_dpi. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_horizontaldpi + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->orientation IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->orientation. + lo_element->set_attribute_ns( name = lc_xml_attr_orientation + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->page_order IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_pageorder + value = io_worksheet->sheet_setup->page_order ). + ENDIF. + + IF io_worksheet->sheet_setup->paper_height IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->paper_height. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_paperheight + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->paper_size IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->paper_size. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_papersize + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->paper_width IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->paper_width. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_paperwidth + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->scale IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->scale. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_scale + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->use_first_page_num IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_usefirstpagenumber + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->use_printer_defaults IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_useprinterdefaults + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->vertical_dpi IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->vertical_dpi. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_verticaldpi + value = lv_value ). + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). " pageSetup node + +* { headerFooter necessary? > + IF io_worksheet->sheet_setup->odd_header IS NOT INITIAL + OR io_worksheet->sheet_setup->odd_footer IS NOT INITIAL + OR io_worksheet->sheet_setup->diff_oddeven_headerfooter = abap_true. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_headerfooter + parent = lo_document ). + + " Different header/footer for odd/even pages? + IF io_worksheet->sheet_setup->diff_oddeven_headerfooter = abap_true. + lo_element->set_attribute_ns( name = lc_xml_attr_differentoddeven + value = '1' ). + ENDIF. + + " OddHeader + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_odd_header = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_oddheader + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + " OddFooter + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_odd_footer = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_oddfooter + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + " evenHeader + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_even_header = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_evenheader + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + " evenFooter + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_even_footer = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_evenfooter + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + + lo_element_root->append_child( new_child = lo_element ). " headerFooter + + ENDIF. + +* issue #377 pagebreaks + TRY. + create_xl_sheet_pagebreaks( io_document = lo_document + io_parent = lo_element_root + io_worksheet = io_worksheet ) . + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + +* drawing + DATA: lo_drawings TYPE REF TO zcl_excel_drawings. + + lo_drawings = io_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + lo_element = lo_document->create_simple_element( name = lc_xml_node_drawing + parent = lo_document ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element->set_attribute( name = 'r:id' + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + +* tables + DATA lv_table_count TYPE i. + + lv_table_count = io_worksheet->get_tables_size( ). + IF lv_table_count > 0. + lo_element = lo_document->create_simple_element( name = 'tableParts' + parent = lo_document ). + lv_value = lv_table_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = 'count' + value = lv_value ). + + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element_2 = lo_document->create_simple_element( name = 'tablePart' + parent = lo_element ). + lo_element_2->set_attribute_ns( name = 'r:id' + value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + + ENDWHILE. + + 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( ). + +ENDMETHOD. + + + + + + + METHOD create_xl_sheet_pagebreaks. + DATA: lo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks, + lt_pagebreaks TYPE zcl_excel_worksheet_pagebreaks=>tt_pagebreak_at, + lt_rows TYPE HASHED TABLE OF int4 WITH UNIQUE KEY table_line, + lt_columns TYPE HASHED TABLE OF int4 WITH UNIQUE KEY table_line, + + lo_node_rowbreaks TYPE REF TO if_ixml_element, + lo_node_colbreaks TYPE REF TO if_ixml_element, + lo_node_break TYPE REF TO if_ixml_element, + + lv_value TYPE string. + + + FIELD-SYMBOLS: <ls_pagebreak> LIKE LINE OF lt_pagebreaks. + + lo_pagebreaks = io_worksheet->get_pagebreaks( ). + CHECK lo_pagebreaks IS BOUND. + + lt_pagebreaks = lo_pagebreaks->get_all_pagebreaks( ). + CHECK lt_pagebreaks IS NOT INITIAL. " No need to proceed if don't have any pagebreaks. + + lo_node_rowbreaks = io_document->create_simple_element( name = 'rowBreaks' + parent = io_document ). + + lo_node_colbreaks = io_document->create_simple_element( name = 'colBreaks' + parent = io_document ). + + + LOOP AT lt_pagebreaks ASSIGNING <ls_pagebreak>. + +* Count how many rows and columns need to be broken + INSERT <ls_pagebreak>-cell_row INTO TABLE lt_rows. + IF sy-subrc = 0. " New + lv_value = <ls_pagebreak>-cell_row. + CONDENSE lv_value. + + lo_node_break = io_document->create_simple_element( name = 'brk' + parent = io_document ). + lo_node_break->set_attribute( name = 'id' value = lv_value ). + lo_node_break->set_attribute( name = 'man' value = '1' ). " Manual break + lo_node_break->set_attribute( name = 'max' value = '16383' ). " Max columns + + lo_node_rowbreaks->append_child( new_child = lo_node_break ). + ENDIF. + + INSERT <ls_pagebreak>-cell_column INTO TABLE lt_columns. + IF sy-subrc = 0. " New + lv_value = <ls_pagebreak>-cell_column. + CONDENSE lv_value. + + lo_node_break = io_document->create_simple_element( name = 'brk' + parent = io_document ). + lo_node_break->set_attribute( name = 'id' value = lv_value ). + lo_node_break->set_attribute( name = 'man' value = '1' ). " Manual break + lo_node_break->set_attribute( name = 'max' value = '1048575' ). " Max rows + + lo_node_colbreaks->append_child( new_child = lo_node_break ). + ENDIF. + + + ENDLOOP. + + lv_value = lines( lt_rows ). + CONDENSE lv_value. + lo_node_rowbreaks->set_attribute( name = 'count' value = lv_value ). + lo_node_rowbreaks->set_attribute( name = 'manualBreakCount' value = lv_value ). + + lv_value = lines( lt_rows ). + CONDENSE lv_value. + lo_node_colbreaks->set_attribute( name = 'count' value = lv_value ). + lo_node_colbreaks->set_attribute( name = 'manualBreakCount' value = lv_value ). + + + + + io_parent->append_child( new_child = lo_node_rowbreaks ). + io_parent->append_child( new_child = lo_node_colbreaks ). + +ENDMETHOD. + + + + + + METHOD create_xl_sheet_rels. + + +** 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', + lc_xml_attr_target_mode TYPE string VALUE 'TargetMode', + lc_xml_val_external TYPE string VALUE 'External', + " Node namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + lc_xml_node_rid_table_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table', + lc_xml_node_rid_printer_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings', + lc_xml_node_rid_drawing_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', + lc_xml_node_rid_link_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink'. + + 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 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_table TYPE REF TO zcl_excel_table, + lo_link TYPE REF TO zcl_excel_hyperlink. + + DATA: lv_value TYPE string, + lv_relation_id TYPE i, + lv_index_str TYPE string. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + " Add sheet Relationship nodes here + lv_relation_id = 0. + lo_iterator = io_worksheet->get_hyperlinks_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_link ?= lo_iterator->if_object_collection_iterator~get_next( ). + CHECK lo_link->is_internal( ) = abap_false. " issue #340 - don't put internal links here + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_link_tp ). + + lv_value = lo_link->get_url( ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_target_mode + value = lc_xml_val_external ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + +* drawing + DATA: lo_drawings TYPE REF TO zcl_excel_drawings. + + lo_drawings = io_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_drawing_tp ). + + lv_index_str = iv_drawing_index. + CONDENSE lv_index_str NO-GAPS. + MOVE me->c_xl_drawings TO lv_value. + REPLACE 'xl' WITH '..' INTO lv_value. + REPLACE '#' WITH lv_index_str INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_table_tp ). + + lv_value = lo_table->get_name( ). + CONCATENATE '../tables/' lv_value '.xml' INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + +* IF io_worksheet->get_print_settings( )->is_empty( ) = abap_false. +* ADD 1 TO lv_relation_id. +* lv_value = lv_relation_id. +* CONDENSE lv_value. +* CONCATENATE 'rId' lv_value INTO lv_value. +* +* lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship +* parent = lo_document ). +* lo_element->set_attribute_ns( name = lc_xml_attr_id +* value = lv_value ). +* lo_element->set_attribute_ns( name = lc_xml_attr_type +* value = lc_xml_node_rid_printer_tp ). +* +* lv_index_str = iv_printer_index. +* CONDENSE lv_index_str NO-GAPS. +* MOVE me->c_xl_printersettings TO lv_value. +* REPLACE 'xl' WITH '..' INTO lv_value. +* REPLACE '#' WITH lv_index_str INTO lv_value. +* lo_element->set_attribute_ns( name = lc_xml_attr_target +* value = lv_value ). +* +* 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( ). + +ENDMETHOD. + + + + METHOD create_xl_styles. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 dxfs-cellstyles are used in conditional formats: +* CellIs, Expression, top10 ( forthcoming above average as well ) +* create own method to write dsfx-cellstyle to be reuseable by all these +*--------------------------------------------------------------------* + + +** 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', + lc_xml_attr_type TYPE string VALUE 'type', + lc_xml_attr_bottom TYPE string VALUE 'bottom', + lc_xml_attr_top TYPE string VALUE 'top', + lc_xml_attr_right TYPE string VALUE 'right', + lc_xml_attr_left TYPE string VALUE 'left'. + + 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, + ls_conditional_top10 TYPE zexcel_conditional_top10, + + 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_index TYPE i, + lv_align_flag TYPE c. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +*********************************************************************** +* 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 ). + +********************************************************************** +* 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 + 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( ). + + 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. + +* 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. + +* 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. + +* 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. + +* 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. + ELSE. + APPEND ls_protection TO lt_protections. + DESCRIBE TABLE lt_protections LINES ls_cellxfs-protectionid. + ENDIF. + ls_cellxfs-applyprotection = 1. + ENDIF. + 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. + + 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. + 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. +* elseif ls_numfmt-NUMFMT eq 'STD_NDEC'. +* ls_cellxfs-numfmtid = 2. + 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. + +* 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 ). + + IF ls_fill-gradtype IS NOT INITIAL. + "gradient + + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_gradientfill + parent = lo_document ). + IF ls_fill-gradtype-degree IS NOT INITIAL. + lv_value = ls_fill-gradtype-degree. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_degree value = lv_value ). + ENDIF. + IF ls_fill-gradtype-type IS NOT INITIAL. + lv_value = ls_fill-gradtype-type. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_type value = lv_value ). + ENDIF. + IF ls_fill-gradtype-bottom IS NOT INITIAL. + lv_value = ls_fill-gradtype-bottom. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_bottom value = lv_value ). + ENDIF. + IF ls_fill-gradtype-top IS NOT INITIAL. + lv_value = ls_fill-gradtype-top. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_top value = lv_value ). + ENDIF. + IF ls_fill-gradtype-right IS NOT INITIAL. + lv_value = ls_fill-gradtype-right. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_right value = lv_value ). + ENDIF. + IF ls_fill-gradtype-left IS NOT INITIAL. + lv_value = ls_fill-gradtype-left. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_left value = lv_value ). + ENDIF. + + IF ls_fill-gradtype-position3 IS NOT INITIAL. + "create <stop> elements for gradients, we can have 2 or 3 stops in each gradient + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + lv_value = ls_fill-gradtype-position1. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position value = lv_value ). + + 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_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + + lv_value = ls_fill-gradtype-position2. + + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position + value = lv_value ). + + 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_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + + lv_value = ls_fill-gradtype-position3. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position + value = lv_value ). + + 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_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + ELSE. + "create <stop> elements for gradients, we can have 2 or 3 stops in each gradient + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + lv_value = ls_fill-gradtype-position1. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position value = lv_value ). + + 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_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + + lv_value = ls_fill-gradtype-position2. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position + value = lv_value ). + + 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_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + + + + + ELSE. + "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 ). + + IF ls_fill-fgcolor-rgb IS INITIAL AND + ls_fill-fgcolor-indexed EQ zcl_excel_style_color=>c_indexed_not_set AND + ls_fill-fgcolor-theme EQ zcl_excel_style_color=>c_theme_not_set AND + ls_fill-fgcolor-tint IS INITIAL AND ls_fill-bgcolor-indexed EQ zcl_excel_style_color=>c_indexed_sys_foreground. + + " 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 ). + + ENDIF. + ENDIF. + + 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 ). + 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. +* begin of change issue #366 - missing conditional rules: top10, move dfx-styles to own method + WHEN zcl_excel_style_conditional=>c_rule_cellis. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_cellis-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). + + WHEN zcl_excel_style_conditional=>c_rule_expression. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_expression-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). + + + + WHEN zcl_excel_style_conditional=>c_rule_top10. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_top10-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). + + WHEN zcl_excel_style_conditional=>c_rule_above_average. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_above_average-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). +* begin of change issue #366 - missing conditional rules: top10, move dfx-styles to own method + + 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( ). + +ENDMETHOD. + + + + + + + METHOD create_xl_styles_color_node. + DATA: lo_sub_element TYPE REF TO if_ixml_element, + lv_value TYPE string. + + CONSTANTS: 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'. + + "add node only if at least one attribute is set + CHECK is_color-rgb IS NOT INITIAL OR + is_color-indexed <> zcl_excel_style_color=>c_indexed_not_set OR + is_color-theme <> zcl_excel_style_color=>c_theme_not_set OR + is_color-tint IS NOT INITIAL. + + lo_sub_element = io_document->create_simple_element( + name = iv_color_elem_name + parent = io_parent ). + + IF is_color-rgb IS NOT INITIAL. + lv_value = is_color-rgb. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_rgb + value = lv_value ). + ENDIF. + + IF is_color-indexed <> zcl_excel_style_color=>c_indexed_not_set. + lv_value = zcl_excel_common=>number_to_excel_string( is_color-indexed ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_indexed + value = lv_value ). + ENDIF. + + IF is_color-theme <> zcl_excel_style_color=>c_theme_not_set. + lv_value = zcl_excel_common=>number_to_excel_string( is_color-theme ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_theme + value = lv_value ). + ENDIF. + + IF is_color-tint IS NOT INITIAL. + lv_value = zcl_excel_common=>number_to_excel_string( is_color-tint ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_tint + value = lv_value ). + ENDIF. + + io_parent->append_child( new_child = lo_sub_element ). +ENDMETHOD. + + + + + METHOD create_xl_table. + + DATA: lc_xml_node_table TYPE string VALUE 'table', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'id', + lc_xml_attr_name TYPE string VALUE 'name', + lc_xml_attr_display_name TYPE string VALUE 'displayName', + lc_xml_attr_ref TYPE string VALUE 'ref', + lc_xml_attr_totals TYPE string VALUE 'totalsRowShown', + " Node namespace + lc_xml_node_table_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#'. + + 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 TYPE REF TO if_ixml_element, + lo_element2 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, + + lv_table_name TYPE string, + lv_id TYPE i, + lv_match TYPE i, + lv_syindex TYPE char3, + lv_ref TYPE string, + lv_value TYPE string, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lv_num_columns TYPE i, + ls_fieldcat TYPE zexcel_s_fieldcatalog. + + +********************************************************************** +* STEP 1: Create xml + 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 ). + +********************************************************************** +* STEP 3: Create main node table + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_table + parent = lo_document ). + + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_table_ns ). + + lv_id = io_table->get_id( ). + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_id ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + + FIND ALL OCCURRENCES OF REGEX '[^_a-zA-Z0-9]' IN io_table->settings-table_name IGNORING CASE MATCH COUNT lv_match. + IF io_table->settings-table_name IS NOT INITIAL AND lv_match EQ 0. + lv_table_name = io_table->settings-table_name. + ELSE. + lv_table_name = io_table->get_name( ). + ENDIF. + lo_element_root->set_attribute_ns( name = lc_xml_attr_name + value = lv_table_name ). + + lo_element_root->set_attribute_ns( name = lc_xml_attr_display_name + value = lv_table_name ). + + lv_ref = io_table->get_reference( ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_ref + value = lv_ref ). + IF io_table->has_totals( ) = abap_true. + lo_element_root->set_attribute_ns( name = 'totalsRowCount' + value = '1' ). + ELSE. + lo_element_root->set_attribute_ns( name = lc_xml_attr_totals + value = '0' ). + ENDIF. + +********************************************************************** +* STEP 4: Create subnodes + + " autoFilter + IF io_table->settings-nofilters EQ abap_false. + lo_element = lo_document->create_simple_element( name = 'autoFilter' + parent = lo_document ). + + lv_ref = io_table->get_reference( ip_include_totals_row = abap_false ). + lo_element->set_attribute_ns( name = 'ref' + value = lv_ref ). + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + "columns + lo_element = lo_document->create_simple_element( name = 'tableColumns' + parent = lo_document ). + +* lo_columns = io_table->get_columns( ). + LOOP AT io_table->fieldcat INTO ls_fieldcat WHERE dynpfld = abap_true. + ADD 1 TO lv_num_columns. + ENDLOOP. + + lv_value = lv_num_columns. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = 'count' + value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). + + LOOP AT io_table->fieldcat INTO ls_fieldcat WHERE dynpfld = abap_true. + lo_element2 = lo_document->create_simple_element_ns( name = 'tableColumn' + parent = lo_element ). + + lv_value = ls_fieldcat-position. + SHIFT lv_value LEFT DELETING LEADING '0'. + lo_element2->set_attribute_ns( name = 'id' + value = lv_value ). + lv_value = ls_fieldcat-scrtext_l. + lo_element2->set_attribute_ns( name = 'name' + value = lv_value ). + + IF ls_fieldcat-totals_function IS NOT INITIAL. + lo_element2->set_attribute_ns( name = 'totalsRowFunction' + value = ls_fieldcat-totals_function ). + ENDIF. + + lo_element->append_child( new_child = lo_element2 ). + ENDLOOP. + + + lo_element = lo_document->create_simple_element( name = 'tableStyleInfo' + parent = lo_element_root ). + + lo_element->set_attribute_ns( name = 'name' + value = io_table->settings-table_style ). + + lo_element->set_attribute_ns( name = 'showFirstColumn' + value = '0' ). + + lo_element->set_attribute_ns( name = 'showLastColumn' + value = '0' ). + + IF io_table->settings-show_row_stripes = abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + + lo_element->set_attribute_ns( name = 'showRowStripes' + value = lv_value ). + + IF io_table->settings-show_column_stripes = abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + + lo_element->set_attribute_ns( name = 'showColumnStripes' + value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). +********************************************************************** +* 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( ). + +ENDMETHOD. + + + + method CREATE_XL_THEME. + + +* @TODO * + + DATA: lv_xl_theme TYPE string, + lv_xl_theme_01 TYPE string, + lv_xl_theme_02 TYPE string, + lv_xl_theme_03 TYPE string, + lv_xl_theme_04 TYPE string, + lv_xl_theme_05 TYPE string, + lv_xl_theme_06 TYPE string, + lv_xl_theme_07 TYPE string, + lv_xl_theme_08 TYPE string, + lv_xl_theme_09 TYPE string, + lv_xl_theme_10 TYPE string, + lv_xl_theme_11 TYPE string, + lv_xl_theme_12 TYPE string, + lv_xl_theme_13 TYPE string, + lv_xl_theme_14 TYPE string, + lv_xl_theme_15 TYPE string, + lv_xl_theme_16 TYPE string, + lv_xl_theme_17 TYPE string, + lv_xl_theme_18 TYPE string, + lv_xl_theme_19 TYPE string, + lv_xl_theme_20 TYPE string, + lv_xl_theme_21 TYPE string, + lv_xl_theme_22 TYPE string, + lv_xl_theme_23 TYPE string, + lv_xl_theme_24 TYPE string, + lv_xl_theme_25 TYPE string, + lv_xl_theme_26 TYPE string, + lv_xl_theme_27 TYPE string, + lv_xl_theme_28 TYPE string, + lv_xl_theme_29 TYPE string, + lv_xl_theme_30 TYPE string, + lv_xl_theme_31 TYPE string, + lv_xl_theme_32 TYPE string. + + lv_xl_theme_01 = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'. + lv_xl_theme_02 = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme"><a:themeElements><a:clrScheme name="Office"><a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1><a:lt1><a:sysClr val="window" '. + lv_xl_theme_03 = 'lastClr="FFFFFF"/></a:lt1><a:dk2><a:srgbClr val="1F497D"/></a:dk2><a:lt2><a:srgbClr val="EEECE1"/></a:lt2><a:accent1><a:srgbClr val="4F81BD"/></a:accent1><a:accent2><a:srgbClr val="C0504D"/></a:accent2><a:accent3><a:srgbClr '. + lv_xl_theme_04 = 'val="9BBB59"/></a:accent3><a:accent4><a:srgbClr val="8064A2"/></a:accent4><a:accent5><a:srgbClr val="4BACC6"/></a:accent5><a:accent6><a:srgbClr val="F79646"/></a:accent6><a:hlink><a:srgbClr val="0000FF"/></a:hlink><a:folHlink>'. + lv_xl_theme_05 = '<a:srgbClr val="800080"/></a:folHlink></a:clrScheme><a:fontScheme name="Office"><a:majorFont><a:latin typeface="Cambria"/><a:ea typeface=""/><a:cs typeface=""/>'. + lv_xl_theme_06 = '<a:font script="Arab" typeface="Times New Roman"/><a:font script="Hebr" typeface="Times New Roman"/><a:font script="Thai" '. + lv_xl_theme_07 = 'typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="MoolBoran"/><a:font script="Knda" typeface="Tunga"/><a:font '. + lv_xl_theme_08 = 'script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font script="Tibt" '. + lv_xl_theme_09 = 'typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" '. + lv_xl_theme_10 = 'typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" '. + lv_xl_theme_11 = 'typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Times New Roman"/><a:font script="Uigh" typeface="Microsoft Uighur"/></a:majorFont><a:minorFont><a:latin typeface="Calibri"/><a:ea typeface=""/><a:cs typeface=""/>'. + lv_xl_theme_12 = '<a:font script="Arab" typeface="Arial"/><a:font script="Hebr" '. + lv_xl_theme_13 = 'typeface="Arial"/><a:font script="Thai" typeface="Tahoma"/><a:font script="Ethi" typeface="Nyala"/><a:font script="Beng" typeface="Vrinda"/><a:font script="Gujr" typeface="Shruti"/><a:font script="Khmr" typeface="DaunPenh"/><a:font '. + lv_xl_theme_14 = 'script="Knda" typeface="Tunga"/><a:font script="Guru" typeface="Raavi"/><a:font script="Cans" typeface="Euphemia"/><a:font script="Cher" typeface="Plantagenet Cherokee"/><a:font script="Yiii" typeface="Microsoft Yi Baiti"/><a:font '. + lv_xl_theme_15 = 'script="Tibt" typeface="Microsoft Himalaya"/><a:font script="Thaa" typeface="MV Boli"/><a:font script="Deva" typeface="Mangal"/><a:font script="Telu" typeface="Gautami"/><a:font script="Taml" typeface="Latha"/><a:font script="Syrc" '. + lv_xl_theme_16 = 'typeface="Estrangelo Edessa"/><a:font script="Orya" typeface="Kalinga"/><a:font script="Mlym" typeface="Kartika"/><a:font script="Laoo" typeface="DokChampa"/><a:font script="Sinh" typeface="Iskoola Pota"/><a:font script="Mong" '. + lv_xl_theme_17 = 'typeface="Mongolian Baiti"/><a:font script="Viet" typeface="Arial"/><a:font script="Uigh" typeface="Microsoft Uighur"/></a:minorFont></a:fontScheme><a:fmtScheme name="Office"><a:fillStyleLst><a:solidFill><a:schemeClr val="phClr"/>'. + lv_xl_theme_18 = '</a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod '. + lv_xl_theme_19 = 'val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="1"/></a:gradFill><a:gradFill rotWithShape="1">'. + lv_xl_theme_20 = '<a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:shade val="51000"/><a:satMod val="130000"/></a:schemeClr></a:gs><a:gs pos="80000"><a:schemeClr val="phClr"><a:shade val="93000"/><a:satMod val="130000"/></a:schemeClr></a:gs><a:gs '. + lv_xl_theme_21 = 'pos="100000"><a:schemeClr val="phClr"><a:shade val="94000"/><a:satMod val="135000"/></a:schemeClr></a:gs></a:gsLst><a:lin ang="16200000" scaled="0"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w="9525" cap="flat" cmpd="sng" '. + lv_xl_theme_22 = 'algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000"/><a:satMod val="105000"/></a:schemeClr></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr '. + lv_xl_theme_23 = 'val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln><a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln></a:lnStyleLst><a:effectStyleLst>'. + lv_xl_theme_24 = '<a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst>'. + lv_xl_theme_25 = '<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad="40000" '. + lv_xl_theme_26 = 'dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw></a:effectLst><a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0"/></a:camera><a:lightRig '. + lv_xl_theme_27 = 'rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000"/></a:lightRig></a:scene3d><a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val="phClr"/>'. + lv_xl_theme_28 = '</a:solidFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000"/><a:shade '. + lv_xl_theme_29 = 'val="99000"/><a:satMod val="350000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" '. + lv_xl_theme_30 = 't="-80000" r="50000" b="180000"/></a:path></a:gradFill><a:gradFill rotWithShape="1"><a:gsLst><a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs><a:gs pos="100000"><a:schemeClr '. + lv_xl_theme_31 = 'val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs></a:gsLst><a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path></a:gradFill></a:bgFillStyleLst></a:fmtScheme>'. + lv_xl_theme_32 = '</a:themeElements><a:objectDefaults/><a:extraClrSchemeLst/></a:theme>'. + + + CONCATENATE lv_xl_theme_01 lv_xl_theme_02 lv_xl_theme_03 lv_xl_theme_04 lv_xl_theme_05 lv_xl_theme_06 lv_xl_theme_07 lv_xl_theme_08 lv_xl_theme_09 lv_xl_theme_10 lv_xl_theme_11 lv_xl_theme_12 lv_xl_theme_13 lv_xl_theme_14 lv_xl_theme_15 + lv_xl_theme_16 lv_xl_theme_17 lv_xl_theme_18 lv_xl_theme_19 lv_xl_theme_20 lv_xl_theme_21 lv_xl_theme_22 lv_xl_theme_23 lv_xl_theme_24 lv_xl_theme_25 lv_xl_theme_26 lv_xl_theme_27 lv_xl_theme_28 lv_xl_theme_29 lv_xl_theme_30 + lv_xl_theme_31 lv_xl_theme_32 + INTO lv_xl_theme SEPARATED BY space. + + CALL FUNCTION 'SCMS_STRING_TO_XSTRING' + EXPORTING + text = lv_xl_theme + IMPORTING + buffer = ep_content. + + + endmethod. + + + + METHOD create_xl_workbook. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - 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 +* changes: correction of pointer to localSheetId +*--------------------------------------------------------------------* + +** Constant node name + DATA: lc_xml_node_workbook TYPE string VALUE 'workbook', + lc_xml_node_fileversion TYPE string VALUE 'fileVersion', + lc_xml_node_workbookpr TYPE string VALUE 'workbookPr', + lc_xml_node_bookviews TYPE string VALUE 'bookViews', + lc_xml_node_workbookview TYPE string VALUE 'workbookView', + lc_xml_node_sheets TYPE string VALUE 'sheets', + lc_xml_node_sheet TYPE string VALUE 'sheet', + lc_xml_node_calcpr TYPE string VALUE 'calcPr', + lc_xml_node_workbookprotection TYPE string VALUE 'workbookProtection', + lc_xml_node_definednames TYPE string VALUE 'definedNames', + lc_xml_node_definedname TYPE string VALUE 'definedName', + " Node attributes + lc_xml_attr_appname TYPE string VALUE 'appName', + lc_xml_attr_lastedited TYPE string VALUE 'lastEdited', + lc_xml_attr_lowestedited TYPE string VALUE 'lowestEdited', + lc_xml_attr_rupbuild TYPE string VALUE 'rupBuild', + lc_xml_attr_themeversion TYPE string VALUE 'defaultThemeVersion', + lc_xml_attr_xwindow TYPE string VALUE 'xWindow', + lc_xml_attr_ywindow TYPE string VALUE 'yWindow', + lc_xml_attr_windowwidth TYPE string VALUE 'windowWidth', + lc_xml_attr_windowheight TYPE string VALUE 'windowHeight', + lc_xml_attr_activetab TYPE string VALUE 'activeTab', + lc_xml_attr_name TYPE string VALUE 'name', + lc_xml_attr_sheetid TYPE string VALUE 'sheetId', + lc_xml_attr_state TYPE string VALUE 'state', + lc_xml_attr_id TYPE string VALUE 'id', + lc_xml_attr_calcid TYPE string VALUE 'calcId', + lc_xml_attr_lockrevision TYPE string VALUE 'lockRevision', + lc_xml_attr_lockstructure TYPE string VALUE 'lockStructure', + lc_xml_attr_lockwindows TYPE string VALUE 'lockWindows', + lc_xml_attr_revisionspassword TYPE string VALUE 'revisionsPassword', + lc_xml_attr_workbookpassword TYPE string VALUE 'workbookPassword', + lc_xml_attr_hidden TYPE string VALUE 'hidden', + lc_xml_attr_localsheetid TYPE string VALUE 'localSheetId', + " Node namespace + lc_r_ns TYPE string VALUE 'r', + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + lc_xml_node_r_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#'. + + 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 TYPE REF TO if_ixml_element, + lo_element_range TYPE REF TO if_ixml_element, + lo_sub_element 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_iterator_range TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lo_autofilters TYPE REF TO zcl_excel_autofilters, + lo_autofilter TYPE REF TO zcl_excel_autofilter. + + DATA: lv_xml_node_ridx_id TYPE string, + lv_value TYPE string, + lv_syindex TYPE string, + l_guid TYPE uuid, + lv_active_sheet TYPE zexcel_active_worksheet. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + 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 ). + +********************************************************************** +* STEP 3: Create main node + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_workbook + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_r_ns ). + +********************************************************************** +* STEP 4: Create subnode + " fileVersion node + lo_element = lo_document->create_simple_element( name = lc_xml_node_fileversion + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_appname + value = 'xl' ). + lo_element->set_attribute_ns( name = lc_xml_attr_lastedited + value = '4' ). + lo_element->set_attribute_ns( name = lc_xml_attr_lowestedited + value = '4' ). + lo_element->set_attribute_ns( name = lc_xml_attr_rupbuild + value = '4506' ). + lo_element_root->append_child( new_child = lo_element ). + + " fileVersion node + lo_element = lo_document->create_simple_element( name = lc_xml_node_workbookpr + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_themeversion + value = '124226' ). + lo_element_root->append_child( new_child = lo_element ). + + " workbookProtection node + IF me->excel->zif_excel_book_protection~protected EQ abap_true. + lo_element = lo_document->create_simple_element( name = lc_xml_node_workbookprotection + parent = lo_document ). + MOVE me->excel->zif_excel_book_protection~workbookpassword TO lv_value. + IF lv_value IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_workbookpassword + value = lv_value ). + ENDIF. + MOVE me->excel->zif_excel_book_protection~revisionspassword TO lv_value. + IF lv_value IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_revisionspassword + value = lv_value ). + ENDIF. + MOVE me->excel->zif_excel_book_protection~lockrevision TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_lockrevision + value = lv_value ). + MOVE me->excel->zif_excel_book_protection~lockstructure TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_lockstructure + value = lv_value ). + MOVE me->excel->zif_excel_book_protection~lockwindows TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_lockwindows + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + " bookviews node + lo_element = lo_document->create_simple_element( name = lc_xml_node_bookviews + parent = lo_document ). + " bookview node + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_workbookview + parent = lo_document ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_xwindow + value = '120' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_ywindow + value = '120' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_windowwidth + value = '19035' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_windowheight + value = '8445' ). + " Set Active Sheet + lv_active_sheet = excel->get_active_sheet_index( ). +* issue #365 - test if sheet exists - otherwise set active worksheet to 1 + lo_worksheet = excel->get_worksheet_by_index( lv_active_sheet ). + IF lo_worksheet IS NOT BOUND. + lv_active_sheet = 1. + excel->SET_ACTIVE_SHEET_INDEX( lv_active_sheet ). + ENDIF. + IF lv_active_sheet > 1. + lv_active_sheet = lv_active_sheet - 1. + lv_value = lv_active_sheet. + CONDENSE lv_value. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_activetab + value = lv_value ). + ENDIF. + lo_element->append_child( new_child = lo_sub_element )." bookview node + lo_element_root->append_child( new_child = lo_element )." bookviews node + + " sheets node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheets + parent = lo_document ). + lo_iterator = excel->get_worksheets_iterator( ). + + " ranges node + lo_element_range = lo_document->create_simple_element( name = lc_xml_node_definednames " issue 163 + + parent = lo_document ). " issue 163 + + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + " sheet node + 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_value = lo_worksheet->get_title( ). + 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_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_sheetid + value = lv_syindex ). + IF lo_worksheet->zif_excel_sheet_properties~hidden EQ zif_excel_sheet_properties=>c_hidden. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_state + value = 'hidden' ). + ELSEIF lo_worksheet->zif_excel_sheet_properties~hidden EQ zif_excel_sheet_properties=>c_veryhidden. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_state + value = 'veryHidden' ). + ENDIF. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_id + prefix = lc_r_ns + value = lv_xml_node_ridx_id ). + lo_element->append_child( new_child = lo_sub_element ). " sheet node + + " issue 163 >>> + lo_iterator_range = lo_worksheet->get_ranges_iterator( ). + +*--------------------------------------------------------------------* +* Defined names sheetlocal: Ranges, Repeat rows and columns +*--------------------------------------------------------------------* + WHILE lo_iterator_range->if_object_collection_iterator~has_next( ) EQ abap_true. + " range node + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_definedname + parent = lo_document ). + lo_range ?= lo_iterator_range->if_object_collection_iterator~get_next( ). + lv_value = lo_range->name. + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + +* lo_sub_element->set_attribute_ns( name = lc_xml_attr_localsheetid "del #235 Repeat rows/cols - EXCEL starts couting from zero +* value = lv_xml_node_ridx_id ). "del #235 Repeat rows/cols - and needs absolute referencing to localSheetId + lv_value = lv_syindex - 1. "ins #235 Repeat rows/cols + CONDENSE lv_value NO-GAPS. "ins #235 Repeat rows/cols + lo_sub_element->set_attribute_ns( name = lc_xml_attr_localsheetid + value = lv_value ). + + lv_value = lo_range->get_value( ). + lo_sub_element->set_value( value = lv_value ). + lo_element_range->append_child( new_child = lo_sub_element ). " range node + + ENDWHILE. + " issue 163 <<< + + ENDWHILE. + lo_element_root->append_child( new_child = lo_element )." sheets node + + +*--------------------------------------------------------------------* +* Defined names workbookgolbal: Ranges +*--------------------------------------------------------------------* +* " ranges node +* lo_element = lo_document->create_simple_element( name = lc_xml_node_definednames " issue 163 - +* parent = lo_document ). " issue 163 - + lo_iterator = excel->get_ranges_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + " range node + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_definedname + parent = lo_document ). + lo_range ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_value = lo_range->name. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + lv_value = lo_range->get_value( ). + lo_sub_element->set_value( value = lv_value ). + lo_element_range->append_child( new_child = lo_sub_element ). " range node + + ENDWHILE. + +*--------------------------------------------------------------------* +* Defined names - Autofilters ( also sheetlocal ) +*--------------------------------------------------------------------* + lo_autofilters = excel->get_autofilters_reference( ). + IF lo_autofilters->is_empty( ) = abap_false. + lo_iterator = excel->get_worksheets_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_syindex = sy-index - 1 . + l_guid = lo_worksheet->get_guid( ). + lo_autofilter = lo_autofilters->get( i_sheet_guid = l_guid ) . + IF lo_autofilter IS BOUND. + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_definedname + parent = lo_document ). + lv_value = lo_autofilters->c_autofilter. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + lv_value = lv_syindex. + CONDENSE lv_value NO-GAPS. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_localsheetid + value = lv_value ). + lv_value = '1'. " Always hidden + lo_sub_element->set_attribute_ns( name = lc_xml_attr_hidden + value = lv_value ). + lv_value = lo_autofilter->get_filter_reference( ). + lo_sub_element->set_value( value = lv_value ). + lo_element_range->append_child( new_child = lo_sub_element ). " range node + ENDIF. + + ENDWHILE. + ENDIF. + lo_element_root->append_child( new_child = lo_element_range ). " ranges node + + + " calcPr node + lo_element = lo_document->create_simple_element( name = lc_xml_node_calcpr + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_calcid + value = '125725' ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* 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( ). + +ENDMETHOD. + + + + + method FLAG2BOOL. + + + IF ip_flag EQ abap_true. + ep_boolean = 'true'. + ELSE. + ep_boolean = 'false'. + ENDIF. + endmethod. + + + + + METHOD get_shared_string_index. + + + DATA ls_shared_string TYPE zexcel_s_shared_string. + + 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. + + + + + *"* 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_WRITER~WRITE_FILE. + me->excel = io_excel. + ep_file = me->create( ). + endmethod. + + + + method CREATE. + +* .csv format with ; delimiter + + ep_excel = me->CREATE_CSV( ). + + endmethod. + + + + method CREATE_CSV. + + TYPES: BEGIN OF lty_format, + cmpname TYPE SEOCMPNAME, + attvalue TYPE SEOVALUE, + END OF lty_format. + DATA: lt_format TYPE STANDARD TABLE OF lty_format, + ls_format LIKE LINE OF lt_format, + lv_date TYPE DATS, + lv_tmp TYPE string, + lv_time TYPE CHAR08. + + DATA: lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: lt_cell_data TYPE zexcel_t_cell_data_unsorted, + lv_row TYPE sytabix, + lv_col TYPE sytabix, + lv_string TYPE string, + lc_value TYPE string, + lv_attrname TYPE SEOCMPNAME. + + DATA: ls_numfmt TYPE zexcel_s_style_numfmt, + lo_style TYPE REF TO zcl_excel_style. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + +* --- Retrieve supported cell format + REFRESH lt_format. + SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_format + FROM seocompodf + WHERE clsname = 'ZCL_EXCEL_STYLE_NUMBER_FORMAT' + AND typtype = 1 + AND type = 'ZEXCEL_NUMBER_FORMAT'. + +* --- Retrieve SAP date format + CLEAR ls_format. + SELECT ddtext INTO ls_format-attvalue FROM dd07t WHERE domname = 'XUDATFM' + AND ddlanguage = sy-langu. + ls_format-cmpname = 'DATE'. + CONDENSE ls_format-attvalue. + CONCATENATE '''' ls_format-attvalue '''' INTO ls_format-attvalue. + APPEND ls_format TO lt_format. + ENDSELECT. + + + LOOP AT lt_format INTO ls_format. + TRANSLATE ls_format-attvalue TO UPPER CASE. + MODIFY lt_format FROM ls_format. + ENDLOOP. + + +* STEP 1: Collect strings from the first worksheet + lo_iterator = excel->get_worksheets_iterator( ). + data: current_worksheet_title type ZEXCEL_SHEET_TITLE. + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + + IF worksheet_name IS NOT INITIAL. + current_worksheet_title = lo_worksheet->get_title( ). + CHECK current_worksheet_title = worksheet_name. + ELSE. + IF worksheet_index IS INITIAL. + worksheet_index = 1. + ENDIF. + CHECK worksheet_index = sy-index. + ENDIF. + APPEND LINES OF lo_worksheet->sheet_content TO lt_cell_data. + EXIT. " Take first worksheet only + ENDWHILE. + + DELETE lt_cell_data WHERE cell_formula IS NOT INITIAL. " delete formula content + + SORT lt_cell_data BY cell_row + cell_column. + lv_row = 1. + lv_col = 1. + CLEAR lv_string. + LOOP AT lt_cell_data ASSIGNING <fs_sheet_content>. + +* --- Retrieve Cell Style format and data type + CLEAR ls_numfmt. + IF <fs_sheet_content>-data_type IS INITIAL AND <fs_sheet_content>-cell_style IS NOT INITIAL. + 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( ). + CHECK lo_style->get_guid( ) = <fs_sheet_content>-cell_style. + ls_numfmt = lo_style->number_format->get_structure( ). + EXIT. + ENDWHILE. + ENDIF. + IF <fs_sheet_content>-data_type IS INITIAL AND ls_numfmt IS NOT INITIAL. + " determine data-type + CLEAR lv_attrname. + CONCATENATE '''' ls_numfmt-NUMFMT '''' INTO ls_numfmt-NUMFMT. + TRANSLATE ls_numfmt-numfmt TO UPPER CASE. + READ TABLE lt_format INTO ls_format WITH KEY attvalue = ls_numfmt-NUMFMT. + IF sy-subrc = 0. + lv_attrname = ls_format-cmpname. + ENDIF. + + IF lv_attrname IS NOT INITIAL. + FIND FIRST OCCURRENCE OF 'DATETIME' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'd'. + ELSE. + FIND FIRST OCCURRENCE OF 'TIME' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 't'. + ELSE. + FIND FIRST OCCURRENCE OF 'DATE' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'd'. + ELSE. + FIND FIRST OCCURRENCE OF 'CURRENCY' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'n'. + ELSE. + FIND FIRST OCCURRENCE OF 'NUMBER' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'n'. + ELSE. + FIND FIRST OCCURRENCE OF 'PERCENTAGE' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'n'. + ENDIF. " Purcentage + ENDIF. " Number + ENDIF. " Currency + ENDIF. " Date + ENDIF. " TIME + ENDIF. " DATETIME + ENDIF. " lv_attrname IS NOT INITIAL. + ENDIF. " <fs_sheet_content>-data_type IS INITIAL AND ls_numfmt IS NOT INITIAL. + +* --- Add empty rows + WHILE lv_row < <fs_sheet_content>-cell_row. +* CONCATENATE lv_string cl_abap_char_utilities=>newline INTO lv_string. +* CONCATENATE lv_string cl_abap_char_utilities=>cr_lf INTO lv_string. + CONCATENATE lv_string zcl_excel_writer_csv=>eol INTO lv_string. + lv_row = lv_row + 1. + lv_col = 1. + ENDWHILE. + +* --- Add empty columns + WHILE lv_col < <fs_sheet_content>-cell_column. +* CONCATENATE lv_string ';' INTO lv_string. + CONCATENATE lv_string zcl_excel_writer_csv=>delimiter INTO lv_string. + lv_col = lv_col + 1. + ENDWHILE. + +* ----- Use format to determine the data type and display format. + CASE <fs_sheet_content>-data_type. +* WHEN 'n' OR 'N'. +* lc_value = zcl_excel_common=>excel_number_to_string( ip_value = <fs_sheet_content>-cell_value ). + + WHEN 'd' OR 'D'. + lc_value = zcl_excel_common=>excel_string_to_date( ip_value = <fs_sheet_content>-cell_value ). + TRY. + lv_date = lc_value. + CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL' + EXPORTING + DATE_INTERNAL = lv_date + IMPORTING + DATE_EXTERNAL = lv_tmp + EXCEPTIONS + DATE_INTERNAL_IS_INVALID = 1 + OTHERS = 2 + . + IF SY-SUBRC = 0. + lc_value = lv_tmp. + ENDIF. + + CATCH CX_SY_CONVERSION_NO_NUMBER. + + ENDTRY. + + WHEN 't' OR 'T'. + lc_value = zcl_excel_common=>excel_string_to_time( ip_value = <fs_sheet_content>-cell_value ). + write lc_value to lv_time USING EDIT MASK '__:__:__'. + lc_value = lv_time. + WHEN OTHERS. + lc_value = <fs_sheet_content>-cell_value. + + ENDCASE. + +* REPLACE ALL OCCURRENCES OF '"' in lc_value with '""'. + CONCATENATE zcl_excel_writer_csv=>enclosure zcl_excel_writer_csv=>enclosure INTO lv_tmp. + CONDENSE lv_tmp. + REPLACE ALL OCCURRENCES OF zcl_excel_writer_csv=>enclosure in lc_value with lv_tmp. + +* FIND FIRST OCCURRENCE OF ';' IN lc_value. + FIND FIRST OCCURRENCE OF zcl_excel_writer_csv=>delimiter IN lc_value. + IF sy-subrc = 0. + CONCATENATE lv_string zcl_excel_writer_csv=>enclosure lc_value zcl_excel_writer_csv=>enclosure INTO lv_string. + ELSE. + CONCATENATE lv_string lc_value INTO lv_string. + ENDIF. + + ENDLOOP. " AT lt_cell_data + + CLEAR ep_content. + + CALL FUNCTION 'SCMS_STRING_TO_XSTRING' + EXPORTING + TEXT = lv_string +* MIMETYPE = ' ' +* ENCODING = + IMPORTING + BUFFER = ep_content + EXCEPTIONS + FAILED = 1 + OTHERS = 2 + . + + endmethod. + + + + method SET_ACTIVE_SHEET_INDEX. + CLEAR WORKSHEET_NAME. + WORKSHEET_INDEX = i_active_worksheet. + endmethod. + + + + method SET_ACTIVE_SHEET_INDEX_BY_NAME. + CLEAR WORKSHEET_INDEX. + WORKSHEET_NAME = i_worksheet_name. + endmethod. + + + + method SET_DELIMITER. + delimiter = ip_value. + endmethod. + + + + method SET_ENCLOSURE. + zcl_excel_writer_csv=>enclosure = ip_value. + endmethod. + + + + method SET_ENDOFLINE. + zcl_excel_writer_csv=>eol = 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 + + + + + + + + + + + METHOD add_further_data_to_zip. + + super->add_further_data_to_zip( io_zip = io_zip ). + +* Add vbaProject.bin to zip + io_zip->add( name = me->c_xl_vbaproject + content = me->excel->zif_excel_book_vba_project~vbaproject ). + +ENDMETHOD. + + + 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 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 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. + + + + + + + *"* 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. "constructor + method if_message~get_text. + result = error. + endmethod. "if_message~get_text +endclass. "lcx_not_found IMPLEMENTATION + *"* 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_empty_cells 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_shared_string_some_empty 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 `Test1` to out->shared_strings. + append `Test2` to out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>1</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Test2` ). + 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. + append `Test` to out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>1</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_empty_cells. + +* There is no need to store an empty cell in the ABAP worksheet structure + + data: lo_reader type ref to if_sxml_reader, + lo_ex type ref to lcx_not_found, + lv_text type string. + append `` to out->shared_strings. + append `t` to out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>0</v></c>` & + `<c r="A2" t="inlineStr"><is><t></t></is></c>` & + `<c r="A3" t="s"><v>1</v></c>` + ). + + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + + assert_value_equals( iv_row = 1 iv_col = 1 iv_value = `` ). + assert_value_equals( iv_row = 2 iv_col = 1 iv_value = `` ). + assert_value_equals( iv_row = 3 iv_col = 1 iv_value = `t` ). + + endmethod. + +* + 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_c2x type ref to cl_abap_conv_out_ce, + lv_xstring type xstring, + lo_reader type ref to if_sxml_reader, + lt_act type stringtab, + lt_exp type stringtab. + + lo_c2x = cl_abap_conv_out_ce=>create( ). + lo_c2x->convert( exporting data = `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + importing buffer = lv_xstring ). + lo_reader = cl_sxml_string_reader=>create( lv_xstring ). + 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_shared_string_some_empty. + 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/></si>` & + `<si><t>Bravo</t></si></sst>` + ) ). + append : + `` to lt_exp, + `Alpha` to lt_exp, + `` 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_c2x type ref to cl_abap_conv_out_ce, + lv_xstring type xstring, + lo_reader type ref to if_sxml_reader, + lo_ex type ref to lcx_not_found, + lv_text type string. + + lo_c2x = cl_abap_conv_out_ce=>create( ). + lo_c2x->convert( exporting data = `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + importing buffer = lv_xstring ). + lo_reader = cl_sxml_string_reader=>create( lv_xstring ). + 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, + lo_c2x type ref to cl_abap_conv_out_ce, + lv_xstring type xstring. + concatenate `<root><sheetData><row>` iv_xml `</row></sheetData></root>` into lv_full. + lo_c2x = cl_abap_conv_out_ce=>create( ). + lo_c2x->convert( exporting data = lv_full + importing buffer = lv_xstring ). + eo_reader = cl_sxml_string_reader=>create( lv_xstring ). + endmethod. "get_reader +* + method assert_value_equals. + + constants: lc_empty_string type string value is initial. + + field-symbols: <ls_cell_data> type zexcel_s_cell_data, + <lv_value> type string. + + read table worksheet->sheet_content assigning <ls_cell_data> + with table key cell_row = iv_row cell_column = iv_col. + if sy-subrc eq 0. + assign <ls_cell_data>-cell_value to <lv_value>. + else. + assign lc_empty_string to <lv_value>. + endif. + + assert_equals( act = <lv_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. + +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_error type string. + lv_tabix = iv_index + 1. + read table shared_strings into ev_value index lv_tabix. + if sy-subrc ne 0. + concatenate 'Entry ' iv_index ' not found in Shared String Table' into lv_error. + raise exception type lcx_not_found + exporting + error = lv_error. + endif. +endmethod. + + + + + + method GET_STYLE. + + data: lv_tabix type i, + lo_style type ref to zcl_excel_style, + lv_error type string. + + 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. + concatenate 'Entry ' iv_index ' not found in Style Table' into lv_error. + raise exception type lcx_not_found + exporting + error = lv_error. + 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. + check is_cell-value is not initial + or is_cell-formula is not initial + or is_cell-style is not initial. + 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. + + data lv_value type string. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + if io_reader->name eq `t`. + case io_reader->node_type . + when c_element_open . + clear lv_value . + when c_node_value . + lv_value = lv_value && io_reader->value . + when c_element_close . + append lv_value to et_shared_strings. + endcase . + 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_node_value. + case io_reader->name. + when `f`. + ls_cell-formula = io_reader->value. + when `v`. + if ls_cell-datatype eq `s`. + ls_cell-value = get_shared_string( io_reader->value ). + else. + ls_cell-value = io_reader->value. + endif. + when `t` or `is`. + ls_cell-value = io_reader->value. + endcase. + when c_element_close. + case io_reader->name. + when `c`. + put_cell_to_worksheet( is_cell = ls_cell io_worksheet = io_worksheet ). + when `sheetData`. + exit. + endcase. + endcase. + endwhile. + +endmethod. + + + + + + method SKIP_TO. + + data: lv_error type string. + +* 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. + concatenate 'XML error: Didn''t find element <' iv_element_name '>' into lv_error. + raise exception type lcx_not_found + exporting + error = lv_error. + 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 add_pagebreak. + DATA: ls_pagebreak LIKE LINE OF me->mt_pagebreaks. + + ls_pagebreak-cell_row = ip_row. + ls_pagebreak-cell_column = zcl_excel_common=>convert_column2int( ip_column ). + + INSERT ls_pagebreak INTO TABLE me->mt_pagebreaks. + + +ENDMETHOD. + + + + METHOD get_all_pagebreaks. + rt_pagebreaks = me->mt_pagebreaks. +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 guid_create. + + TRY. + rv_guid_16 = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ). + CATCH cx_uuid_error. + ENDTRY. + +*--------------------------------------------------------------------* +* If you are on a release that does not yet have the class cl_system_uuid +* please use the following coding instead which is using the function +* call that was used before but which has been flagged as obsolete +* in newer SAP releases +*--------------------------------------------------------------------* +* +* CALL FUNCTION 'GUID_CREATE' +* IMPORTING +* ev_guid_16 = rv_guid_16. + +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 + 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 + + + + + + + + + + + + + + + + + + + + + METHOD zif_excel_book_properties~initialize. + DATA: lv_timestamp TYPE timestampl. + + me->zif_excel_book_properties~application = 'Microsoft Excel'. + me->zif_excel_book_properties~appversion = '12.0000'. + + GET TIME STAMP FIELD lv_timestamp. + me->zif_excel_book_properties~created = lv_timestamp. + me->zif_excel_book_properties~creator = sy-uname. + me->zif_excel_book_properties~description = zcl_excel=>version. + me->zif_excel_book_properties~modified = lv_timestamp. + me->zif_excel_book_properties~lastmodifiedby = sy-uname. +ENDMETHOD. + + + method ZIF_EXCEL_BOOK_PROTECTION~INITIALIZE. + me->zif_excel_book_protection~protected = zif_excel_book_protection=>c_unprotected. + me->zif_excel_book_protection~lockrevision = zif_excel_book_protection=>c_unlocked. + me->zif_excel_book_protection~lockstructure = zif_excel_book_protection=>c_unlocked. + 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. + + + method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_CODENAME. + me->zif_excel_book_vba_project~codename = ip_codename. + endmethod. + + + method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_CODENAME_PR. + me->zif_excel_book_vba_project~codename_pr = ip_codename_pr. + endmethod. + + + method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_VBAPROJECT. + me->zif_excel_book_vba_project~vbaproject = ip_vbaproject. + endmethod. + + + + + + METHOD add_new_autofilter. +* Check for autofilter reference: new or overwrite; only one per sheet + ro_autofilter = autofilters->add( io_sheet ) . +ENDMETHOD. + + + + + + method ADD_NEW_DRAWING. + DATA: lv_guid TYPE guid_16. +* Create default blank worksheet + CREATE OBJECT eo_drawing + EXPORTING + ip_type = ip_type + ip_title = ip_title. + + CASE ip_type. + WHEN 'image'. + drawings->add( eo_drawing ). + WHEN 'chart'. + charts->add( eo_drawing ). + ENDCASE. + endmethod. + + + + method ADD_NEW_RANGE. +* Create default blank range + CREATE OBJECT eo_range. + ranges->add( eo_range ). + endmethod. + + + + + method ADD_NEW_STYLE. +* Start of deletion # issue 139 - Dateretention of cellstyles +* CREATE OBJECT eo_style. +* styles->add( eo_style ). +* End of deletion # issue 139 - Dateretention of cellstyles +* Start of insertion # issue 139 - Dateretention of cellstyles +* Create default style + CREATE OBJECT eo_style + EXPORTING + ip_guid = ip_guid. + styles->add( eo_style ). + + DATA: style2 TYPE zexcel_s_stylemapping. +* Copy to new representations + style2 = stylemapping_dynamic_style( eo_style ). + INSERT style2 INTO TABLE t_stylemapping1. + INSERT style2 INTO TABLE t_stylemapping2. +* End of insertion # issue 139 - Dateretention of cellstyles + + endmethod. + + + + + + method ADD_NEW_WORKSHEET. + DATA: lv_guid TYPE guid_16. + +* Create default blank worksheet + CREATE OBJECT eo_worksheet + EXPORTING + ip_excel = me + ip_title = ip_title. + + worksheets->add( eo_worksheet ). + worksheets->active_worksheet = worksheets->size( ). + endmethod. + + + METHOD add_static_styles. + " # issue 139 + FIELD-SYMBOLS: <style1> LIKE LINE OF t_stylemapping1, + <style2> LIKE LINE OF t_stylemapping2. + DATA: style TYPE REF TO zcl_excel_style. + + LOOP AT me->t_stylemapping1 ASSIGNING <style1> WHERE added_to_iterator IS INITIAL. + READ TABLE me->t_stylemapping2 ASSIGNING <style2> WITH TABLE KEY guid = <style1>-guid. + CHECK sy-subrc = 0. " Should always be true since these tables are being filled parallel + + style = me->add_new_style( <style1>-guid ). + + zcl_excel_common=>recursive_struct_to_class( EXPORTING i_source = <style1>-complete_style + i_sourcex = <style1>-complete_stylex + CHANGING e_target = style ). + + ENDLOOP. +ENDMETHOD. + + + method CONSTRUCTOR. + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style TYPE REF TO zcl_excel_style. + +* Inizialize instance objects + CREATE OBJECT security. + CREATE OBJECT worksheets. + CREATE OBJECT ranges. + CREATE OBJECT styles. + CREATE OBJECT drawings + EXPORTING + ip_type = zcl_excel_drawing=>type_image. + CREATE OBJECT charts + EXPORTING + ip_type = zcl_excel_drawing=>type_chart. + CREATE OBJECT legacy_palette. + CREATE OBJECT autofilters. + + me->zif_excel_book_protection~initialize( ). + me->zif_excel_book_properties~initialize( ). + + me->add_new_worksheet( ). + me->add_new_style( ). " Standard style + lo_style = me->add_new_style( ). " Standard style with fill gray125 + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_pattern_gray125. + + endmethod. + + + + + METHOD delete_worksheet. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + l_size TYPE i, + lv_errormessage TYPE string. + + l_size = get_worksheets_size( ). + IF l_size = 1. " Only 1 worksheet left --> check whether this is the worksheet to be deleted + lo_worksheet = me->get_worksheet_by_index( 1 ). + IF lo_worksheet = io_worksheet. + lv_errormessage = 'Deleting last remaining worksheet is not allowed'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + ENDIF. + + me->worksheets->remove( io_worksheet ). + +ENDMETHOD. + + + + METHOD delete_worksheet_by_index. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_errormessage TYPE string. + + lo_worksheet = me->get_worksheet_by_index( iv_index ). + IF lo_worksheet IS NOT BOUND. + lv_errormessage = 'Worksheet not existing'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + me->delete_worksheet( lo_worksheet ). + +ENDMETHOD. + + + + METHOD delete_worksheet_by_name. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_errormessage TYPE string. + + lo_worksheet = me->get_worksheet_by_name( iv_title ). + IF lo_worksheet IS NOT BOUND. + lv_errormessage = 'Worksheet not existing'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + me->delete_worksheet( lo_worksheet ). + +ENDMETHOD. + + + + method GET_ACTIVE_SHEET_INDEX. + r_active_worksheet = me->worksheets->active_worksheet. + endmethod. + + + + method GET_ACTIVE_WORKSHEET. + + eo_worksheet = me->worksheets->get( me->worksheets->active_worksheet ). + + endmethod. + + + + method GET_AUTOFILTERS_REFERENCE. + + ro_autofilters = autofilters. + + endmethod. + + + + method GET_DEFAULT_STYLE. + ep_style = me->default_style. + endmethod. + + + + + method GET_DRAWINGS_ITERATOR. + + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + eo_iterator = me->drawings->get_iterator( ). + WHEN zcl_excel_drawing=>type_chart. + eo_iterator = me->charts->get_iterator( ). + WHEN OTHERS. + ENDCASE. + + endmethod. + + + + method GET_NEXT_TABLE_ID. + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lv_tables_count TYPE i. + + lo_iterator = me->get_worksheets_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_tables_count = lo_worksheet->get_tables_size( ). + ADD lv_tables_count TO ep_id. + + ENDWHILE. + + ADD 1 TO ep_id. + + endmethod. + + + + method GET_RANGES_ITERATOR. + + eo_iterator = me->ranges->get_iterator( ). + + endmethod. + + + + + + METHOD get_static_cellstyle_guid. + " # issue 139 + DATA: style LIKE LINE OF me->t_stylemapping1. + + READ TABLE me->t_stylemapping1 INTO style + WITH TABLE KEY dynamic_style_guid = style-guid " no dynamic style --> look for initial guid here + complete_style = ip_cstyle_complete + complete_stylex = ip_cstylex_complete. + IF sy-subrc <> 0. + style-complete_style = ip_cstyle_complete. + style-complete_stylex = ip_cstylex_complete. +* CALL FUNCTION 'GUID_CREATE' +* IMPORTING +* ev_guid_16 = style-guid. + style-guid = zcl_excel_obsolete_func_wrap=>guid_create( ). + INSERT style INTO TABLE me->t_stylemapping1. + INSERT style INTO TABLE me->t_stylemapping2. + + ENDIF. + + ep_guid = style-guid. +ENDMETHOD. + + + + method GET_STYLES_ITERATOR. + + eo_iterator = me->styles->get_iterator( ). + + endmethod. + + + + + + method GET_STYLE_INDEX_IN_STYLES. + DATA: index TYPE syindex. + DATA: lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_style TYPE REF TO zcl_excel_style. + + CHECK ip_guid IS NOT INITIAL. + + + lo_iterator = me->get_styles_iterator( ). + WHILE lo_iterator->has_next( ) = 'X'. + ADD 1 TO index. + lo_style ?= lo_iterator->get_next( ). + IF lo_style->get_guid( ) = ip_guid. + ep_index = index. + EXIT. + ENDIF. + ENDWHILE. + + IF ep_index IS INITIAL. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Index not found'. + else. + SUBTRACT 1 from ep_index. " In excel list starts with "0" + ENDIF. + endmethod. + + + + + + method GET_STYLE_TO_GUID. + " # issue 139 + + READ TABLE me->t_stylemapping2 INTO ep_stylemapping WITH TABLE KEY guid = ip_guid. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'GUID not found'. + ENDIF. + + IF ep_stylemapping-dynamic_style_guid IS NOT INITIAL. + zcl_excel_common=>recursive_class_to_struct( EXPORTING i_source = ep_stylemapping-cl_style + CHANGING e_target = ep_stylemapping-complete_style + e_targetx = ep_stylemapping-complete_stylex ). + ENDIF. + + + endmethod. + + + + method GET_WORKSHEETS_ITERATOR. + + eo_iterator = me->worksheets->get_iterator( ). + + endmethod. + + + + method GET_WORKSHEETS_NAME. + + ep_name = me->worksheets->name. + + endmethod. + + + + METHOD get_worksheets_size. + + ep_size = me->worksheets->size( ). + +ENDMETHOD. + + + + + METHOD get_worksheet_by_index. + + + DATA: lv_index TYPE zexcel_active_worksheet. + + lv_index = iv_index. + eo_worksheet = me->worksheets->get( lv_index ). + +ENDMETHOD. + + + + + METHOD get_worksheet_by_name. + + DATA: lv_index TYPE zexcel_active_worksheet, + l_size TYPE i. + + l_size = get_worksheets_size( ). + + DO l_size TIMES. + lv_index = sy-index. + eo_worksheet = me->worksheets->get( lv_index ). + IF eo_worksheet->get_title( ) = ip_sheet_name. + RETURN. + ENDIF. + ENDDO. + + CLEAR eo_worksheet. + +ENDMETHOD. + + + + + METHOD set_active_sheet_index. + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_errormessage TYPE string. + +*--------------------------------------------------------------------* +* Check whether worksheet exists +*--------------------------------------------------------------------* + lo_worksheet = me->get_worksheet_by_index( i_active_worksheet ). + IF lo_worksheet IS NOT BOUND. + lv_errormessage = 'Worksheet not existing'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + me->worksheets->active_worksheet = i_active_worksheet. + +ENDMETHOD. + + + + METHOD set_active_sheet_index_by_name. + + DATA: ws_it TYPE REF TO cl_object_collection_iterator, + ws TYPE REF TO zcl_excel_worksheet, + lv_title TYPE zexcel_sheet_title, + count TYPE i VALUE 1. + + ws_it = me->worksheets->get_iterator( ). + + WHILE ws_it->if_object_collection_iterator~has_next( ) = abap_true. + ws ?= ws_it->if_object_collection_iterator~get_next( ). + lv_title = ws->get_title( ). + IF lv_title = i_worksheet_name. + me->worksheets->active_worksheet = count. + EXIT. + ENDIF. + count = count + 1. + ENDWHILE. + +ENDMETHOD. + + + + + method SET_DEFAULT_STYLE. + me->default_style = ip_style. + endmethod. + + + + + method STYLEMAPPING_DYNAMIC_STYLE. +" # issue 139 + eo_style2-dynamic_style_guid = ip_style->get_guid( ). + eo_style2-guid = eo_style2-dynamic_style_guid. + eo_style2-added_to_iterator = abap_true. + eo_style2-cl_style = ip_style. + +* don't care about attributes here, since this data may change +* dynamically + + 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 + *"* 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. + METHODS: is_cell_in_range 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 + + METHOD is_cell_in_range. + DATA ep_cell_in_range TYPE abap_bool. + +* Test 1: upper left corner (in range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'B' + ip_row = 2 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_true + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 2: lower right corner (in range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'D' + ip_row = 4 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_true + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 3: left side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'A' + ip_row = 3 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 4: upper side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'C' + ip_row = 1 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 5: right side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'E' + ip_row = 3 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 6: lower side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'C' + ip_row = 5 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + ENDMETHOD. + +ENDCLASS. "lcl_Excel_Common_Test + + + + + + + + + + + + + + + + + + ABAP + + + + + + + + + + + + + + + + + + + + method ASSERT_DIFFERS. + DATA: ls_seoclass TYPE seoclass. + +" Let see >=7.02 + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_differs + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + RECEIVING + assertion_failed = assertion_failed. + ELSE. +" Let see >=7.00 or even lower + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_AUNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_differs + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + RECEIVING + assertion_failed = assertion_failed. + ELSE. +* We do nothing for now not supported + ENDIF. + ENDIF. +endmethod. + + + + + + + + + + + METHOD assert_equals. + DATA: ls_seoclass TYPE seoclass. + + " Let see >=7.02 + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_equals + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + ignore_hash_sequence = ignore_hash_sequence + RECEIVING + assertion_failed = assertion_failed. + ELSE. + " Let see >=7.00 or even lower + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_AUNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_equals + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + ignore_hash_sequence = ignore_hash_sequence + RECEIVING + assertion_failed = assertion_failed. + ELSE. +* We do nothing for now not supported + ENDIF. + ENDIF. +ENDMETHOD. + + + + + + + + METHOD calculate_cell_distance. + + DATA: lv_reference_row TYPE i, + lv_reference_col_alpha TYPE zexcel_cell_column_alpha, + lv_reference_col TYPE i, + lv_current_row TYPE i, + lv_current_col_alpha TYPE zexcel_cell_column_alpha, + lv_current_col TYPE i. + +*--------------------------------------------------------------------* +* Split reference cell into numerical row/column representation +*--------------------------------------------------------------------* + convert_columnrow2column_a_row( EXPORTING + i_columnrow = iv_reference_cell + IMPORTING + e_column = lv_reference_col_alpha + e_row = lv_reference_row ). + lv_reference_col = convert_column2int( lv_reference_col_alpha ). + +*--------------------------------------------------------------------* +* Split current cell into numerical row/column representation +*--------------------------------------------------------------------* + convert_columnrow2column_a_row( EXPORTING + i_columnrow = iv_current_cell + IMPORTING + e_column = lv_current_col_alpha + e_row = lv_current_row ). + lv_current_col = convert_column2int( lv_current_col_alpha ). + +*--------------------------------------------------------------------* +* Calculate row and column difference +* Positive: Current cell below reference cell +* or Current cell right of reference cell +* Negative: Current cell above reference cell +* or Current cell left of reference cell +*--------------------------------------------------------------------* + ev_row_difference = lv_current_row - lv_reference_row. + ev_col_difference = lv_current_col - lv_reference_col. + +ENDMETHOD. + + + + + method CHAR2HEX. + + IF o_conv IS NOT BOUND. + o_conv = cl_abap_conv_out_ce=>create( endian = 'L' + ignore_cerr = abap_true + replacement = '#' ). + ENDIF. + + CALL METHOD o_conv->reset( ). + CALL METHOD o_conv->write( data = i_char ). + r_hex+1 = o_conv->get_buffer( ). " x'65' must be x'0065' + +endmethod. + + + METHOD class_constructor. + c_xlsx_file_filter = 'Excel Workbook (*.xlsx)|*.xlsx|'(005). +ENDMETHOD. + + + + + + METHOD convert_column2alpha. + + DATA: lv_uccpi TYPE i, + lv_text TYPE sychar02, + lv_module TYPE int4, + lv_column TYPE zexcel_cell_column. + +* Propagate zcx_excel if error occurs " issue #155 - less restrictive typing for ip_column + lv_column = convert_column2int( ip_column ). " issue #155 - less restrictive typing for ip_column + +*--------------------------------------------------------------------* +* Check whether column is in allowed range for EXCEL to handle ( 1-16384 ) +*--------------------------------------------------------------------* + IF lv_column > 16384 + OR lv_column < 1. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Index out of bounds'. + ENDIF. + +*--------------------------------------------------------------------* +* Build alpha representation of column +*--------------------------------------------------------------------* + WHILE lv_column GT 0. + + lv_module = ( lv_column - 1 ) MOD 26. + lv_uccpi = 65 + lv_module. + + lv_column = ( lv_column - lv_module ) / 26. + + lv_text = cl_abap_conv_in_ce=>uccpi( lv_uccpi ). + CONCATENATE lv_text ep_column INTO ep_column. + + ENDWHILE. + +ENDMETHOD. + + + + + + METHOD convert_column2int. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-12-29 +* - ... +* changes: renaming variables to naming conventions +* removing unused variables +* removing commented out code that is inactive for more then half a year +* message made to support multilinguality +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* +* issue#246 - error converting lower case column names +* - 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 +* adding missing exception if input contains +* illegal characters like german umlauts +*--------------------------------------------------------------------* + + DATA: lv_column TYPE zexcel_cell_column_alpha, + lv_column_c TYPE char10, + lv_column_s TYPE string, + lv_errormessage TYPE string, " Can't pass '...'(abc) to exception-class + lv_modulo TYPE i. + +*--------------------------------------------------------------------* +* This module tries to identify which column a user wants to access +* Numbers as input are just passed back, anything else will be converted +* using EXCEL nomenclatura A = 1, AA = 27, ..., XFD = 16384 +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* Normalize input ( upper case , no gaps ) +*--------------------------------------------------------------------* + lv_column_c = ip_column. +* TRANSLATE lv_column TO UPPER CASE. " Fix #246 + TRANSLATE lv_column_c TO UPPER CASE. " Fix #246 + CONDENSE lv_column_c NO-GAPS. + IF lv_column_c EQ ''. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + +*--------------------------------------------------------------------* +* If a number gets passed, just convert it to an integer and return +* the converted value +*--------------------------------------------------------------------* + TRY. + IF lv_column_c CO '1234567890 '. " Fix #164 + ep_column = lv_column_c. " Fix #164 +*--------------------------------------------------------------------* +* Maximum column for EXCEL: XFD = 16384 " if anyone has a reference for this information - please add here instead of this comment +*--------------------------------------------------------------------* + IF ep_column > 16384 OR ep_column < 1. + lv_errormessage = 'Index out of bounds'(004). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + EXIT. + ENDIF. + CATCH cx_sy_conversion_no_number. "#EC NO_HANDLER + " Try the character-approach if approach via number has failed + ENDTRY. + +*--------------------------------------------------------------------* +* Raise error if unexpected characters turns up +*--------------------------------------------------------------------* + lv_column_s = lv_column_c. + IF lv_column_s CN sy-abcde. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + +*--------------------------------------------------------------------* +* Interpret input as number to base 26 with A=1, ... Z=26 +* Raise error if unexpected character turns up +*--------------------------------------------------------------------* +* 1st character +*--------------------------------------------------------------------* + lv_column = lv_column_c. + lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+0(1) ) MOD zcl_excel_common=>c_excel_col_module. + IF lv_modulo < 1 OR lv_modulo > 26. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + ep_column = lv_modulo. " Leftmost digit + +*--------------------------------------------------------------------* +* 2nd character if present +*--------------------------------------------------------------------* + CHECK lv_column+1(1) IS NOT INITIAL. " No need to continue if string ended + lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+1(1) ) MOD zcl_excel_common=>c_excel_col_module. + IF lv_modulo < 1 OR lv_modulo > 26. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + ep_column = 26 * ep_column + lv_modulo. " if second digit is present first digit is for 26^1 + +*--------------------------------------------------------------------* +* 3rd character if present +*--------------------------------------------------------------------* + CHECK lv_column+2(1) IS NOT INITIAL. " No need to continue if string ended + lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+2(1) ) MOD zcl_excel_common=>c_excel_col_module. + IF lv_modulo < 1 OR lv_modulo > 26. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + ep_column = 26 * ep_column + lv_modulo. " if third digit is present first digit is for 26^2 and second digit for 26^1 + +*--------------------------------------------------------------------* +* Maximum column for EXCEL: XFD = 16384 " if anyone has a reference for this information - please add here instead of this comment +*--------------------------------------------------------------------* + IF ep_column > 16384 OR ep_column < 1. + lv_errormessage = 'Index out of bounds'(004). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + +ENDMETHOD. + + + + + + method CONVERT_COLUMNROW2COLUMN_A_ROW. +*--------------------------------------------------------------------* + "issue #256 - replacing char processing with regex +*--------------------------------------------------------------------* +* Stefan Schmöcker, 2013-08-11 +* Allow input to be CLIKE instead of STRING +*--------------------------------------------------------------------* + + DATA: pane_cell_row_a TYPE string, + lv_columnrow type string. + + lv_columnrow = i_columnrow. " Get rid of trailing blanks + + FIND REGEX '^(\D+)(\d+)$' IN lv_columnrow SUBMATCHES e_column + pane_cell_row_a. + e_row = pane_cell_row_a. + +endmethod. + + + + + + + + + + method CONVERT_RANGE2COLUMN_A_ROW. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-12-07 +* - ... +* changes: renaming variables to naming conventions +* aligning code +* added exceptionclass +* added errorhandling for invalid range +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* +* issue#241 - error when sheetname contains "!" +* - sheetname should be returned unescaped +* - 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 +* changes: i_range changed to clike +* e_sheet changed to clike +*--------------------------------------------------------------------* + + DATA: lv_sheet TYPE string, + lv_range TYPE string, + lv_columnrow_start TYPE string, + lv_columnrow_end TYPE string, + lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + + +*--------------------------------------------------------------------* +* Split input range into sheetname and Area +* 4 cases - a) input empty --> nothing to do +* - b) sheetname existing - starts with ' example 'Sheet 1'!$B$6:$D$13 +* - c) sheetname existing - does not start with ' example Sheet1!$B$6:$D$13 +* - d) no sheetname - just area example $B$6:$D$13 +*--------------------------------------------------------------------* +* Initialize output parameters + CLEAR: e_column_start, + e_column_end, + e_row_start, + e_row_end, + e_sheet. + + IF i_range IS INITIAL. " a) input empty --> nothing to do + EXIT. + + ELSEIF i_range(1) = `'`. " b) sheetname existing - starts with ' + FIND REGEX '\![^\!]*$' IN i_range MATCH OFFSET sy-fdpos. " Find last ! + IF sy-subrc = 0. + lv_sheet = i_range(sy-fdpos). + ADD 1 TO sy-fdpos. + lv_range = i_range. + SHIFT lv_range LEFT BY sy-fdpos PLACES. + ELSE. + lv_errormessage = 'Invalid range'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ELSEIF i_range CS '!'. " c) sheetname existing - does not start with ' + SPLIT i_range AT '!' INTO lv_sheet lv_range. + + ELSE. " d) no sheetname - just area + lv_range = i_range. + ENDIF. + + REPLACE ALL OCCURRENCES OF '$' IN lv_range WITH ''. + SPLIT lv_range AT ':' INTO lv_columnrow_start lv_columnrow_end. + + convert_columnrow2column_a_row( EXPORTING + i_columnrow = lv_columnrow_start + IMPORTING + e_column = e_column_start + e_row = e_row_start ). + convert_columnrow2column_a_row( EXPORTING + i_columnrow = lv_columnrow_end + IMPORTING + e_column = e_column_end + e_row = e_row_end ). + + e_sheet = unescape_string( lv_sheet ). " Return in unescaped form +endmethod. + + + + + method DATE_TO_EXCEL_STRING. + DATA: lv_date_diff TYPE i. + + CHECK ip_value IS NOT INITIAL. + " Needed hack caused by the problem that: + " Excel 2000 incorrectly assumes that the year 1900 is a leap year + " http://support.microsoft.com/kb/214326/en-us + IF ip_value > c_excel_1900_leap_year. + lv_date_diff = ip_value - c_excel_baseline_date + 2. + ELSE. + 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. + + + + + method DESCRIBE_STRUCTURE. + DATA: lt_components TYPE abap_component_tab, + lt_comps TYPE abap_component_tab, + lo_struct TYPE REF TO cl_abap_structdescr, + ls_component TYPE abap_componentdescr, + lo_elemdescr TYPE REF TO cl_abap_elemdescr, + ls_dfies TYPE dfies, + l_position TYPE tabfdpos. + + "for DDIC structure get the info directly + IF io_struct->is_ddic_type( ) = abap_true. + rt_dfies = io_struct->get_ddic_field_list( ). + ELSE. + lt_components = io_struct->get_components( ). + + LOOP AT lt_components INTO ls_component. + structure_case( EXPORTING is_component = ls_component + CHANGING xt_components = lt_comps ) . + ENDLOOP. + LOOP AT lt_comps INTO ls_component. + CLEAR ls_dfies. + IF ls_component-type->kind = cl_abap_typedescr=>kind_elem. "E Elementary Type + ADD 1 TO l_position. + lo_elemdescr ?= ls_component-type. + IF lo_elemdescr->is_ddic_type( ) = abap_true. + ls_dfies = lo_elemdescr->get_ddic_field( ). + ls_dfies-fieldname = ls_component-name. + ls_dfies-position = l_position. + ELSE. + ls_dfies-fieldname = ls_component-name. + ls_dfies-position = l_position. + ls_dfies-inttype = lo_elemdescr->type_kind. + ls_dfies-leng = lo_elemdescr->length. + ls_dfies-outputlen = lo_elemdescr->length. + ls_dfies-decimals = lo_elemdescr->decimals. + ls_dfies-fieldtext = ls_component-name. + ls_dfies-reptext = ls_component-name. + ls_dfies-scrtext_s = ls_component-name. + ls_dfies-scrtext_m = ls_component-name. + ls_dfies-scrtext_l = ls_component-name. + ls_dfies-dynpfld = abap_true. + ENDIF. + INSERT ls_dfies INTO TABLE rt_dfies. + ENDIF. + ENDLOOP. + ENDIF. +endmethod. + + + + + + + + METHOD determine_resulting_formula. + + DATA: lv_row_difference TYPE i, + lv_col_difference TYPE i. + +*--------------------------------------------------------------------* +* Calculate distance of reference and current cell +*--------------------------------------------------------------------* + calculate_cell_distance( EXPORTING + iv_reference_cell = iv_reference_cell + iv_current_cell = iv_current_cell + IMPORTING + ev_row_difference = lv_row_difference + ev_col_difference = lv_col_difference ). + +*--------------------------------------------------------------------* +* and shift formula by using the row- and columndistance +*--------------------------------------------------------------------* + ev_resulting_formula = shift_formula( iv_reference_formula = iv_reference_formula + iv_shift_rows = lv_row_difference + iv_shift_cols = lv_col_difference ). + +ENDMETHOD. "determine_resulting_formula + + + + + method ENCRYPT_PASSWORD. + + DATA lv_curr_offset TYPE i. + DATA lv_curr_char TYPE c LENGTH 1. + DATA lv_curr_hex TYPE zexcel_pwd_hash. + DATA lv_pwd_len TYPE zexcel_pwd_hash. + DATA lv_pwd_hash TYPE zexcel_pwd_hash. + + CONSTANTS: + lv_0x7fff TYPE zexcel_pwd_hash VALUE '7FFF', + lv_0x0001 TYPE zexcel_pwd_hash VALUE '0001', + lv_0xce4b TYPE zexcel_pwd_hash VALUE 'CE4B'. + + DATA lv_pwd TYPE zexcel_aes_password. + + lv_pwd = i_pwd(15). + + lv_pwd_len = STRLEN( lv_pwd ). + lv_curr_offset = lv_pwd_len - 1. + + WHILE lv_curr_offset GE 0. + + lv_curr_char = lv_pwd+lv_curr_offset(1). + lv_curr_hex = char2hex( lv_curr_char ). + + lv_pwd_hash = ( shr14( lv_pwd_hash ) BIT-AND lv_0x0001 ) BIT-OR ( shl01( lv_pwd_hash ) BIT-AND lv_0x7fff ). + + lv_pwd_hash = lv_pwd_hash BIT-XOR lv_curr_hex. + SUBTRACT 1 FROM lv_curr_offset. + ENDWHILE. + + lv_pwd_hash = ( shr14( lv_pwd_hash ) BIT-AND lv_0x0001 ) BIT-OR ( shl01( lv_pwd_hash ) BIT-AND lv_0x7fff ). + lv_pwd_hash = lv_pwd_hash BIT-XOR lv_0xce4b. + lv_pwd_hash = lv_pwd_hash BIT-XOR lv_pwd_len. + + WRITE lv_pwd_hash TO r_encrypted_pwd. + +endmethod. + + + + + method ESCAPE_STRING. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - 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 +* 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 +* changes: ip_value changed to clike +*--------------------------------------------------------------------* + DATA: lv_value TYPE string. + +*--------------------------------------------------------------------* +* There exist various situations when a space will be used to separate +* different parts of a string. When we have a string consisting spaces +* that will cause errors unless we "escape" the string by putting ' at +* the beginning and at the end of the string. +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* When allowing clike-input parameters we might encounter trailing +* "real" blanks . These are automatically eliminated when moving +* the input parameter to a string. +* Now any remaining spaces ( white-spaces or normal spaces ) should +* trigger the escaping as well as any ' +*--------------------------------------------------------------------* + lv_value = ip_value. + + + FIND REGEX `\s|'` IN lv_value. " \s finds regular and white spaces + IF sy-subrc = 0. + REPLACE ALL OCCURRENCES OF `'` IN lv_value WITH `''`. + CONCATENATE `'` lv_value `'` INTO lv_value . + ENDIF. + + ep_escaped_value = lv_value. + +endmethod. + + + + + + method EXCEL_STRING_TO_DATE. + DATA: lv_date_int TYPE i. + + TRY. + lv_date_int = ip_value. + ep_value = lv_date_int + c_excel_baseline_date - 2. + " Needed hack caused by the problem that: + " Excel 2000 incorrectly assumes that the year 1900 is a leap year + " http://support.microsoft.com/kb/214326/en-us + IF ep_value < c_excel_1900_leap_year. + ep_value = ep_value + 1. + ENDIF. + CATCH cx_sy_conversion_error. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Index out of bounds'. + ENDTRY. +endmethod. + + + + + + method EXCEL_STRING_TO_NUMBER. + +* If we encounter anything more complicated in EXCEL we might have to extend this +* But currently this works fine - even for numbers in scientific notation + + ep_value = ip_value. + +endmethod. + + + + + + method EXCEL_STRING_TO_TIME. + DATA: lv_seconds_in_day TYPE i, + lv_day_fraction TYPE f, + lc_seconds_in_day TYPE i VALUE 86400. + + TRY. + + lv_day_fraction = ip_value. + lv_seconds_in_day = lv_day_fraction * lc_seconds_in_day. + + ep_value = lv_seconds_in_day. + + CATCH cx_sy_conversion_error. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret time'. + ENDTRY. +endmethod. + + + + + + + method FAIL. + DATA: ls_seoclass TYPE seoclass. + + " Let see >=7.02 + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>fail + EXPORTING + msg = msg + level = level + quit = quit + detail = detail. + ELSE. + " Let see >=7.00 or even lower + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_AUNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>fail + EXPORTING + msg = msg + level = level + quit = quit + detail = detail. + ELSE. +* We do nothing for now not supported + ENDIF. + ENDIF. + +endmethod. + + + + + method GET_FIELDCATALOG. + DATA: lr_dref_tab TYPE REF TO data, + lo_salv_table TYPE REF TO cl_salv_table, + lo_salv_columns_table TYPE REF TO cl_salv_columns_table, + lt_salv_t_column_ref TYPE salv_t_column_ref, + ls_salv_t_column_ref LIKE LINE OF lt_salv_t_column_ref, + lo_salv_column_table TYPE REF TO cl_salv_column_table. + + FIELD-SYMBOLS: <tab> TYPE STANDARD TABLE. + FIELD-SYMBOLS: <fcat> LIKE LINE OF ep_fieldcatalog. + +* Get copy of IP_TABLE-structure <-- must be changeable to create salv + CREATE DATA lr_dref_tab LIKE ip_table. + ASSIGN lr_dref_tab->* TO <tab>. +* Create salv --> implicitly create fieldcat + TRY. + cl_salv_table=>factory( IMPORTING + r_salv_table = lo_salv_table + CHANGING + t_table = <tab> ). + lo_salv_columns_table = lo_salv_table->get_columns( ). + lt_salv_t_column_ref = lo_salv_columns_table->get( ). + CATCH cx_root. +* maybe some errorhandling here - just haven't made up my mind yet + ENDTRY. + +* Loop through columns and set relevant fields ( fieldname, texts ) + LOOP AT lt_salv_t_column_ref INTO ls_salv_t_column_ref. + + lo_salv_column_table ?= ls_salv_t_column_ref-r_column. + APPEND INITIAL LINE TO ep_fieldcatalog ASSIGNING <fcat>. + <fcat>-position = sy-tabix. + <fcat>-fieldname = ls_salv_t_column_ref-columnname. + <fcat>-scrtext_s = ls_salv_t_column_ref-r_column->get_short_text( ). + <fcat>-scrtext_m = ls_salv_t_column_ref-r_column->get_medium_text( ). + <fcat>-scrtext_l = ls_salv_t_column_ref-r_column->get_long_text( ). + + <fcat>-dynpfld = 'X'. " What in the world would we exclude here? + IF <fcat>-position = 1. " except for the MANDT-field of most tables ( 1st column that is ) + IF lo_salv_column_table->get_ddic_datatype( ) = 'CLNT'. + CLEAR <fcat>-dynpfld. + ENDIF. + ENDIF. + +* For fields that don't a description ( i.e. defined by "field type i," ) +* just use the fieldname as description - that is better than nothing + IF <fcat>-scrtext_s IS INITIAL + AND <fcat>-scrtext_m IS INITIAL + AND <fcat>-scrtext_l IS INITIAL. + CONCATENATE 'Col:' <fcat>-fieldname INTO <fcat>-scrtext_l SEPARATED BY space. + <fcat>-scrtext_m = <fcat>-scrtext_l. + <fcat>-scrtext_s = <fcat>-scrtext_l. + ENDIF. + + ENDLOOP. + +endmethod. + + + + + + + + method IS_CELL_IN_RANGE. + DATA lv_column_start TYPE zexcel_cell_column_alpha. + DATA lv_column_end TYPE zexcel_cell_column_alpha. + DATA lv_row_start TYPE zexcel_cell_row. + DATA lv_row_end TYPE zexcel_cell_row. + DATA lv_column_start_i TYPE zexcel_cell_column. + DATA lv_column_end_i TYPE zexcel_cell_column. + DATA lv_column_i TYPE zexcel_cell_column. + + +* Split range and convert columns + convert_range2column_a_row( + exporting + i_range = ip_range + IMPORTING + e_column_start = lv_column_start + e_column_end = lv_column_end + e_row_start = lv_row_start + e_row_end = lv_row_end ). + + lv_column_start_i = convert_column2int( ip_column = lv_column_start ). + lv_column_end_i = convert_column2int( ip_column = lv_column_end ). + + lv_column_i = convert_column2int( ip_column = ip_column ). + +* Check if cell is in range + IF lv_column_i >= lv_column_start_i AND + lv_column_i <= lv_column_end_i AND + ip_row >= lv_row_start AND + ip_row <= lv_row_end. + rp_in_range = abap_true. + ENDIF. +endmethod. + + + + + method NUMBER_TO_EXCEL_STRING. + DATA: lv_value_c TYPE c LENGTH 100. + + WRITE ip_value TO lv_value_c EXPONENT 0 NO-GROUPING NO-SIGN. + REPLACE ALL OCCURRENCES OF ',' IN lv_value_c WITH '.'. + + ep_value = lv_value_c. + CONDENSE ep_value. + + IF ip_value < 0. + CONCATENATE '-' ep_value INTO ep_value. + ELSEIF ip_value EQ 0. + ep_value = '0'. + ENDIF. +endmethod. + + + + + + method RECURSIVE_CLASS_TO_STRUCT. + " # issue 139 +* is working for me - but after looking through this coding I guess +* I'll rewrite this to a version w/o recursion +* This is private an no one using it so far except me, so no need to hurry + DATA: descr TYPE REF TO cl_abap_structdescr, + wa_component LIKE LINE OF descr->components, + attribute_name TYPE fieldname, + flag_class TYPE flag, + o_border TYPE REF TO zcl_excel_style_border. + + FIELD-SYMBOLS: <field> TYPE any, + <fieldx> TYPE any, + <class> TYPE REF TO object, + <attribute> TYPE any. + + + descr ?= cl_abap_structdescr=>describe_by_data( e_target ). + + LOOP AT descr->components INTO wa_component. + +* Assign structure and X-structure + ASSIGN COMPONENT wa_component-name OF STRUCTURE e_target TO <field>. + ASSIGN COMPONENT wa_component-name OF STRUCTURE e_targetx TO <fieldx>. +* At least one field in the structure should be marked - otherwise continue with next field + CLEAR flag_class. +* maybe source is just a structure - try assign component... + ASSIGN COMPONENT wa_component-name OF STRUCTURE i_source TO <attribute>. + IF sy-subrc <> 0. +* not - then it is an attribute of the class - use different assign then + CONCATENATE 'i_source->' wa_component-name INTO attribute_name. + ASSIGN (attribute_name) TO <attribute>. + IF sy-subrc <> 0. + EXIT. + ENDIF. " Should not happen if structure is built properly - otherwise just exit to create no dumps + flag_class = abap_true. + ENDIF. + + CASE wa_component-type_kind. + WHEN cl_abap_structdescr=>typekind_struct1 OR cl_abap_structdescr=>typekind_struct2. " Structure --> use recursio +* IF flag_class = abap_true. +** Only borders will be passed as unbound references. But since we want to set a value we have to create an instance +* ENDIF. + zcl_excel_common=>recursive_class_to_struct( EXPORTING i_source = <attribute> + CHANGING e_target = <field> + e_targetx = <fieldx> ). + WHEN OTHERS. + <field> = <attribute>. + <fieldx> = abap_true. + + ENDCASE. + ENDLOOP. + +endmethod. + + + + + + METHOD recursive_struct_to_class. + " # issue 139 +* is working for me - but after looking through this coding I guess +* I'll rewrite this to a version w/o recursion +* This is private an no one using it so far except me, so no need to hurry + DATA: descr TYPE REF TO cl_abap_structdescr, + wa_component LIKE LINE OF descr->components, + attribute_name TYPE fieldname, + flag_class TYPE flag, + o_border TYPE REF TO zcl_excel_style_border. + + FIELD-SYMBOLS: <field> TYPE any, + <fieldx> TYPE any, + <class> TYPE REF TO object, + <attribute> TYPE any, + <attribute_s> TYPE ANY TABLE. + + + descr ?= cl_abap_structdescr=>describe_by_data( i_source ). + + LOOP AT descr->components INTO wa_component. + +* Assign structure and X-structure + ASSIGN COMPONENT wa_component-name OF STRUCTURE i_source TO <field>. + ASSIGN COMPONENT wa_component-name OF STRUCTURE i_sourcex TO <fieldx>. +* At least one field in the structure should be marked - otherwise continue with next field + CHECK <fieldx> CA abap_true. + CLEAR flag_class. +* maybe target is just a structure - try assign component... + ASSIGN COMPONENT wa_component-name OF STRUCTURE e_target TO <attribute>. + IF sy-subrc <> 0. +* not - then it is an attribute of the class - use different assign then + CONCATENATE 'E_TARGET->' wa_component-name INTO attribute_name. + ASSIGN (attribute_name) TO <attribute>. + IF sy-subrc <> 0.EXIT.ENDIF. " Should not happen if structure is built properly - otherwise just exit to create no dumps + flag_class = abap_true. + ENDIF. + + CASE wa_component-type_kind. + WHEN cl_abap_structdescr=>typekind_struct1 OR cl_abap_structdescr=>typekind_struct2. " Structure --> use recursion + " To avoid dump with attribute GRADTYPE of class ZCL_EXCEL_STYLE_FILL + " quick and really dirty fix -> check the attribute name + " Border has to be initialized somewhere else + IF wa_component-name EQ 'GRADTYPE'. + flag_class = abap_false. + ENDIF. + + IF flag_class = abap_true AND <attribute> IS INITIAL. +* Only borders will be passed as unbound references. But since we want to set a value we have to create an instance + CREATE OBJECT o_border. + <attribute> = o_border. + ENDIF. + zcl_excel_common=>recursive_struct_to_class( EXPORTING i_source = <field> + i_sourcex = <fieldx> + CHANGING e_target = <attribute> ). +* WHEN cl_abap_structdescr=>typekind_struct2. " String +* CHECK <fieldx> = abap_true. " Marked for change +* <attribute_s> = <field>. + WHEN OTHERS. + CHECK <fieldx> = abap_true. " Marked for change + <attribute> = <field>. + + ENDCASE. + ENDLOOP. + +ENDMETHOD. + + + + + + + + METHOD shift_formula. + + CONSTANTS: lcv_operators TYPE string VALUE '+-/*^%=<>&, !', + lcv_letters TYPE string VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ$', + lcv_digits TYPE string VALUE '0123456789', + lcv_cell_reference_error TYPE string VALUE '#REF!'. + + DATA: lv_tcnt TYPE i, " Counter variable + lv_tlen TYPE i, " Temp variable length + lv_cnt TYPE i, " Counter variable + lv_cnt2 TYPE i, " Counter variable + lv_offset1 TYPE i, " Character offset + lv_numchars TYPE i, " Number of characters counter + lv_tchar(1) TYPE c, " Temp character + lv_tchar2(1) TYPE c, " Temp character + lv_cur_form(2000) TYPE c, " Formula for current cell + lv_ref_cell_addr TYPE string, " Reference cell address + lv_tcol1 TYPE string, " Temp column letter + lv_tcol2 TYPE string, " Temp column letter + lv_tcoln TYPE i, " Temp column number + lv_trow1 TYPE string, " Temp row number + lv_trow2 TYPE string, " Temp row number + lv_flen TYPE i, " Length of reference formula + lv_tlen2 TYPE i, " Temp variable length + lv_substr1 TYPE string, " Substring variable + lv_abscol TYPE string, " Absolute column symbol + lv_absrow TYPE string, " Absolute row symbol + + lv_errormessage TYPE string. + + FIELD-SYMBOLS: <find_my_include> TYPE ANY. + +*--------------------------------------------------------------------* +* When copying a cell in EXCEL to another cell any inherent formulas +* 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 +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* No distance --> Reference = resulting cell/formula +*--------------------------------------------------------------------* + IF iv_shift_cols = 0 + AND iv_shift_rows = 0. + ev_resulting_formula = iv_reference_formula. + EXIT. " done + ENDIF. + + + lv_flen = STRLEN( iv_reference_formula ). + lv_numchars = 1. + +*--------------------------------------------------------------------* +* §1 Parse reference formula character by character +*--------------------------------------------------------------------* + DO lv_flen TIMES. + + CLEAR: lv_tchar, + lv_substr1, + lv_ref_cell_addr. + lv_cnt2 = lv_cnt + 1. + IF lv_cnt2 > lv_flen. + EXIT. " Done + ENDIF. + +*--------------------------------------------------------------------* +* Here we have the current character in the formula +*--------------------------------------------------------------------* + lv_tchar = iv_reference_formula+lv_cnt(1). + +*--------------------------------------------------------------------* +* Operators or opening parenthesis will separate possible cellreferences +*--------------------------------------------------------------------* + IF ( lv_tchar CA lcv_operators + OR lv_tchar CA '(' ) + AND lv_cnt2 = 1. + lv_substr1 = iv_reference_formula+lv_offset1(1). + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_numchars = 1. + CONTINUE. " --> next character in formula can be analyzed + ENDIF. + +*--------------------------------------------------------------------* +* Quoted literal text holds no cell reference --> advance to end of text +*--------------------------------------------------------------------* + IF lv_tchar EQ '"'. + lv_cnt = lv_cnt + 1. + lv_numchars = lv_numchars + 1. + lv_tchar = iv_reference_formula+lv_cnt(1). + WHILE lv_tchar NE '"'. + + lv_cnt = lv_cnt + 1. + lv_numchars = lv_numchars + 1. + lv_tchar = iv_reference_formula+lv_cnt(1). + + ENDWHILE. + lv_cnt2 = lv_cnt + 1. + lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars). + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + IF lv_cnt = lv_flen. + EXIT. + ENDIF. + lv_offset1 = lv_cnt. + lv_numchars = 1. + lv_tchar = iv_reference_formula+lv_cnt(1). + lv_cnt2 = lv_cnt + 1. + CONTINUE. " --> next character in formula can be analyzed + ENDIF. + + +*--------------------------------------------------------------------* +* Operators or parenthesis or last character in formula will separate possible cellreferences +*--------------------------------------------------------------------* + IF lv_tchar CA lcv_operators + OR lv_tchar CA '():' + OR lv_cnt2 = lv_flen. + IF lv_cnt > 0. + lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars). +*--------------------------------------------------------------------* +* Check for text concatenation and functions +*--------------------------------------------------------------------* + IF ( lv_tchar CA lcv_operators AND lv_tchar EQ lv_substr1 ) OR lv_tchar EQ '('. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. " --> next character in formula can be analyzed + ENDIF. + + lv_tlen = lv_cnt2 - lv_offset1. +*--------------------------------------------------------------------* +* Exclude mathematical operators and closing parentheses +*--------------------------------------------------------------------* + IF lv_tchar CA lcv_operators + OR lv_tchar CA ':)'. + IF lv_cnt2 = lv_flen + AND lv_numchars = 1. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. " --> next character in formula can be analyzed + ELSE. + lv_tlen = lv_tlen - 1. + ENDIF. + ENDIF. +*--------------------------------------------------------------------* +* Capture reference cell address +*--------------------------------------------------------------------* + TRY. + MOVE: iv_reference_formula+lv_offset1(lv_tlen) TO lv_ref_cell_addr. "Ref cell address + CATCH cx_root. + lv_errormessage = 'Internal error in Class ZCL_EXCEL_COMMON Method SHIFT_FORMULA Spot 1 '. " Change to messageclass if possible + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDTRY. + +*--------------------------------------------------------------------* +* Split cell address into characters and numbers +*--------------------------------------------------------------------* + CLEAR: lv_tlen, + lv_tcnt, + lv_tcol1, + lv_trow1. + lv_tlen = STRLEN( lv_ref_cell_addr ). + IF lv_tlen <> 0. + CLEAR: lv_tcnt. + DO lv_tlen TIMES. + CLEAR: lv_tchar2. + lv_tchar2 = lv_ref_cell_addr+lv_tcnt(1). + IF lv_tchar2 CA lcv_letters. + CONCATENATE lv_tcol1 lv_tchar2 INTO lv_tcol1. + ELSEIF lv_tchar2 CA lcv_digits. + CONCATENATE lv_trow1 lv_tchar2 INTO lv_trow1. + ENDIF. + lv_tcnt = lv_tcnt + 1. + ENDDO. + ENDIF. +*--------------------------------------------------------------------* +* Check for invalid cell address +*--------------------------------------------------------------------* + IF lv_tcol1 IS INITIAL OR lv_trow1 IS INITIAL. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDIF. +*--------------------------------------------------------------------* +* Check for range names +*--------------------------------------------------------------------* + CLEAR: lv_tlen. + lv_tlen = STRLEN( lv_tcol1 ). + IF lv_tlen GT 3. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDIF. +*--------------------------------------------------------------------* +* Check for valid row +*--------------------------------------------------------------------* + IF lv_trow1 GT 1048576. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDIF. +*--------------------------------------------------------------------* +* Check for absolute column or row reference +*--------------------------------------------------------------------* + CLEAR: lv_tcol2, + lv_trow2, + lv_abscol, + lv_absrow. + lv_tlen2 = STRLEN( lv_tcol1 ) - 1. + IF lv_tcol1 IS NOT INITIAL. + lv_abscol = lv_tcol1(1). + ENDIF. + IF lv_tlen2 GE 0. + lv_absrow = lv_tcol1+lv_tlen2(1). + ENDIF. + IF lv_abscol EQ '$' AND lv_absrow EQ '$'. + lv_tlen2 = lv_tlen2 - 1. + IF lv_tlen2 > 0. + lv_tcol1 = lv_tcol1+1(lv_tlen2). + ENDIF. + lv_tlen2 = lv_tlen2 + 1. + ELSEIF lv_abscol EQ '$'. + lv_tcol1 = lv_tcol1+1(lv_tlen2). + ELSEIF lv_absrow EQ '$'. + lv_tcol1 = lv_tcol1(lv_tlen2). + ENDIF. +*--------------------------------------------------------------------* +* Check for valid column +*--------------------------------------------------------------------* + TRY. + lv_tcoln = zcl_excel_common=>convert_column2int( lv_tcol1 ) + iv_shift_cols. + CATCH zcx_excel. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDTRY. +*--------------------------------------------------------------------* +* Check whether there is a referencing problem +*--------------------------------------------------------------------* + lv_trow2 = lv_trow1 + iv_shift_rows. + IF ( lv_tcoln < 1 AND lv_abscol <> '$' ) " Maybe we should add here max-column and max row-tests as well. + OR ( lv_trow2 < 1 AND lv_absrow <> '$' ). " Check how EXCEL behaves in this case +*--------------------------------------------------------------------* +* Referencing problem encountered --> set error +*--------------------------------------------------------------------* + CONCATENATE lv_cur_form lcv_cell_reference_error INTO lv_cur_form. + ELSE. +*--------------------------------------------------------------------* +* No referencing problems --> adjust row and column +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* Adjust column +*--------------------------------------------------------------------* + IF lv_abscol EQ '$'. + CONCATENATE lv_cur_form lv_abscol lv_tcol1 INTO lv_cur_form. + ELSEIF iv_shift_cols EQ 0. + CONCATENATE lv_cur_form lv_tcol1 INTO lv_cur_form. + ELSE. + TRY. + lv_tcol2 = zcl_excel_common=>convert_column2alpha( lv_tcoln ). + CONCATENATE lv_cur_form lv_tcol2 INTO lv_cur_form. + CATCH zcx_excel. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDTRY. + ENDIF. +*--------------------------------------------------------------------* +* Adjust row +*--------------------------------------------------------------------* + IF lv_absrow EQ '$'. + CONCATENATE lv_cur_form lv_absrow lv_trow1 INTO lv_cur_form. + ELSEIF iv_shift_rows = 0. + CONCATENATE lv_cur_form lv_trow1 INTO lv_cur_form. +* elseif lv_trow2 < 1. +* CONCATENATE lv_cur_form lc_cell_reference_error INTO lv_cur_form. + ELSE. + CONCATENATE lv_cur_form lv_trow2 INTO lv_cur_form. + ENDIF. + ENDIF. + + lv_numchars = 0. + IF lv_tchar CA lcv_operators + OR lv_tchar CA ':)'. + CONCATENATE lv_cur_form lv_tchar INTO lv_cur_form. + ENDIF. + lv_offset1 = lv_cnt2. + ENDIF. + ENDIF. + lv_numchars = lv_numchars + 1. + lv_cnt = lv_cnt + 1. + lv_cnt2 = lv_cnt + 1. + + ENDDO. + + + +*--------------------------------------------------------------------* +* Return resulting formula +*--------------------------------------------------------------------* + IF lv_cur_form IS NOT INITIAL. + MOVE lv_cur_form TO ev_resulting_formula. + ENDIF. + +ENDMETHOD. + + + + + method SHL01. + + DATA: + lv_bit TYPE i, + lv_curr_pos TYPE i VALUE 2, + lv_prev_pos TYPE i VALUE 1. + + DO 15 TIMES. + GET BIT lv_curr_pos OF i_pwd_hash INTO lv_bit. + SET BIT lv_prev_pos OF r_pwd_hash TO lv_bit. + ADD 1 TO lv_curr_pos. + ADD 1 TO lv_prev_pos. + ENDDO. + SET BIT 16 OF r_pwd_hash TO 0. + +endmethod. + + + + + method SHR14. + + DATA: + lv_bit TYPE i, + lv_curr_pos TYPE i, + lv_next_pos TYPE i. + + r_pwd_hash = i_pwd_hash. + + DO 14 TIMES. + lv_curr_pos = 15. + lv_next_pos = 16. + + DO 15 TIMES. + GET BIT lv_curr_pos OF r_pwd_hash INTO lv_bit. + SET BIT lv_next_pos OF r_pwd_hash TO lv_bit. + SUBTRACT 1 FROM lv_curr_pos. + SUBTRACT 1 FROM lv_next_pos. + ENDDO. + SET BIT 1 OF r_pwd_hash TO 0. + ENDDO. + +endmethod. + + + + + + + method SPLIT_FILE. + + DATA: lt_hlp TYPE TABLE OF text255, + ls_hlp TYPE text255. + + DATA: lf_ext(10) TYPE c, + lf_dot_ext(10) TYPE c. + DATA: lf_str TYPE text255, + lf_anz TYPE i, + lf_len TYPE i. +** --------------------------------------------------------------------- + + CLEAR: lt_hlp, + ep_file, + ep_extension, + ep_dotextension. + +** Split the whole file at '.' + SPLIT ip_file AT '.' INTO TABLE lt_hlp. + +** get the extenstion from the last line of table + DESCRIBE TABLE lt_hlp LINES lf_anz. + IF lf_anz <= 1. + ep_file = ip_file. + EXIT. + ENDIF. + + READ TABLE lt_hlp INTO ls_hlp INDEX lf_anz. + ep_extension = ls_hlp. + lf_ext = ls_hlp. + IF NOT lf_ext IS INITIAL. + CONCATENATE '.' lf_ext INTO lf_dot_ext. + ENDIF. + ep_dotextension = lf_dot_ext. + +** get only the filename + lf_len = strlen( ip_file ) - strlen( lf_dot_ext ). + IF lf_len > 0. + ep_file = ip_file(lf_len). + ENDIF. + +endmethod. + + + + + method STRUCTURE_CASE. + DATA: lt_comp_str TYPE abap_component_tab. + + CASE is_component-type->kind. + WHEN cl_abap_typedescr=>kind_elem. "E Elementary Type + INSERT is_component INTO TABLE xt_components. + WHEN cl_abap_typedescr=>kind_table. "T Table + INSERT is_component INTO TABLE xt_components. + WHEN cl_abap_typedescr=>kind_struct. "S Structure + lt_comp_str = structure_recursive( is_component = is_component ). + INSERT LINES OF lt_comp_str INTO TABLE xt_components. + 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. + + + + + method STRUCTURE_RECURSIVE. + DATA: lo_struct TYPE REF TO cl_abap_structdescr, + lt_components TYPE abap_component_tab, + ls_components TYPE abap_componentdescr. + + REFRESH rt_components. + + lo_struct ?= is_component-type. + lt_components = lo_struct->get_components( ). + + LOOP AT lt_components INTO ls_components. + structure_case( EXPORTING is_component = ls_components + CHANGING xt_components = rt_components ) . + ENDLOOP. + +endmethod. + + + + + method TIME_TO_EXCEL_STRING. + DATA: lv_seconds_in_day TYPE i, + lv_day_fraction TYPE f, + lc_time_baseline TYPE t VALUE '000000', + lc_seconds_in_day TYPE i VALUE 86400. + + 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. + + + + + + method UNESCAPE_STRING. + + CONSTANTS lcv_regex TYPE string VALUE `^'[^']` & `|` & " Beginning single ' OR + `[^']'$` & `|` & " Trailing single ' OR + `[^']'[^']`. " Single ' somewhere in between + + + DATA: lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + +*--------------------------------------------------------------------* +* This method is used to extract the "real" string from an escaped string. +* An escaped string can be identified by a beginning ' which must be +* accompanied by a trailing ' +* All '' in between beginning and trailing ' are treated as single ' +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* When allowing clike-input parameters we might encounter trailing +* "real" blanks . These are automatically eliminated when moving +* the input parameter to a string. +*--------------------------------------------------------------------* + ev_unescaped_string = iv_escaped. " Pass through if not escaped + + CHECK ev_unescaped_string IS NOT INITIAL. " Nothing to do if empty + CHECK ev_unescaped_string(1) = `'`. " Nothing to do if not escaped + +*--------------------------------------------------------------------* +* Remove leading and trailing ' +*--------------------------------------------------------------------* + REPLACE REGEX `^'(.*)'$` IN ev_unescaped_string WITH '$1'. + IF sy-subrc <> 0. + lv_errormessage = 'Input not properly escaped - &'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Any remaining single ' should not be here +*--------------------------------------------------------------------* + FIND REGEX lcv_regex IN ev_unescaped_string. + IF sy-subrc = 0. + lv_errormessage = 'Input not properly escaped - &'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Replace '' with ' +*--------------------------------------------------------------------* + REPLACE ALL OCCURRENCES OF `''` IN ev_unescaped_string WITH `'`. + + +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. + + MOVE 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 +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_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 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_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 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. + + 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. + + + + *"* 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. + + + + *"* 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 + + + *"* 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' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = me->guid. + me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call + + 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. + + DATA: lv_language TYPE sylangu. + DATA: lt_bin_mime TYPE sdokcntbins. + DATA: lt_mime TYPE tsfmime, + lv_filesize TYPE i, + lv_filesizec(10). + + CASE media_source. + WHEN c_media_source_xstring. + r_media = media. + WHEN c_media_source_www. + 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. + lv_language = sy-langu. + cl_wb_mime_repository=>load_mime( EXPORTING + io = me->io + IMPORTING + filesize = lv_filesize + bin_data = lt_bin_mime + CHANGING + language = lv_language ). + + 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. + + DATA: lv_language TYPE sylangu. + + io = ip_io. + media_source = c_media_source_mime. + size-width = ip_width. + size-height = ip_height. + + lv_language = sy-langu. + cl_wb_mime_repository=>load_mime( EXPORTING + io = ip_io + IMPORTING + filename = media_name + "mimetype = media_type + CHANGING + language = lv_language ). + + 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. + + + + + + + + *"* 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 CONSTRUCTOR. + "Load default values + me->pagemargins-b = '0.75'. + me->pagemargins-l = '0.7'. + me->pagemargins-r = '0.7'. + me->pagemargins-t = '0.75'. + me->pagemargins-header = '0.3'. + me->pagemargins-footer = '0.3'. + endmethod. + + + + + + + + + + + + + + + + + + + + method CREATE_SERIE. + DATA ls_serie TYPE s_series. + + DATA: lv_start_row_c TYPE char7, + lv_stop_row_c TYPE char7. + + + IF ip_lbl IS NOT SUPPLIED. + lv_stop_row_c = ip_lbl_to_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_lbl_from_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + ls_serie-lbl = ip_sheet. + ls_serie-lbl = zcl_excel_common=>escape_string( ip_value = ls_serie-lbl ). + CONCATENATE ls_serie-lbl '!$' ip_lbl_from_col '$' lv_start_row_c ':$' ip_lbl_to_col '$' lv_stop_row_c INTO ls_serie-lbl. + CLEAR: lv_start_row_c, lv_stop_row_c. + ELSE. + ls_serie-lbl = ip_lbl. + ENDIF. + IF ip_ref IS NOT SUPPLIED. + lv_stop_row_c = ip_ref_to_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_ref_from_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + ls_serie-ref = ip_sheet. + ls_serie-ref = zcl_excel_common=>escape_string( ip_value = ls_serie-ref ). + CONCATENATE ls_serie-ref '!$' ip_ref_from_col '$' lv_start_row_c ':$' ip_ref_to_col '$' lv_stop_row_c INTO ls_serie-ref. + CLEAR: lv_start_row_c, lv_stop_row_c. + ELSE. + ls_serie-ref = ip_ref. + ENDIF. + ls_serie-idx = ip_idx. + ls_serie-order = ip_order. + ls_serie-invertifnegative = ip_invertifnegative. + ls_serie-symbol = ip_symbol. + ls_serie-smooth = ip_smooth. + ls_serie-sername = ip_sername. + APPEND ls_serie TO me->series. + SORT me->series BY order ASCENDING. + endmethod. + + + + method SET_PRINT_LBL. + me->print_label = ip_value. + endmethod. + + + + 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. + + + + + + *"* 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + method SET_SHOW_CAT_NAME. + ns_showcatnameval = ip_value. + endmethod. + + + + method SET_SHOW_LEADER_LINES. + ns_showleaderlinesval = 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 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. + + + + *"* 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel3. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +DATA: ls_table_settings TYPE zexcel_s_table_settings. + + +DATA: lv_title TYPE zexcel_sheet_title, + lt_carr TYPE TABLE OF scarr, + row TYPE zexcel_cell_row VALUE 2, + lo_range TYPE REF TO zcl_excel_range. +DATA: lo_data_validation TYPE REF TO zcl_excel_data_validation. +FIELD-SYMBOLS: <carr> LIKE LINE OF lt_carr. + +CONSTANTS: c_airlines TYPE string VALUE 'Airlines'. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '03_iTab.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_empty TYPE flag. + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Internal table'). + + DATA lt_test TYPE TABLE OF sflight. + + IF p_empty <> abap_true. + SELECT * FROM sflight INTO TABLE lt_test. "#EC CI_NOWHERE + ENDIF. + + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ls_table_settings-show_row_stripes = abap_true. + ls_table_settings-nofilters = abap_true. + + lo_worksheet->bind_table( ip_table = lt_test + is_table_settings = ls_table_settings ). + + lo_worksheet->freeze_panes( ip_num_rows = 3 ). "freeze column headers when scrolling + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'E' ). "make date field a bit wider + column_dimension->set_width( ip_width = 11 ). + " Add another table for data validations + lo_worksheet = lo_excel->add_new_worksheet( ). + lv_title = 'Data Validation'. + lo_worksheet->set_title( lv_title ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = c_airlines ). + SELECT * FROM scarr INTO TABLE lt_carr. "#EC CI_NOWHERE + LOOP AT lt_carr ASSIGNING <carr>. + lo_worksheet->set_cell( ip_row = row ip_column = 'A' ip_value = <carr>-carrid ). + row = row + 1. + ENDLOOP. + row = row - 1. + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_airlines. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'A' + ip_start_row = 2 + ip_stop_column = 'A' + ip_stop_row = row ). + " Set Data Validation + lo_excel->set_active_sheet_index( 1 ). + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_airlines. + lo_data_validation->cell_row = 4. + lo_data_validation->cell_column = 'C'. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel30. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + +DATA: lv_value TYPE string, + lv_count TYPE i VALUE 10, + lv_packed TYPE p LENGTH 16 DECIMALS 1 VALUE '1234567890.5'. + +CONSTANTS: lc_typekind_string TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_string, + lc_typekind_packed TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_packed, + lc_typekind_num TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_num, + lc_typekind_date TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_date, + lc_typekind_s_ls TYPE string VALUE 's_leading_blanks'. + +CONSTANTS: gc_save_file_name TYPE string VALUE '30_CellDataTypes.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Cell data types' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Number as String' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 2 ip_value = '11' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 1 ip_value = 'String' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = ' String with leading spaces' + ip_data_type = lc_typekind_s_ls ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = ' Negative Value' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 1 ip_value = 'Packed' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 2 ip_value = '50000.01-' + ip_abap_type = lc_typekind_packed ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 1 ip_value = 'Number with Percentage' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 2 ip_value = '0 %' + ip_abap_type = lc_typekind_num ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = 1 ip_value = 'Date' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = 2 ip_value = '20110831' + ip_abap_type = lc_typekind_date ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'Positive Value' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = '5000.02' + ip_abap_type = lc_typekind_packed ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 3 ip_value = '50 %' + ip_abap_type = lc_typekind_num ). + + WHILE lv_count <= 15. + lv_value = lv_count. + CONCATENATE 'Positive Value with' lv_value 'Digits' INTO lv_value SEPARATED BY space. + lo_worksheet->set_cell( ip_column = 'B' ip_row = lv_count ip_value = lv_value + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = lv_count ip_value = lv_packed + ip_abap_type = lc_typekind_packed ). + CONCATENATE 'Positive Value with' lv_value 'Digits formated as string' INTO lv_value SEPARATED BY space. + lo_worksheet->set_cell( ip_column = 'D' ip_row = lv_count ip_value = lv_value + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = lv_count ip_value = lv_packed + ip_abap_type = lc_typekind_string ). + lv_packed = lv_packed * 10. + lv_count = lv_count + 1. + ENDWHILE. + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'D' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'E' ). + column_dimension->set_auto_size( abap_true ). + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel31. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + +DATA: fieldval TYPE text80, + row TYPE i, + style_column_a TYPE REF TO zcl_excel_style, + style_column_a_guid TYPE zexcel_cell_style, + style_column_b TYPE REF TO zcl_excel_style, + style_column_b_guid TYPE zexcel_cell_style, + style_column_c TYPE REF TO zcl_excel_style, + style_column_c_guid TYPE zexcel_cell_style, + style_font TYPE REF TO zcl_excel_style_font. + +CONSTANTS: gc_save_file_name TYPE string VALUE '31_AutosizeWithDifferentFontSizes.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + " Use active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Regular Font' ). + + style_column_a = lo_excel->add_new_style( ). + style_column_a->font->size = 32. " quite large + style_column_a_guid = style_column_a->get_guid( ). + + style_column_c = lo_excel->add_new_style( ). + style_column_c->font->size = 16. " not so large + style_column_c_guid = style_column_c->get_guid( ). + + + DO 20 TIMES. + row = sy-index. + CLEAR fieldval. + DO sy-index TIMES. + CONCATENATE fieldval 'X' INTO fieldval. + ENDDO. + lo_worksheet->set_cell( ip_column = 'A' ip_row = row ip_value = fieldval ip_style = style_column_a_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = row ip_value = fieldval ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = row ip_value = fieldval ip_style = style_column_c_guid ). + ENDDO. + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Add sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Bold Font' ). + + style_column_a = lo_excel->add_new_style( ). + style_column_a->font->size = 32. " quite large + style_column_a->font->bold = abap_true. + style_column_a_guid = style_column_a->get_guid( ). + + style_column_b = lo_excel->add_new_style( ). + style_column_b->font->bold = abap_true. + style_column_b_guid = style_column_b->get_guid( ). + + style_column_c = lo_excel->add_new_style( ). + style_column_c->font->size = 16. " not so large + style_column_c->font->bold = abap_true. + style_column_c_guid = style_column_c->get_guid( ). + + DO 20 TIMES. + row = sy-index. + CLEAR fieldval. + DO sy-index TIMES. + CONCATENATE fieldval 'X' INTO fieldval. + ENDDO. + lo_worksheet->set_cell( ip_column = 'A' ip_row = row ip_value = fieldval ip_style = style_column_a_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = row ip_value = fieldval ip_style = style_column_b_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = row ip_value = fieldval ip_style = style_column_c_guid ). + ENDDO. + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Add sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Italic Font' ). + + style_column_a = lo_excel->add_new_style( ). + style_column_a->font->size = 32. " quite large + style_column_a->font->italic = abap_true. + style_column_a_guid = style_column_a->get_guid( ). + + style_column_b = lo_excel->add_new_style( ). + style_column_b->font->italic = abap_true. + style_column_b_guid = style_column_b->get_guid( ). + + style_column_c = lo_excel->add_new_style( ). + style_column_c->font->size = 16. " not so large + style_column_c->font->italic = abap_true. + style_column_c_guid = style_column_c->get_guid( ). + + DO 20 TIMES. + row = sy-index. + CLEAR fieldval. + DO sy-index TIMES. + CONCATENATE fieldval 'X' INTO fieldval. + ENDDO. + lo_worksheet->set_cell( ip_column = 'A' ip_row = row ip_value = fieldval ip_style = style_column_a_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = row ip_value = fieldval ip_style = style_column_b_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = row ip_value = fieldval ip_style = style_column_c_guid ). + ENDDO. + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Add sheet for merged cells + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Merged cells' ). + + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'This is a very long header text' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 2 ip_value = 'Some data' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Some more data' ). + + lo_worksheet->set_merge( + EXPORTING + ip_column_start = 'A' + ip_column_end = 'C' + ip_row = 1 ). + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + lo_excel->set_active_sheet_index( i_active_worksheet = 1 ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *--------------------------------------------------------------------* +* REPORT ZDEMO_EXCEL32 +* Demo for export options from ALV GRID: +* export data from ALV (CL_GUI_ALV_GRID) object or cl_salv_table object +* to Excel. +*--------------------------------------------------------------------* +REPORT zdemo_excel32. + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events DEFINITION. + PUBLIC SECTION. + METHODS: + on_user_command FOR EVENT added_function OF cl_salv_events + IMPORTING e_salv_function. +ENDCLASS. "lcl_handle_events DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events IMPLEMENTATION. + METHOD on_user_command. + PERFORM user_command." using e_salv_function text-i08. + ENDMETHOD. "on_user_command +ENDCLASS. "lcl_handle_events IMPLEMENTATION + +*--------------------------------------------------------------------* +* DATA DECLARATION +*--------------------------------------------------------------------* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_salv TYPE REF TO cl_salv_table, + gr_events TYPE REF TO lcl_handle_events, + lr_events TYPE REF TO cl_salv_events_table, + gt_sbook TYPE TABLE OF sbook. + +DATA: l_path TYPE string, " local dir + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: + lv_default_file_name TYPE string VALUE '32_Export_ALV.xlsx', + lv_default_file_name2 TYPE string VALUE '32_Export_Convert.xlsx'. +*--------------------------------------------------------------------* +*START-OF-SELECTION +*--------------------------------------------------------------------* + +START-OF-SELECTION. + +* get data +* ------------------------------------------ + + SELECT * + INTO TABLE gt_sbook[] + FROM sbook "#EC CI_NOWHERE + UP TO 100 ROWS. + +* Display ALV +* ------------------------------------------ + + TRY. + cl_salv_table=>factory( + EXPORTING + list_display = abap_false + IMPORTING + r_salv_table = lo_salv + CHANGING + t_table = gt_sbook[] ). + CATCH cx_salv_msg . + ENDTRY. + + TRY. + lo_salv->set_screen_status( + EXPORTING + report = sy-repid + pfstatus = 'ALV_STATUS' + set_functions = lo_salv->c_functions_all ). + CATCH cx_salv_msg . + ENDTRY. + + lr_events = lo_salv->get_event( ). + CREATE OBJECT gr_events. + SET HANDLER gr_events->on_user_command FOR lr_events. + + lo_salv->display( ). + + +*&---------------------------------------------------------------------* +*& Form USER_COMMAND +*&---------------------------------------------------------------------* +* ALV user command +*--------------------------------------------------------------------* +FORM user_command . + +* get save file path + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = l_path ). + cl_gui_cfw=>flush( ). + cl_gui_frontend_services=>directory_browse( + EXPORTING initial_folder = l_path + CHANGING selected_folder = l_path ). + + IF l_path IS INITIAL. + cl_gui_frontend_services=>get_sapgui_workdir( + CHANGING sapworkdir = lv_workdir ). + l_path = lv_workdir. + ENDIF. + + cl_gui_frontend_services=>get_file_separator( + CHANGING file_separator = lv_file_separator ). + + + +* export file to save file path + CASE sy-ucomm. + WHEN 'EXCELBIND'. + CONCATENATE l_path lv_file_separator lv_default_file_name + INTO l_path. + PERFORM export_to_excel_bind. + + WHEN 'EXCELCONV'. + + CONCATENATE l_path lv_file_separator lv_default_file_name2 + INTO l_path. + PERFORM export_to_excel_conv. + + ENDCASE. +ENDFORM. " USER_COMMAND +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL_CONV +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +FORM export_to_excel_conv. + DATA: lo_converter TYPE REF TO zcl_excel_converter. + + CREATE OBJECT lo_converter. +*TRY. + lo_converter->convert( + EXPORTING + io_alv = lo_salv + it_table = gt_sbook + i_row_int = 2 + i_column_int = 2 +* i_table = +* i_style_table = +* io_worksheet = +* CHANGING +* co_excel = + ). +* CATCH zcx_excel . +*ENDTRY. + lo_converter->write_file( i_path = l_path ). + +ENDFORM. "EXPORT_TO_EXCEL_CONV + +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL_BIND +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +FORM export_to_excel_bind. +* create zcl_excel_worksheet object + CREATE OBJECT lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + +* write to excel using method Bin_object +*try. + lo_worksheet->bind_alv( + io_alv = lo_salv + it_table = gt_sbook + i_top = 2 + i_left = 1 + ). +* catch zcx_excel . +*endtry. + + + PERFORM write_file. + +ENDFORM. "EXPORT_TO_EXCEL_BIND +*&---------------------------------------------------------------------* +*& Form WRITE_FILE +*&---------------------------------------------------------------------* +* text +*----------------------------------------------------------------------* +* --> p1 text +* <-- p2 text +*----------------------------------------------------------------------* +FORM write_file . + DATA: lt_file TYPE solix_tab, + l_bytecount TYPE i, + l_file TYPE xstring. + + DATA: lo_excel_writer TYPE REF TO zif_excel_writer. + + DATA: ls_seoclass TYPE seoclass. + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + l_file = lo_excel_writer->write_file( lo_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 = l_file + RECEIVING + et_solix = lt_file. + + l_bytecount = XSTRLEN( l_file ). + ELSE. + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = l_file + IMPORTING + output_length = l_bytecount + TABLES + binary_tab = lt_file. + ENDIF. + + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = l_bytecount + filename = l_path + filetype = 'BIN' + CHANGING data_tab = lt_file ). + +ENDFORM. " WRITE_FILE + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel33. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_converter TYPE REF TO zcl_excel_converter, + lo_autofilter TYPE REF TO zcl_excel_autofilter. + +DATA lt_test TYPE TABLE OF t005t. + +DATA: l_cell_value TYPE zexcel_cell_value, + ls_area TYPE zexcel_s_autofilter_area. + +CONSTANTS: c_airlines TYPE string VALUE 'Airlines'. + +CONSTANTS: gc_save_file_name TYPE string VALUE '33_autofilter.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Internal table'). + + SELECT * UP TO 2 ROWS FROM t005t INTO TABLE lt_test. "#EC CI_NOWHERE + + CREATE OBJECT lo_converter. + + lo_converter->convert( EXPORTING + it_table = lt_test + i_row_int = 1 + i_column_int = 1 + io_worksheet = lo_worksheet + CHANGING + co_excel = lo_excel ) . + + lo_autofilter = lo_excel->add_new_autofilter( io_sheet = lo_worksheet ) . + + ls_area-row_start = 1. + ls_area-col_start = 1. + ls_area-row_end = lo_worksheet->get_highest_row( ). + ls_area-col_end = lo_worksheet->get_highest_column( ). + + lo_autofilter->set_filter_area( is_area = ls_area ). + + lo_worksheet->get_cell( EXPORTING + ip_column = 'C' + ip_row = 2 + IMPORTING + ep_value = l_cell_value ). + lo_autofilter->set_value( i_column = 3 + i_value = l_cell_value ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL2 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel34. + +CONSTANTS: width TYPE f VALUE '10.14'. +CONSTANTS: height TYPE f VALUE '57.75'. + +DATA: current_row TYPE i, + col TYPE i, + col_alpha TYPE zexcel_cell_column_alpha, + row TYPE i, + row_board TYPE i, + colorflag TYPE i, + color TYPE zexcel_style_color_argb, + + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + + writing1 TYPE string, + writing2 TYPE string. + + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +CONSTANTS: gc_save_file_name TYPE string VALUE '34_Static Styles_Chess.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Spassky_vs_Bronstein' ). + +* Header + current_row = 1. + + ADD 1 TO current_row. + lo_worksheet->set_cell( ip_row = current_row ip_column = 'B' ip_value = 'White' ). + lo_worksheet->set_cell( ip_row = current_row ip_column = 'C' ip_value = 'Spassky, Boris V -- wins in turn 23' ). + + ADD 1 TO current_row. + lo_worksheet->set_cell( ip_row = current_row ip_column = 'B' ip_value = 'Black' ). + lo_worksheet->set_cell( ip_row = current_row ip_column = 'C' ip_value = 'Bronstein, David I' ). + + ADD 1 TO current_row. +* Set size of column + Writing above chessboard + DO 8 TIMES. + + writing1 = zcl_excel_common=>convert_column2alpha( sy-index ). + writing2 = sy-index . + row = current_row + sy-index. + + col = sy-index + 1. + col_alpha = zcl_excel_common=>convert_column2alpha( col ). + +* Set size of column + column_dimension = lo_worksheet->get_column_dimension( col_alpha ). + column_dimension->set_width( width ). + +* Set size of row + row_dimension = lo_worksheet->get_row_dimension( row ). + row_dimension->set_row_height( height ). + +* Set writing on chessboard + lo_worksheet->set_cell( ip_row = row + ip_column = 'A' + ip_value = writing2 ). + lo_worksheet->change_cell_style( ip_column = 'A' + ip_row = row + ip_alignment_vertical = zcl_excel_style_alignment=>c_vertical_center ). + lo_worksheet->set_cell( ip_row = row + ip_column = 'J' + ip_value = writing2 ). + lo_worksheet->change_cell_style( ip_column = 'J' + ip_row = row + ip_alignment_vertical = zcl_excel_style_alignment=>c_vertical_center ). + + row = current_row + 9. + lo_worksheet->set_cell( ip_row = current_row + ip_column = col_alpha + ip_value = writing1 ). + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = current_row + ip_alignment_horizontal = zcl_excel_style_alignment=>c_horizontal_center ). + lo_worksheet->set_cell( ip_row = row + ip_column = col_alpha + ip_value = writing1 ). + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_alignment_horizontal = zcl_excel_style_alignment=>c_horizontal_center ). + ENDDO. + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'J' ). + column_dimension->set_auto_size( abap_true ). + +* Set win-position + CONSTANTS: c_pawn TYPE string VALUE 'Pawn'. + CONSTANTS: c_rook TYPE string VALUE 'Rook'. + CONSTANTS: c_knight TYPE string VALUE 'Knight'. + CONSTANTS: c_bishop TYPE string VALUE 'Bishop'. + CONSTANTS: c_queen TYPE string VALUE 'Queen'. + CONSTANTS: c_king TYPE string VALUE 'King'. + + row = current_row + 1. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = c_rook ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_rook ). + lo_worksheet->set_cell( ip_row = row ip_column = 'G' ip_value = c_knight ). + row = current_row + 2. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'D' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_queen ). + lo_worksheet->set_cell( ip_row = row ip_column = 'H' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'I' ip_value = c_king ). + row = current_row + 3. + lo_worksheet->set_cell( ip_row = row ip_column = 'I' ip_value = c_pawn ). + row = current_row + 4. + lo_worksheet->set_cell( ip_row = row ip_column = 'D' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_knight ). + row = current_row + 5. + lo_worksheet->set_cell( ip_row = row ip_column = 'E' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_queen ). + row = current_row + 6. + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = c_bishop ). + row = current_row + 7. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'H' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'I' ip_value = c_pawn ). + row = current_row + 8. + lo_worksheet->set_cell( ip_row = row ip_column = 'G' ip_value = c_rook ). + lo_worksheet->set_cell( ip_row = row ip_column = 'H' ip_value = c_king ). + +* Set Chessboard + DO 8 TIMES. + IF sy-index <= 3. " Black + color = zcl_excel_style_color=>c_black. + ELSE. + color = zcl_excel_style_color=>c_white. + ENDIF. + row_board = sy-index. + row = current_row + sy-index. + DO 8 TIMES. + col = sy-index + 1. + col_alpha = zcl_excel_common=>convert_column2alpha( col ). + TRY. +* Borders around outer limits + IF row_board = 1. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_top_style = zcl_excel_style_border=>c_border_thick + ip_borders_top_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. + IF row_board = 8. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_down_style = zcl_excel_style_border=>c_border_thick + ip_borders_down_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. + IF col = 2. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_left_style = zcl_excel_style_border=>c_border_thick + ip_borders_left_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. + IF col = 9. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_right_style = zcl_excel_style_border=>c_border_thick + ip_borders_right_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. +* Style for writing + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_font_color_rgb = color + ip_font_bold = 'X' + ip_font_size = 16 + ip_alignment_horizontal = zcl_excel_style_alignment=>c_horizontal_center + ip_alignment_vertical = zcl_excel_style_alignment=>c_vertical_center + ip_fill_filltype = zcl_excel_style_fill=>c_fill_solid ). +* Color of field + colorflag = ( row + col ) MOD 2. + IF colorflag = 0. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_fill_fgcolor_rgb = 'FFB5866A' + ip_fill_filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal135 ). + ELSE. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_fill_fgcolor_rgb = 'FFF5DEBF' + ip_fill_filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal45 ). + ENDIF. + + + + CATCH zcx_excel . + ENDTRY. + + ENDDO. + ENDDO. + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL2 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel35. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_bold TYPE REF TO zcl_excel_style, + lo_style_underline TYPE REF TO zcl_excel_style, + lo_style_filled TYPE REF TO zcl_excel_style, + lo_style_border TYPE REF TO zcl_excel_style, + lo_style_button TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + lo_border_light TYPE REF TO zcl_excel_style_border. + +DATA: lv_style_bold_guid TYPE zexcel_cell_style, + lv_style_underline_guid TYPE zexcel_cell_style, + lv_style_filled_guid TYPE zexcel_cell_style, + lv_style_filled_green_guid TYPE zexcel_cell_style, + lv_style_border_guid TYPE zexcel_cell_style, + lv_style_button_guid TYPE zexcel_cell_style, + lv_style_filled_turquoise_guid TYPE zexcel_cell_style. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE '35_Static_Styles.xlsx'. + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>GET_DESKTOP_DIRECTORY( CHANGING DESKTOP_DIRECTORY = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + + sy-title = 'ZDEMO_EXCEL2;Issue 139: Change cellstyle retroactivly'. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + CREATE OBJECT lo_border_light. + lo_border_light->border_color-rgb = zcl_excel_style_color=>c_gray. + lo_border_light->border_style = zcl_excel_style_border=>c_border_thin. + " Create a bold / italic style + lo_style_bold = lo_excel->add_new_style( ). + lo_style_bold->font->bold = abap_true. + lo_style_bold->font->italic = abap_true. + lo_style_bold->font->name = zcl_excel_style_font=>c_name_arial. + lo_style_bold->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_bold->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_bold_guid = lo_style_bold->get_guid( ). + " Create an underline double style + lo_style_underline = lo_excel->add_new_style( ). + lo_style_underline->font->underline = abap_true. + lo_style_underline->font->underline_mode = zcl_excel_style_font=>c_underline_double. + lo_style_underline->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_underline->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_underline->font->family = zcl_excel_style_font=>c_family_roman. + lv_style_underline_guid = lo_style_underline->get_guid( ). + " Create filled style yellow + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-theme = zcl_excel_style_color=>c_theme_accent6. + lv_style_filled_guid = lo_style_filled->get_guid( ). + " Create border with button effects + lo_style_button = lo_excel->add_new_style( ). + lo_style_button->borders->right = lo_border_dark. + lo_style_button->borders->down = lo_border_dark. + lo_style_button->borders->left = lo_border_light. + lo_style_button->borders->top = lo_border_light. + lv_style_button_guid = lo_style_button->get_guid( ). + "Create style with border + lo_style_border = lo_excel->add_new_style( ). + lo_style_border->borders->allborders = lo_border_dark. + lo_style_border->borders->diagonal = lo_border_dark. + lo_style_border->borders->diagonal_mode = zcl_excel_style_borders=>c_diagonal_both. + lv_style_border_guid = lo_style_border->get_guid( ). + " Create filled style green + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_green. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_filled_green_guid = lo_style_filled->get_guid( ). + + " Create filled style turquoise using legacy excel ver <= 2003 palette. (https://code.sdn.sap.com/spaces/abap2xlsx/tickets/92) + lo_style_filled = lo_excel->add_new_style( ). + lo_excel->legacy_palette->set_color( "replace built-in color from palette with out custom RGB turquoise + ip_index = 16 + ip_color = '0040E0D0' ). + + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-indexed = 16. + lv_style_filled_turquoise_guid = lo_style_filled->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Styles' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Bold text' ip_style = lv_style_bold_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 4 ip_value = 'Underlined text' ip_style = lv_style_underline_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 6 ip_value = 'Borders' ip_style = lv_style_border_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 7 ip_value = 'I''m not a button :)' ip_style = lv_style_button_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 9 ip_value = 'Modified color for Excel 2003' ip_style = lv_style_filled_turquoise_guid ). + " Fill the cell and apply one style + lo_worksheet->set_cell( ip_column = 'B' ip_row = 6 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + " Change the style + lo_worksheet->set_cell_style( ip_column = 'B' ip_row = 6 ip_style = lv_style_filled_green_guid ). + " Add Style to an empty cell to test Fix for Issue + "#44 Exception ZCX_EXCEL thrown when style is set for an empty cell + " https://code.sdn.sap.com/spaces/abap2xlsx/tickets/44-exception-zcx_excel-thrown-when-style-is-set-for-an-empty-cell + lo_worksheet->set_cell_style( ip_column = 'E' ip_row = 6 ip_style = lv_style_filled_green_guid ). + + +* Demonstrate how to retroactivly change the cellstyle +*Filled text and underlinded text + lo_worksheet->change_cell_style( ip_column = 'B' + ip_row = 5 + ip_font_bold = abap_true + ip_font_italic = abap_true ). + + lo_worksheet->change_cell_style( ip_column = 'D' + ip_row = 4 + ip_font_bold = abap_true + ip_font_italic = abap_true ). + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL36 +REPORT zdemo_excel36. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + col TYPE i. + +DATA: lo_style_arial20 TYPE REF TO zcl_excel_style, + lo_style_times11 TYPE REF TO zcl_excel_style, + lo_style_cambria8red TYPE REF TO zcl_excel_style. + +DATA: lv_style_arial20_guid TYPE zexcel_cell_style, + lv_style_times11_guid TYPE zexcel_cell_style, + lv_style_cambria8red_guid TYPE zexcel_cell_style. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '36_DefaultStyles.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create a bold / italic style + lo_style_arial20 = lo_excel->add_new_style( ). + lo_style_arial20->font->name = zcl_excel_style_font=>c_name_arial. + lo_style_arial20->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_arial20->font->size = 20. + lv_style_arial20_guid = lo_style_arial20->get_guid( ). + + lo_style_times11 = lo_excel->add_new_style( ). + lo_style_times11->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_times11->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_times11->font->size = 11. + lv_style_times11_guid = lo_style_times11->get_guid( ). + + lo_style_cambria8red = lo_excel->add_new_style( ). + lo_style_cambria8red->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_cambria8red->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_cambria8red->font->size = 8. + lo_style_cambria8red->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_cambria8red_guid = lo_style_cambria8red->get_guid( ). + + lo_excel->set_default_style( lv_style_arial20_guid ). " Default for all new worksheets + +* 1st sheet - do not change anything --> defaultstyle from lo_excel should apply + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Style for complete document' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 4 ip_value = 'All cells in this sheet are set to font Arial, fontsize 20' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 5 ip_value = 'because no separate style was passed for this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 6 ip_value = 'but a default style was set for the complete instance of zcl_excel' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 1 ip_value = space ). " Missing feature "set active cell - use this to simulate that + + +* 2nd sheet - defaultstyle for this sheet set explicitly ( set to Times New Roman 11 ) + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Style for this sheet' ). + lo_worksheet->zif_excel_sheet_properties~set_style( lv_style_times11_guid ). + + lo_worksheet->set_cell( ip_column = 2 ip_row = 4 ip_value = 'All cells in this sheet are set to font Times New Roman, fontsize 11' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 5 ip_value = 'because this style was passed for this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 6 ip_value = 'thus the default style from zcl_excel does not apply to this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 1 ip_value = space ). " Missing feature "set active cell - use this to simulate that + + +* 3rd sheet - defaultstyle for columns ( set to Times New Roman 11 ) + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Style for 3 columns' ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_column_style_by_guid( ip_style_guid = lv_style_times11_guid ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_column_style_by_guid( ip_style_guid = lv_style_times11_guid ). + column_dimension = lo_worksheet->get_column_dimension( 'F' ). + column_dimension->set_column_style_by_guid( ip_style_guid = lv_style_times11_guid ). + + lo_worksheet->set_cell( ip_column = 2 ip_row = 4 ip_value = 'The columns B,C and F are set to Times New Roman' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 10 ip_value = 'All other cells in this sheet are set to font Arial, fontsize 20' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 11 ip_value = 'because no separate style was passed for this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 12 ip_value = 'but a default style was set for the complete instance of zcl_excel' ). + + lo_worksheet->set_cell( ip_column = 8 ip_row = 1 ip_value = 'Of course' ip_style = lv_style_cambria8red_guid ). + lo_worksheet->set_cell( ip_column = 8 ip_row = 2 ip_value = 'setting a specific style to a cell' ip_style = lv_style_cambria8red_guid ). + lo_worksheet->set_cell( ip_column = 8 ip_row = 3 ip_value = 'takes precedence over all defaults' ip_style = lv_style_cambria8red_guid ). + lo_worksheet->set_cell( ip_column = 8 ip_row = 4 ip_value = 'Here: Cambria 8 in red' ip_style = lv_style_cambria8red_guid ). + + +* Set entry into each of the first 10 columns + DO 20 TIMES. + col = sy-index. + CASE col. + WHEN 2 " B + OR 3 " C + OR 6." F + lo_worksheet->set_cell( ip_column = col ip_row = 6 ip_value = 'Times 11' ). + WHEN OTHERS. + lo_worksheet->set_cell( ip_column = col ip_row = 6 ip_value = 'Arial 20' ). + ENDCASE. + ENDDO. + + lo_worksheet->set_cell( ip_column = 2 ip_row = 1 ip_value = space ). " Missing feature "set active cell - use this to simulate that + + + + lo_excel->set_active_sheet_index( 1 ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + REPORT zdemo_excel37. + +TYPE-POOLS: vrm. + +DATA: excel TYPE REF TO zcl_excel, + reader TYPE REF TO zif_excel_reader, + go_error TYPE REF TO cx_root, + gv_memid_gr8 TYPE text255, + gv_message TYPE string, + lv_extension TYPE string, + gv_error_program_name TYPE syrepid, + gv_error_include_name TYPE syrepid, + gv_error_line TYPE i. + +DATA: gc_save_file_name TYPE string VALUE '37- Read template and output.&'. + +SELECTION-SCREEN BEGIN OF BLOCK blx WITH FRAME. +PARAMETERS: p_upfile TYPE string LOWER CASE MEMORY ID gr8. +SELECTION-SCREEN END OF BLOCK blx. + +INCLUDE zdemo_excel_outputopt_incl. + +SELECTION-SCREEN BEGIN OF BLOCK cls WITH FRAME TITLE text-cls. +PARAMETERS: lb_read TYPE seoclsname AS LISTBOX VISIBLE LENGTH 40 LOWER CASE OBLIGATORY DEFAULT 'Autodetect'(001). +PARAMETERS: lb_write TYPE seoclsname AS LISTBOX VISIBLE LENGTH 40 LOWER CASE OBLIGATORY DEFAULT 'Autodetect'(001). +SELECTION-SCREEN END OF BLOCK cls. + +SELECTION-SCREEN BEGIN OF BLOCK bl_err WITH FRAME TITLE text-err. +PARAMETERS: cb_errl AS CHECKBOX DEFAULT 'X'. +SELECTION-SCREEN BEGIN OF LINE. +PARAMETERS: cb_dump AS CHECKBOX DEFAULT space. +SELECTION-SCREEN COMMENT (60) cmt_dump FOR FIELD cb_dump. +SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN END OF BLOCK bl_err. + +INITIALIZATION. + PERFORM setup_listboxes. + cmt_dump = text-dum. + GET PARAMETER ID 'GR8' FIELD gv_memid_gr8. + p_upfile = gv_memid_gr8. + + IF p_upfile IS INITIAL. + p_upfile = 'c:\temp\whatever.xlsx'. + ENDIF. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_upfile. + PERFORM f4_p_upfile CHANGING p_upfile. + + +START-OF-SELECTION. + IF cb_dump IS INITIAL. + TRY. + PERFORM read_template. + PERFORM write_template. +*** Create output + CATCH cx_root INTO go_error. + MESSAGE 'Error reading excelfile' TYPE 'I'. + gv_message = go_error->get_text( ). + IF cb_errl = ' '. + IF gv_message IS NOT INITIAL. + MESSAGE gv_message TYPE 'I'. + ENDIF. + ELSE. + go_error->get_source_position( IMPORTING program_name = gv_error_program_name + include_name = gv_error_include_name + source_line = gv_error_line ). + WRITE:/ 'Errormessage:' ,gv_message. + WRITE:/ 'Errorposition:', + AT /10 'Program:' ,gv_error_program_name, + AT /10 'include_name:' ,gv_error_include_name, + AT /10 'source_line:' ,gv_error_line. + ENDIF. + ENDTRY. + ELSE. " This will dump if an error occurs. In some cases the information given in cx_root is not helpful - this will show exactly where the problem is + PERFORM read_template. + PERFORM write_template. + ENDIF. + + + +*&---------------------------------------------------------------------* +*& Form F4_P_UPFILE +*&---------------------------------------------------------------------* +FORM f4_p_upfile CHANGING p_upfile TYPE string. + + DATA: lv_repid TYPE syrepid, + lt_fields TYPE dynpread_tabtype, + ls_field LIKE LINE OF lt_fields, + lt_files TYPE filetable, + lv_file_filter TYPE string. + + lv_repid = sy-repid. + + CALL FUNCTION 'DYNP_VALUES_READ' + EXPORTING + dyname = lv_repid + dynumb = '1000' + request = 'A' + TABLES + dynpfields = lt_fields + EXCEPTIONS + invalid_abapworkarea = 01 + invalid_dynprofield = 02 + invalid_dynproname = 03 + invalid_dynpronummer = 04 + invalid_request = 05 + no_fielddescription = 06 + undefind_error = 07. + READ TABLE lt_fields INTO ls_field WITH KEY fieldname = 'P_UPFILE'. + p_upfile = ls_field-fieldvalue. + + lv_file_filter = 'Excel Files (*.XLSX;*.XLSM)|*.XLSX;*.XLSM'. + cl_gui_frontend_services=>file_open_dialog( EXPORTING + default_filename = p_upfile + file_filter = lv_file_filter + CHANGING + file_table = lt_files + rc = sy-tabix + EXCEPTIONS + OTHERS = 1 ). + READ TABLE lt_files INDEX 1 INTO p_upfile. + +ENDFORM. " F4_P_UPFILE + + +*&---------------------------------------------------------------------* +*& Form SETUP_LISTBOXES +*&---------------------------------------------------------------------* +FORM setup_listboxes . + + DATA: lv_id TYPE vrm_id, + lt_values TYPE vrm_values, + lt_implementing_classes TYPE seo_relkeys. + + FIELD-SYMBOLS: <ls_implementing_class> LIKE LINE OF lt_implementing_classes, + <ls_value> LIKE LINE OF lt_values. + +*--------------------------------------------------------------------* +* Possible READER-Classes +*--------------------------------------------------------------------* + lv_id = 'LB_READ'. + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = 'Autodetect'(001). + <ls_value>-text = 'Autodetect'(001). + + + PERFORM get_implementing_classds USING 'ZIF_EXCEL_READER' + CHANGING lt_implementing_classes. + CLEAR lt_values. + LOOP AT lt_implementing_classes ASSIGNING <ls_implementing_class>. + + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = <ls_implementing_class>-clsname. + <ls_value>-text = <ls_implementing_class>-clsname. + + ENDLOOP. + + CALL FUNCTION 'VRM_SET_VALUES' + EXPORTING + id = lv_id + values = lt_values + EXCEPTIONS + id_illegal_name = 1 + OTHERS = 2. + +*--------------------------------------------------------------------* +* Possible WRITER-Classes +*--------------------------------------------------------------------* + lv_id = 'LB_WRITE'. + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = 'Autodetect'(001). + <ls_value>-text = 'Autodetect'(001). + + + PERFORM get_implementing_classds USING 'ZIF_EXCEL_WRITER' + CHANGING lt_implementing_classes. + CLEAR lt_values. + LOOP AT lt_implementing_classes ASSIGNING <ls_implementing_class>. + + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = <ls_implementing_class>-clsname. + <ls_value>-text = <ls_implementing_class>-clsname. + + ENDLOOP. + + CALL FUNCTION 'VRM_SET_VALUES' + EXPORTING + id = lv_id + values = lt_values + EXCEPTIONS + id_illegal_name = 1 + OTHERS = 2. + +ENDFORM. " SETUP_LISTBOXES + + +*&---------------------------------------------------------------------* +*& Form GET_IMPLEMENTING_CLASSDS +*&---------------------------------------------------------------------* +FORM get_implementing_classds USING iv_interface_name TYPE clike + CHANGING ct_implementing_classes TYPE seo_relkeys. + + DATA: lo_oo_interface TYPE REF TO cl_oo_interface, + lo_oo_class TYPE REF TO cl_oo_class, + lt_implementing_subclasses TYPE seo_relkeys. + + FIELD-SYMBOLS: <ls_implementing_class> LIKE LINE OF ct_implementing_classes. + + TRY. + lo_oo_interface ?= cl_oo_interface=>get_instance( iv_interface_name ). + CATCH cx_class_not_existent. + RETURN. + ENDTRY. + ct_implementing_classes = lo_oo_interface->get_implementing_classes( ). + + LOOP AT ct_implementing_classes ASSIGNING <ls_implementing_class>. + TRY. + lo_oo_class ?= cl_oo_class=>get_instance( <ls_implementing_class>-clsname ). + lt_implementing_subclasses = lo_oo_class->get_subclasses( ). + APPEND LINES OF lt_implementing_subclasses TO ct_implementing_classes. + CATCH cx_class_not_existent. + ENDTRY. + ENDLOOP. + + +ENDFORM. " GET_IMPLEMENTING_CLASSDS + + +*&---------------------------------------------------------------------* +*& Form READ_TEMPLATE +*&---------------------------------------------------------------------* +FORM read_template RAISING zcx_excel . + + CASE lb_read. + WHEN 'Autodetect'(001). + FIND REGEX '(\.xlsx|\.xlsm)\s*$' IN p_upfile SUBMATCHES lv_extension. + TRANSLATE lv_extension TO UPPER CASE. + CASE lv_extension. + + WHEN '.XLSX'. + CREATE OBJECT reader TYPE zcl_excel_reader_2007. + excel = reader->load_file( p_upfile ). + "Use template for charts + excel->use_template = abap_true. + + WHEN '.XLSM'. + CREATE OBJECT reader TYPE zcl_excel_reader_xlsm. + excel = reader->load_file( p_upfile ). + "Use template for charts + excel->use_template = abap_true. + + WHEN OTHERS. + MESSAGE 'Unsupported filetype' TYPE 'I'. + RETURN. + + ENDCASE. + + WHEN OTHERS. + CREATE OBJECT reader TYPE (lb_read). + excel = reader->load_file( p_upfile ). + "Use template for charts + excel->use_template = abap_true. + + ENDCASE. + +ENDFORM. " READ_TEMPLATE + + +*&---------------------------------------------------------------------* +*& Form WRITE_TEMPLATE +*&---------------------------------------------------------------------* +FORM write_template RAISING zcx_excel. + + CASE lb_write. + + WHEN 'Autodetect'(001). + FIND REGEX '(\.xlsx|\.xlsm)\s*$' IN p_upfile SUBMATCHES lv_extension. + TRANSLATE lv_extension TO UPPER CASE. + CASE lv_extension. + + WHEN '.XLSX'. + REPLACE '&' IN gc_save_file_name WITH 'xlsx'. " Pass extension for standard writer + lcl_output=>output( excel ). + + WHEN '.XLSM'. + REPLACE '&' IN gc_save_file_name WITH 'xlsm'. " Pass extension for macro-writer + lcl_output=>output( cl_excel = excel + iv_writerclass_name = 'ZCL_EXCEL_WRITER_XLSM' ). + + WHEN OTHERS. + MESSAGE 'Unsupported filetype' TYPE 'I'. + RETURN. + + ENDCASE. + + WHEN OTHERS. + lcl_output=>output( cl_excel = excel + iv_writerclass_name = lb_write ). + ENDCASE. + +ENDFORM. " WRITE_TEMPLATE + + + + + + + + + REPORT. + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_drawing TYPE REF TO zcl_excel_drawing. + +TYPES: BEGIN OF gty_icon, +* name TYPE icon_name, "Fix #228 + name TYPE iconname, "Fix #228 + objid TYPE w3objid, + END OF gty_icon, + gtyt_icon TYPE STANDARD TABLE OF gty_icon WITH NON-UNIQUE DEFAULT KEY. + +DATA: lt_icon TYPE gtyt_icon, + lv_row TYPE sytabix, + ls_wwwdatatab TYPE wwwdatatab, + lt_mimedata TYPE STANDARD TABLE OF w3mime WITH NON-UNIQUE DEFAULT KEY, + lv_xstring TYPE xstring. + +FIELD-SYMBOLS: <icon> LIKE LINE OF lt_icon, + <mimedata> LIKE LINE OF lt_mimedata. + +CONSTANTS: gc_save_file_name TYPE string VALUE '38_SAP-Icons.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +TABLES: icon. +SELECT-OPTIONS: s_icon FOR icon-name DEFAULT 'ICON_LED_*' OPTION CP. + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo Icons' ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). + lo_column_dimension->set_auto_size( 'X' ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( 'X' ). + +* Get all icons + SELECT name + INTO TABLE lt_icon + FROM icon + WHERE name IN s_icon + ORDER BY name. + LOOP AT lt_icon ASSIGNING <icon>. + + lv_row = sy-tabix. +*--------------------------------------------------------------------* +* Set name of icon +*--------------------------------------------------------------------* + lo_worksheet->set_cell( ip_row = lv_row + ip_column = 'A' + ip_value = <icon>-name ). +*--------------------------------------------------------------------* +* Check whether the mime-repository holds some icondata for us +*--------------------------------------------------------------------* + +* Get key + SELECT SINGLE objid + INTO <icon>-objid + FROM wwwdata + WHERE text = <icon>-name. + CHECK sy-subrc = 0. " :o( + lo_worksheet->set_cell( ip_row = lv_row + ip_column = 'B' + ip_value = <icon>-objid ). + +* Load mimedata + CLEAR lt_mimedata. + CLEAR ls_wwwdatatab. + ls_wwwdatatab-relid = 'MI' . + ls_wwwdatatab-objid = <icon>-objid. + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = ls_wwwdatatab + TABLES + mime = lt_mimedata + EXCEPTIONS + wrong_object_type = 1 + import_error = 2 + OTHERS = 3. + CHECK sy-subrc = 0. " :o( + + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = lv_row + ip_from_col = 'C' ). + CLEAR lv_xstring. + LOOP AT lt_mimedata ASSIGNING <mimedata>. + CONCATENATE lv_xstring <mimedata>-line INTO lv_xstring IN BYTE MODE. + ENDLOOP. + + lo_drawing->set_media( ip_media = lv_xstring + ip_media_type = zcl_excel_drawing=>c_media_type_jpg + ip_width = 16 + ip_height = 14 ). + lo_worksheet->add_drawing( lo_drawing ). + + ENDLOOP. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL16 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel39. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_drawing TYPE REF TO zcl_excel_drawing. + +DATA lv_value TYPE i. + +DATA: ls_io TYPE skwf_io. + +DATA: ls_upper TYPE zexcel_drawing_location, + ls_lower TYPE zexcel_drawing_location. + +DATA lo_bar1 TYPE REF TO zcl_excel_graph_bars. +DATA lo_bar2 TYPE REF TO zcl_excel_graph_bars. +DATA lo_pie TYPE REF TO zcl_excel_graph_pie. +DATA lo_line TYPE REF TO zcl_excel_graph_line. + +CONSTANTS: gc_save_file_name TYPE string VALUE '39_Charts.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + " Create a pie chart and series + CREATE OBJECT lo_pie. + + CALL METHOD lo_pie->create_serie + EXPORTING + ip_order = 0 + ip_sheet = 'Values' + ip_lbl_from_col = 'B' + ip_lbl_from_row = '1' + ip_lbl_to_col = 'B' + ip_lbl_to_row = '3' + ip_ref_from_col = 'A' + ip_ref_from_row = '1' + ip_ref_to_col = 'A' + ip_ref_to_row = '3' + ip_sername = 'My serie 1'. + + " Set style + lo_pie->set_style( zcl_excel_graph=>c_style_15 ). + + " Create a bar chart, series and axes + CREATE OBJECT lo_bar1. + + CALL METHOD lo_bar1->create_serie + EXPORTING + ip_order = 0 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_no + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_bar1->create_serie + EXPORTING + ip_order = 1 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_no + ip_lbl = 'Values!$B$1:$B$3' + ip_ref = 'Values!$A$1:$A$3' + ip_sername = 'My serie 2'. + + CALL METHOD lo_bar1->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_catax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + CALL METHOD lo_bar1->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_valax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + " Set style + lo_bar1->set_style( zcl_excel_graph=>c_style_default ). + + " Set label to none + lo_bar1->set_print_lbl( zcl_excel_graph_bars=>c_show_false ). + + " Create a bar chart, series and axes + CREATE OBJECT lo_bar2. + + CALL METHOD lo_bar2->create_serie + EXPORTING + ip_order = 0 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_yes + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_bar2->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_catax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + CALL METHOD lo_bar2->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_valax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + " Set layout + lo_bar2->set_show_legend_key( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_values( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_cat_name( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_ser_name( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_percent( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_varycolor( zcl_excel_graph_bars=>c_show_true ). + + " Create a line chart, series and axes + CREATE OBJECT lo_line. + + CALL METHOD lo_line->create_serie + EXPORTING + ip_order = 0 + ip_symbol = zcl_excel_graph_line=>c_symbol_auto + ip_smooth = zcl_excel_graph_line=>c_show_false + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_line->create_serie + EXPORTING + ip_order = 1 + ip_symbol = zcl_excel_graph_line=>c_symbol_none + ip_smooth = zcl_excel_graph_line=>c_show_false + ip_lbl = 'Values!$B$1:$B$3' + ip_ref = 'Values!$A$1:$A$3' + ip_sername = 'My serie 2'. + + CALL METHOD lo_line->create_serie + EXPORTING + ip_order = 2 + ip_symbol = zcl_excel_graph_line=>c_symbol_auto + ip_smooth = zcl_excel_graph_line=>c_show_false + ip_lbl = 'Values!$F$1:$F$3' + ip_ref = 'Values!$E$1:$E$3' + ip_sername = 'My serie 3'. + + CALL METHOD lo_line->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_line=>c_catax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + CALL METHOD lo_line->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_line=>c_valax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + + + + + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet (Pie sheet) + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'PieChart' ). + + " Create global drawing, set type as pie chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART PIE' ). + lo_drawing->graph = lo_pie. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_pie. + + "Set chart position (anchor 2 cells) + ls_lower-row = 30. + ls_lower-col = 20. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " BarChart1 sheet + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'BarChart1' ). + + " Create global drawing, set type as bar chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART BARS WITH 2 SERIES' ). + lo_drawing->graph = lo_bar1. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_bars. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 11. + ls_lower-row = 22. + ls_lower-col = 21. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " BarChart2 sheet + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'BarChart2' ). + + " Create global drawing, set type as bar chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART BARS WITH 1 SERIE' ). + lo_drawing->graph = lo_bar2. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_bars. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 0. + ls_lower-row = 30. + ls_lower-col = 20. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " LineChart sheet + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'LineChart' ). + + " Create global drawing, set type as line chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART LINES' ). + lo_drawing->graph = lo_line. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_line. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 0. + ls_lower-row = 30. + ls_lower-col = 20. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " Values sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for chart + lv_value = 1. + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = lv_value ). + lv_value = 2. + lo_worksheet->set_cell( ip_column = 'A' ip_row = 2 ip_value = lv_value ). + lv_value = 3. + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = lv_value ). + + " Set labels for chart + lo_worksheet->set_cell( ip_column = 'B' ip_row = 1 ip_value = 'One' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Two' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'Three' ). + + " Set values for chart + lv_value = 3. + lo_worksheet->set_cell( ip_column = 'C' ip_row = 1 ip_value = lv_value ). + lv_value = 2. + lo_worksheet->set_cell( ip_column = 'C' ip_row = 2 ip_value = lv_value ). + lv_value = -1. + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = lv_value ). + + " Set labels for chart + lo_worksheet->set_cell( ip_column = 'D' ip_row = 3 ip_value = 'One (Minus)' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 2 ip_value = 'Two' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 1 ip_value = 'Three' ). + + " Set values for chart + lv_value = 3. + lo_worksheet->set_cell( ip_column = 'E' ip_row = 1 ip_value = lv_value ). + lv_value = 1. + lo_worksheet->set_cell( ip_column = 'E' ip_row = 2 ip_value = lv_value ). + lv_value = 2. + lo_worksheet->set_cell( ip_column = 'E' ip_row = 3 ip_value = lv_value ). + + " Set labels for chart + lo_worksheet->set_cell( ip_column = 'F' ip_row = 3 ip_value = 'Two' ). + lo_worksheet->set_cell( ip_column = 'F' ip_row = 2 ip_value = 'One' ). + lo_worksheet->set_cell( ip_column = 'F' ip_row = 1 ip_value = 'Three' ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL4 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel4. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + + lv_tabcolor TYPE zexcel_s_tabcolor, + + ls_header TYPE zexcel_s_worksheet_head_foot, + ls_footer TYPE zexcel_s_worksheet_head_foot. + +CONSTANTS: gc_save_file_name TYPE string VALUE '04_Sheets.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->zif_excel_sheet_properties~selected = zif_excel_sheet_properties=>c_selected. + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the first sheet' ). +* Set color to tab with sheetname - Red + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = 'FF' + ip_green = '00' + ip_blu = '00' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet2!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to second sheet' ip_hyperlink = lo_hyperlink ). + + " Page printing settings + lo_worksheet->sheet_setup->set_page_margins( ip_header = '1' ip_footer = '1' ip_unit = 'cm' ). + lo_worksheet->sheet_setup->black_and_white = 'X'. + lo_worksheet->sheet_setup->fit_to_page = 'X'. " you should turn this on to activate fit_to_height and fit_to_width + lo_worksheet->sheet_setup->fit_to_height = 0. " used only if ip_fit_to_page = 'X' + lo_worksheet->sheet_setup->fit_to_width = 2. " used only if ip_fit_to_page = 'X' + lo_worksheet->sheet_setup->orientation = zcl_excel_sheet_setup=>c_orientation_landscape. + lo_worksheet->sheet_setup->page_order = zcl_excel_sheet_setup=>c_ord_downthenover. + lo_worksheet->sheet_setup->paper_size = zcl_excel_sheet_setup=>c_papersize_a4. + lo_worksheet->sheet_setup->scale = 80. " used only if ip_fit_to_page = SPACE + + " Header and Footer + ls_header-right_value = 'print date &D'. + ls_header-right_font-size = 8. + ls_header-right_font-name = zcl_excel_style_font=>c_name_arial. + + ls_footer-left_value = '&Z&F'. "Path / Filename + ls_footer-left_font = ls_header-right_font. + ls_footer-right_value = 'page &P of &N'. "page x of y + ls_footer-right_font = ls_header-right_font. + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). +* Set color to tab with sheetname - Green + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = '00' + ip_green = 'FF' + ip_blu = '00' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + lo_worksheet->zif_excel_sheet_properties~selected = zif_excel_sheet_properties=>c_selected. + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the second sheet' ). + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet1!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to first sheet' ip_hyperlink = lo_hyperlink ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 4 ip_value = 'Sheet3 is hidden' ). + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet3' ). +* Set color to tab with sheetname - Blue + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = '00' + ip_green = '00' + ip_blu = 'FF' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + lo_worksheet->zif_excel_sheet_properties~hidden = zif_excel_sheet_properties=>c_hidden. + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet4' ). +* Set color to tab with sheetname - other color + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = '00' + ip_green = 'FF' + ip_blu = 'FF' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Cell B3 has value 0' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 0 ). + lo_worksheet->zif_excel_sheet_properties~show_zeros = zif_excel_sheet_properties=>c_hidezero. + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + lo_excel->set_active_sheet_index_by_name( 'Sheet1' ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + REPORT. + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lv_row TYPE zexcel_cell_row, + lv_col TYPE i, + lv_row_char TYPE char10, + lv_value TYPE string, + ls_fontcolor TYPE zexcel_style_color_argb. + +CONSTANTS: gc_save_file_name TYPE string VALUE '40_Printsettings.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo Printsettings' ). + +*--------------------------------------------------------------------* +* Prepare sheet with trivial data +* - first 4 columns will have fontocolor set +* - first 3 rows will have fontcolor set +* These marked cells will be used for repeatable rows/columns on printpages +*--------------------------------------------------------------------* + DO 100 TIMES. " Rows + + lv_row = sy-index . + WRITE lv_row TO lv_row_char. + + DO 20 TIMES. + + lv_col = sy-index - 1. + CONCATENATE sy-abcde+lv_col(1) lv_row_char INTO lv_value. + lv_col = sy-index. + lo_worksheet->set_cell( ip_row = lv_row + ip_column = lv_col + ip_value = lv_value ). + + TRY. + IF lv_row <= 3. + lo_worksheet->change_cell_style( ip_column = lv_col + ip_row = lv_row + ip_fill_filltype = zcl_excel_style_fill=>c_fill_solid + ip_fill_fgcolor_rgb = zcl_excel_style_color=>c_yellow ). + ENDIF. + IF lv_col <= 4. + lo_worksheet->change_cell_style( ip_column = lv_col + ip_row = lv_row + ip_font_color_rgb = zcl_excel_style_color=>c_red ). + ENDIF. + CATCH zcx_excel . + ENDTRY. + + ENDDO. + + + + ENDDO. + + +*--------------------------------------------------------------------* +* Printsettings +*--------------------------------------------------------------------* + TRY. + lo_worksheet->zif_excel_sheet_printsettings~set_print_repeat_columns( iv_columns_from = 'A' + iv_columns_to = 'D' ). + lo_worksheet->zif_excel_sheet_printsettings~set_print_repeat_rows( iv_rows_from = 1 + iv_rows_to = 3 ). + CATCH zcx_excel . + ENDTRY. + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL5 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel5. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional. + +DATA: ls_iconset TYPE zexcel_conditional_iconset. + + + +CONSTANTS: gc_save_file_name TYPE string VALUE '05_Conditional.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + + + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights2. + 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 = '33'. + ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo3_value = '66'. + ls_iconset-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + lo_style_conditional->mode_iconset = ls_iconset. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 4 + ip_stop_column = 'C' + ip_stop_row = 8 ). + + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 100 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 1000 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 150 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 500 ). + + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights2. + ls_iconset-showvalue = zcl_excel_style_conditional=>c_showvalue_false. + lo_style_conditional->mode_iconset = ls_iconset. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 4 + ip_stop_column = 'E' + ip_stop_row = 8 ). + + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = 100 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'E' ip_value = 1000 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'E' ip_value = 150 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'E' ip_value = 500 ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL6 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel6. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_row TYPE syindex, + lv_formula TYPE string. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '06_Formulas.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + +*--------------------------------------------------------------------* +* Get some testdata +*--------------------------------------------------------------------* + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 100 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 1000 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 150 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = -10 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 500 ). + + +*--------------------------------------------------------------------* +* Demonstrate using formulas +*--------------------------------------------------------------------* + lo_worksheet->set_cell( ip_row = 9 ip_column = 'C' ip_formula = 'SUM(C4:C8)' ). + + +*--------------------------------------------------------------------* +* Demonstrate standard EXCEL-behaviour when copying a formula to another cell +* by calculating the resulting formula to put into another cell +*--------------------------------------------------------------------* + DO 10 TIMES. + + lv_formula = zcl_excel_common=>shift_formula( iv_reference_formula = 'SUM(C4:C8)' + iv_shift_cols = 0 " Offset in Columns - here we copy in same column --> 0 + iv_shift_rows = sy-index ). " Offset in Row - here we copy downward --> sy-index + lv_row = 9 + sy-index. " Absolute row = sy-index rows below reference cell + lo_worksheet->set_cell( ip_row = lv_row ip_column = 'C' ip_formula = lv_formula ). + + ENDDO. + +*--------------------------------------------------------------------* +*** Create output +*--------------------------------------------------------------------* + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL7 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel7. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional. + +DATA: ls_iconset3 TYPE zexcel_conditional_iconset, + ls_iconset4 TYPE zexcel_conditional_iconset, + ls_iconset5 TYPE zexcel_conditional_iconset, + ls_databar TYPE zexcel_conditional_databar, + ls_colorscale2 TYPE zexcel_conditional_colorscale, + ls_colorscale3 TYPE zexcel_conditional_colorscale. + +CONSTANTS: gc_save_file_name TYPE string VALUE '07_ConditionalAll.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + ls_iconset3-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset3-cfvo1_value = '0'. + ls_iconset3-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset3-cfvo2_value = '33'. + ls_iconset3-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset3-cfvo3_value = '66'. + ls_iconset3-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + ls_iconset4-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo1_value = '0'. + ls_iconset4-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo2_value = '25'. + ls_iconset4-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo3_value = '50'. + ls_iconset4-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo4_value = '75'. + ls_iconset4-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + ls_iconset5-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo1_value = '0'. + ls_iconset5-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo2_value = '20'. + ls_iconset5-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo3_value = '40'. + ls_iconset5-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo4_value = '60'. + ls_iconset5-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo5_value = '80'. + ls_iconset5-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + ls_databar-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_min. + ls_databar-cfvo1_value = '0'. + ls_databar-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_max. + ls_databar-cfvo2_value = '0'. + ls_databar-colorrgb = 'FF638EC6'. + + ls_colorscale2-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_min. + ls_colorscale2-cfvo1_value = '0'. + ls_colorscale2-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percentile. + ls_colorscale2-cfvo2_value = '50'. + ls_colorscale2-colorrgb1 = 'FFF8696B'. + ls_colorscale2-colorrgb2 = 'FF63BE7B'. + + ls_colorscale3-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_min. + ls_colorscale3-cfvo1_value = '0'. + ls_colorscale3-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percentile. + ls_colorscale3-cfvo2_value = '50'. + ls_colorscale3-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_max. + ls_colorscale3-cfvo3_value = '0'. + ls_colorscale3-colorrgb1 = 'FFF8696B'. + ls_colorscale3-colorrgb2 = 'FFFFEB84'. + ls_colorscale3-colorrgb3 = 'FF63BE7B'. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + +* ICONSET + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3arrows. + + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 5 + ip_stop_column = 'B' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'C_ICONSET_3ARROWS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3arrowsgray. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 5 + ip_stop_column = 'C' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'C_ICONSET_3ARROWSGRAY' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'C' ip_value = 50 ). + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3flags. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 5 + ip_stop_column = 'D' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'C_ICONSET_3FLAGS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 5 + ip_stop_column = 'E' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = 'C_ICONSET_3TRAFFICLIGHTS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'E' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'E' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'E' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'E' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights2. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'F' + ip_start_row = 5 + ip_stop_column = 'F' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'F' ip_value = 'C_ICONSET_3TRAFFICLIGHTS2' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'F' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'F' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'F' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'F' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'F' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3signs. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'G' + ip_start_row = 5 + ip_stop_column = 'G' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'G' ip_value = 'C_ICONSET_3SIGNS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'G' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'G' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'G' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'G' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'G' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3symbols. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'H' + ip_start_row = 5 + ip_stop_column = 'H' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'H' ip_value = 'C_ICONSET_3SYMBOLS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'H' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'H' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'H' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'H' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'H' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3symbols2. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'I' + ip_start_row = 5 + ip_stop_column = 'I' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'I' ip_value = 'C_ICONSET_3SYMBOLS2' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'I' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'I' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'I' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'I' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'I' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4arrows. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 12 + ip_stop_column = 'B' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'B' ip_value = 'C_ICONSET_4ARROWS' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4arrowsgray. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 12 + ip_stop_column = 'C' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'C' ip_value = 'C_ICONSET_4ARROWSGRAY' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'C' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4redtoblack. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 12 + ip_stop_column = 'D' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'D' ip_value = 'C_ICONSET_4REDTOBLACK' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4rating. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 12 + ip_stop_column = 'E' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'E' ip_value = 'C_ICONSET_4RATING' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'E' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'E' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'E' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'E' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4trafficlights. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'F' + ip_start_row = 12 + ip_stop_column = 'F' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'F' ip_value = 'C_ICONSET_4TRAFFICLIGHTS' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'F' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'F' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'F' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'F' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'F' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5arrows. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 19 + ip_stop_column = 'B' + ip_stop_row = 23 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'B' ip_value = 'C_ICONSET_5ARROWS' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5arrowsgray. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 19 + ip_stop_column = 'C' + ip_stop_row = 23 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'C' ip_value = 'C_ICONSET_5ARROWSGRAY' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'C' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5rating. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 19 + ip_stop_column = 'D' + ip_stop_row = 23 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'D' ip_value = 'C_ICONSET_5RATING' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5quarters. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 19 + ip_stop_column = 'E' + ip_stop_row = 23 ). + +* DATABAR + + lo_worksheet->set_cell( ip_row = 25 ip_column = 'B' ip_value = 'DATABAR' ). + lo_worksheet->set_cell( ip_row = 26 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 27 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 28 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 29 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 30 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_databar. + lo_style_conditional->priority = 1. + lo_style_conditional->mode_databar = ls_databar. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 26 + ip_stop_column = 'B' + ip_stop_row = 30 ). + +* COLORSCALE + + lo_worksheet->set_cell( ip_row = 25 ip_column = 'C' ip_value = 'COLORSCALE 2 COLORS' ). + lo_worksheet->set_cell( ip_row = 26 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 27 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 28 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 29 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 30 ip_column = 'C' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_colorscale. + lo_style_conditional->priority = 1. + lo_style_conditional->mode_colorscale = ls_colorscale2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 26 + ip_stop_column = 'C' + ip_stop_row = 30 ). + + + lo_worksheet->set_cell( ip_row = 25 ip_column = 'D' ip_value = 'COLORSCALE 3 COLORS' ). + lo_worksheet->set_cell( ip_row = 26 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 27 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 28 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 29 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 30 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_colorscale. + lo_style_conditional->priority = 1. + lo_style_conditional->mode_colorscale = ls_colorscale3. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 26 + ip_stop_column = 'D' + ip_stop_row = 30 ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL8 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel8. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range. + +DATA: lv_title TYPE zexcel_sheet_title. + +CONSTANTS: gc_save_file_name TYPE string VALUE '08_Range.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lv_title = 'Sheet1'. + lo_worksheet->set_title( lv_title ). + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'range'. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'C' + ip_start_row = 4 + ip_stop_column = 'C' + ip_stop_row = 8 ). + + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'Apple' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 'Banana' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 'Blueberry' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Ananas' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Grapes' ). + + " Define another Range with a name longer than 40 characters that + " tests the fix of issue #168 ranges namescan be only up to 20 chars + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'A_range_with_a_name_that_is_longer_than_20_characters'. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'D' + ip_start_row = 4 + ip_stop_column = 'D' + ip_stop_row = 5 ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'Range Value 1' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 'Range Value 2' ). + + " issue #163 + " Define another Range with sheet visibility + lo_range = lo_worksheet->add_new_range( ). + lo_range->name = 'A_range_with_sheet_visibility'. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'E' + ip_start_row = 4 + ip_stop_column = 'E' + ip_stop_row = 5 ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = 'Range Value 3' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'E' ip_value = 'Range Value 4' ). + " issue #163 + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL9 +*& +*&---------------------------------------------------------------------* +*& abap2xlsx Demo: Data validations +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel9. + +CONSTANTS: c_fruits TYPE string VALUE 'Fruits', + c_vegetables TYPE string VALUE 'Vegetables', + c_meat TYPE string VALUE 'Meat', + c_fish TYPE string VALUE 'Fish'. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation. + +DATA: row TYPE zexcel_cell_row. + + +DATA: lv_title TYPE zexcel_sheet_title. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '09_DataValidation.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_sbook TYPE flag. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lv_title = 'Data Validation'. + lo_worksheet->set_title( lv_title ). + " Set values for dropdown + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = c_fish ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 'Anchovy' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 'Carp' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 'Catfish' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 'Cod' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 'Eel' ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'A' ip_value = 'Haddock' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_fish. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'B' ip_value = c_meat ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'Pork' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'B' ip_value = 'Beef' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 'Chicken' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'B' ip_value = 'Turkey' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_meat. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'B' + ip_start_row = 4 + ip_stop_column = 'B' + ip_stop_row = 7 ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'C' ip_value = c_fruits ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'Apple' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 'Banana' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 'Blueberry' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Ananas' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Grapes' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_fruits. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'C' + ip_start_row = 4 + ip_stop_column = 'C' + ip_stop_row = 8 ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'D' ip_value = c_vegetables ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'Cucumber' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 'Sweet pepper ' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'D' ip_value = 'Lettuce' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_vegetables. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'D' + ip_start_row = 4 + ip_stop_column = 'D' + ip_stop_row = 6 ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lv_title = 'Table with Data Validation'. + lo_worksheet->set_title( lv_title ). + + " Maximum Text length + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'Validate Maximum Text length of <= 10 in Cell A2:' ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = 'abcdefghij' ). + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_textlength. + lo_data_validation->operator = zcl_excel_data_validation=>c_operator_lessthanorequal. + lo_data_validation->formula1 = 10. + lo_data_validation->cell_row = 2. + lo_data_validation->cell_column = 'A'. + + " Integer Value between 1 and 10 + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 'Validate Integer Value between 1 and 10 in Cell A5:' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = '5' ). + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_whole. + lo_data_validation->operator = zcl_excel_data_validation=>c_operator_between. + lo_data_validation->formula1 = 1. + lo_data_validation->formula2 = 10. + lo_data_validation->prompttitle = 'Range'. + lo_data_validation->prompt = 'Enter a value between 1 and 10'. + lo_data_validation->errortitle = 'Error'. + lo_data_validation->error = 'You have entered a wrong value. Please use only numbers between 1 and 10.'. + lo_data_validation->cell_row = 5. + lo_data_validation->cell_column = 'A'. + + " Evaluation by Formula from issue #161 + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 'Validate if B8 contains a "-":' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 'Text' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'B' ip_value = '-' ). + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_custom. + lo_data_validation->formula1 = '"IF(B8<>"""";INDIRECT(LEFT(B8;SEARCH(""-"";B8;1)));EMPTY)"'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'A'. + + " There was an error when data validation was combined with cell merges this should test that: + lo_worksheet->set_cell( ip_row = 10 ip_column = 'A' ip_value = 'Demo for data validation with a dropdown list' ). + lo_worksheet->set_merge( ip_row = 10 ip_column_start = 'A' ip_column_end = 'F' ). + + " Headlines + lo_worksheet->set_cell( ip_row = 11 ip_column = 'A' ip_value = c_fruits ). + lo_worksheet->set_cell( ip_row = 11 ip_column = 'B' ip_value = c_vegetables ). + + row = 12. + WHILE row < 20. " Starting with 14500 the data validation is dropped 14000 are still ok + " 1st validation + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_fruits. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'A'. + lo_worksheet->set_cell( ip_row = row ip_column = 'A' ip_value = 'Select a value' ). + " 2nd + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_vegetables. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'B'. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = 'Select a value' ). + " 3rd + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_meat. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = 'Select a value' ). + " 4th + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_fish. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'D'. + lo_worksheet->set_cell( ip_row = row ip_column = 'D' ip_value = 'Select a value' ). + " Increment row + row = row + 1. + ENDWHILE. + + IF p_sbook = abap_true. + DATA: bookings type TABLE OF sbook. + + lo_worksheet = lo_excel->add_new_worksheet( ). + lv_title = 'SBOOK'. + lo_worksheet->set_title( lv_title ). + + SELECT * from sbook INTO TABLE bookings UP TO 4000 ROWS. + + lo_worksheet->bind_table( + EXPORTING + ip_table = bookings +* it_field_catalog = " Table binding field catalog +* is_table_settings = " Excel table binding settings +* IMPORTING +* es_table_settings = " Excel table binding settings + ). + ENDIF. + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Include ZDEMO_EXCEL_OUTPUTOPT_INCL +*&---------------------------------------------------------------------* +CLASS lcl_output DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS: + output IMPORTING cl_excel TYPE REF TO zcl_excel + iv_writerclass_name TYPE clike OPTIONAL, + f4_path RETURNING VALUE(selected_folder) TYPE string, + parametertexts. + + PRIVATE SECTION. + METHODS: + download_frontend, + download_backend, + display_online, + send_email. + + DATA: xdata TYPE xstring, " Will be used for sending as email + t_rawdata TYPE solix_tab, " Will be used for downloading or open directly + bytecount TYPE i. " Will be used for downloading or open directly +ENDCLASS. "lcl_output DEFINITION + + +SELECTION-SCREEN BEGIN OF BLOCK bl1 WITH FRAME TITLE txt_bl1. +PARAMETERS: rb_down RADIOBUTTON GROUP rb1 USER-COMMAND space. + +PARAMETERS: rb_back RADIOBUTTON GROUP rb1. + +PARAMETERS: rb_show RADIOBUTTON GROUP rb1 DEFAULT 'X' . + +PARAMETERS: rb_send RADIOBUTTON GROUP rb1. + +PARAMETERS: p_path TYPE string LOWER CASE MODIF ID pat. +PARAMETERS: p_email TYPE string LOWER CASE MODIF ID ema OBLIGATORY DEFAULT 'insert_your_emailadress@here'. +PARAMETERS: p_backfn TYPE text40 NO-DISPLAY. +SELECTION-SCREEN END OF BLOCK bl1. + + +AT SELECTION-SCREEN OUTPUT. + LOOP AT SCREEN. + + IF rb_down IS INITIAL AND screen-group1 = 'PAT'. + screen-input = 0. + screen-invisible = 1. + ENDIF. + + IF rb_send IS INITIAL AND screen-group1 = 'EMA'. + screen-input = 0. + screen-invisible = 1. + ENDIF. + + MODIFY SCREEN. + + ENDLOOP. + +INITIALIZATION. + IF sy-batch IS INITIAL. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = p_path ). + cl_gui_cfw=>flush( ). + ENDIF. + lcl_output=>parametertexts( ). " If started in language w/o textelements translated set defaults + sy-title = gc_save_file_name. + txt_bl1 = 'Output options'(bl1). + p_backfn = gc_save_file_name. " Use as default if nothing else is supplied by submit + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + p_path = lcl_output=>f4_path( ). + + +*----------------------------------------------------------------------* +* CLASS lcl_output IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_output IMPLEMENTATION. + METHOD output. + + DATA: cl_output TYPE REF TO lcl_output, + cl_writer TYPE REF TO zif_excel_writer. + + IF iv_writerclass_name IS INITIAL. + CREATE OBJECT cl_output. + CREATE OBJECT cl_writer TYPE zcl_excel_writer_2007. + ELSE. + CREATE OBJECT cl_output. + CREATE OBJECT cl_writer TYPE (iv_writerclass_name). + ENDIF. + cl_output->xdata = cl_writer->write_file( cl_excel ). + +* After 6.40 via cl_bcs_convert + cl_output->t_rawdata = cl_bcs_convert=>xstring_to_solix( iv_xstring = cl_output->xdata ). + cl_output->bytecount = xstrlen( cl_output->xdata ). + +* before 6.40 +* CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' +* EXPORTING +* buffer = cl_output->xdata +* IMPORTING +* output_length = cl_output->bytecount +* TABLES +* binary_tab = cl_output->t_rawdata. + + CASE 'X'. + WHEN rb_down. + IF sy-batch IS INITIAL. + cl_output->download_frontend( ). + ELSE. + MESSAGE e001(00) WITH 'Frontenddownload impossible in background processing'. + ENDIF. + + WHEN rb_back. + cl_output->download_backend( ). + + WHEN rb_show. + IF sy-batch IS INITIAL. + cl_output->display_online( ). + ELSE. + MESSAGE e001(00) WITH 'Online display absurd in background processing'. + ENDIF. + + WHEN rb_send. + cl_output->send_email( ). + + ENDCASE. + ENDMETHOD. "output + + METHOD f4_path. + DATA: new_path TYPE string, + repid TYPE syrepid, + dynnr TYPE sydynnr, + lt_dynpfields TYPE TABLE OF dynpread, + ls_dynpfields LIKE LINE OF lt_dynpfields. + +* Get current value + dynnr = sy-dynnr. + repid = sy-repid. + ls_dynpfields-fieldname = 'P_PATH'. + APPEND ls_dynpfields TO lt_dynpfields. + + CALL FUNCTION 'DYNP_VALUES_READ' + EXPORTING + dyname = repid + dynumb = dynnr + TABLES + dynpfields = lt_dynpfields + EXCEPTIONS + invalid_abapworkarea = 1 + invalid_dynprofield = 2 + invalid_dynproname = 3 + invalid_dynpronummer = 4 + invalid_request = 5 + no_fielddescription = 6 + invalid_parameter = 7 + undefind_error = 8 + double_conversion = 9 + stepl_not_found = 10 + OTHERS = 11. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + EXIT. + ENDIF. + + READ TABLE lt_dynpfields INTO ls_dynpfields INDEX 1. + + new_path = ls_dynpfields-fieldvalue. + selected_folder = new_path. + + cl_gui_frontend_services=>directory_browse( + EXPORTING + window_title = 'Select path to download EXCEL-file' + initial_folder = new_path + CHANGING + selected_folder = new_path + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4 + ). + cl_gui_cfw=>flush( ). + CHECK new_path IS NOT INITIAL. + selected_folder = new_path. + + ENDMETHOD. "f4_path + + METHOD parametertexts. +* If started in language w/o textelements translated set defaults +* Furthermore I don't have to change the selectiontexts of all demoreports. + DEFINE default_parametertext. + if %_&1_%_app_%-text = '&1' or + %_&1_%_app_%-text is initial. + %_&1_%_app_%-text = &2. + endif. + END-OF-DEFINITION. + + default_parametertext: rb_down 'Save to frontend', + rb_back 'Save to backend', + rb_show 'Direct display', + rb_send 'Send via email', + + p_path 'Frontend-path to download to', + p_email 'Email to send xlsx to'. + + ENDMETHOD. "parametertexts + + METHOD: download_frontend. + DATA: filename TYPE string. +* I don't like p_path here - but for this include it's ok + filename = p_path. +* Add trailing "\" or "/" + IF filename CA '/'. + REPLACE REGEX '([^/])\s*$' IN filename WITH '$1/' . + ELSE. + REPLACE REGEX '([^\\])\s*$' IN filename WITH '$1\\'. + ENDIF. + + CONCATENATE filename gc_save_file_name INTO filename. +* Get trailing blank + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = bytecount + filename = filename + filetype = 'BIN' + CHANGING data_tab = t_rawdata ). + ENDMETHOD. "download_frontend + + METHOD download_backend. + DATA: bytes_remain TYPE i. + FIELD-SYMBOLS: <rawdata> LIKE LINE OF t_rawdata. + + OPEN DATASET p_backfn FOR OUTPUT IN BINARY MODE. + CHECK sy-subrc = 0. + + bytes_remain = bytecount. + + LOOP AT t_rawdata ASSIGNING <rawdata>. + + AT LAST. + CHECK bytes_remain >= 0. + TRANSFER <rawdata> TO p_backfn LENGTH bytes_remain. + EXIT. + ENDAT. + + TRANSFER <rawdata> TO p_backfn. + SUBTRACT 255 FROM bytes_remain. " Solix has length 255 + + ENDLOOP. + + CLOSE DATASET p_backfn. + + + + + IF sy-calld = 'X'. " no need to display anything if download was selected and report was called for demo purposes + LEAVE PROGRAM. + ELSE. + MESSAGE 'Data transferred to default backend directory' TYPE 'I'. + ENDIF. + ENDMETHOD. "download_backend + + METHOD display_online. + 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, "OIContainerCtrl + cl_document TYPE REF TO i_oi_document_proxy. "Office Dokument + + 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 = cl_gui_container=>screen0 + 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 + + cl_document->open_document_from_table( EXPORTING document_size = bytecount + document_table = t_rawdata + open_inplace = 'X' ). + + WRITE: '.'. " To create an output. That way screen0 will exist + ENDMETHOD. "display_online + + METHOD send_email. +* Needed to send emails + DATA: bcs_exception TYPE REF TO cx_bcs, + errortext TYPE string, + cl_send_request TYPE REF TO cl_bcs, + cl_document TYPE REF TO cl_document_bcs, + cl_recipient TYPE REF TO if_recipient_bcs, + cl_sender TYPE REF TO cl_cam_address_bcs, + t_attachment_header TYPE soli_tab, + wa_attachment_header LIKE LINE OF t_attachment_header, + attachment_subject TYPE sood-objdes, + + sood_bytecount TYPE sood-objlen, + mail_title TYPE so_obj_des, + t_mailtext TYPE soli_tab, + wa_mailtext LIKE LINE OF t_mailtext, + send_to TYPE adr6-smtp_addr, + sent TYPE os_boolean. + + + mail_title = 'Mail title'. + wa_mailtext = 'Mailtext'. + APPEND wa_mailtext TO t_mailtext. + + TRY. +* Create send request + cl_send_request = cl_bcs=>create_persistent( ). +* Create new document with mailtitle and mailtextg + cl_document = cl_document_bcs=>create_document( i_type = 'RAW' "#EC NOTEXT + i_text = t_mailtext + i_subject = mail_title ). +* Add attachment to document +* since the new excelfiles have an 4-character extension .xlsx but the attachment-type only holds 3 charactes .xls, +* we have to specify the real filename via attachment header +* Use attachment_type xls to have SAP display attachment with the excel-icon + attachment_subject = gc_save_file_name. + CONCATENATE '&SO_FILENAME=' attachment_subject INTO wa_attachment_header. + APPEND wa_attachment_header TO t_attachment_header. +* Attachment + sood_bytecount = bytecount. " next method expects sood_bytecount instead of any positive integer *sigh* + cl_document->add_attachment( i_attachment_type = 'XLS' "#EC NOTEXT + i_attachment_subject = attachment_subject + i_attachment_size = sood_bytecount + i_att_content_hex = t_rawdata + i_attachment_header = t_attachment_header ). + +* add document to send request + cl_send_request->set_document( cl_document ). + +* set sender in case if no own email is availabe +* cl_sender = cl_cam_address_bcs=>create_internet_address( 'sender@sender.sender' ). +* cl_send_request->set_sender( cl_sender ). + +* add recipient(s) - here only 1 will be needed + send_to = p_email. + IF send_to IS INITIAL. + send_to = 'no_email@no_email.no_email'. " Place into SOST in any case for demonstration purposes + ENDIF. + cl_recipient = cl_cam_address_bcs=>create_internet_address( send_to ). + cl_send_request->add_recipient( cl_recipient ). + +* Und abschicken + sent = cl_send_request->send( i_with_error_screen = 'X' ). + + COMMIT WORK. + + IF sent IS INITIAL. + MESSAGE i500(sbcoms) WITH p_email. + ELSE. + MESSAGE s022(so). + MESSAGE 'Document ready to be sent - Check SOST or SCOT' TYPE 'I'. + ENDIF. + + CATCH cx_bcs INTO bcs_exception. + errortext = bcs_exception->if_message~get_text( ). + MESSAGE errortext TYPE 'I'. + + ENDTRY. + ENDMETHOD. "send_email + + +ENDCLASS. "lcl_output IMPLEMENTATION + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched1. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo01' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_reader TYPE REF TO zif_excel_reader, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +DATA: lt_files TYPE filetable, + ls_file TYPE file_table, + lv_rc TYPE i, + lv_value TYPE zexcel_cell_value. + +CONSTANTS: gc_save_file_name TYPE string VALUE 'TechEd01.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + +******************************* +* abap2xlsx read XLSX * +******************************* + CREATE OBJECT lo_excel_reader TYPE zcl_excel_reader_2007. + lo_excel = lo_excel_reader->load_file( lv_full_path ). + + lo_excel->set_active_sheet_index( 1 ). + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_worksheet->get_cell( EXPORTING ip_column = 'C' + ip_row = 10 + IMPORTING ep_value = lv_value ). + + WRITE: 'abap2xlsx total score is ', lv_value. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED2 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched2. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lv_style_title_guid TYPE zexcel_cell_style. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_value = 'Total score' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 10 ip_formula = 'SUM(C7:C8)' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_style_green TYPE REF TO zcl_excel_style, + lo_style_yellow TYPE REF TO zcl_excel_style, + lo_style_red TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lv_style_title_guid TYPE zexcel_cell_style, + lv_style_green_guid TYPE zexcel_cell_style, + lv_style_yellow_guid TYPE zexcel_cell_style, + lv_style_red_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_value = 'Total score' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 10 ip_formula = 'SUM(C7:C8)' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + +* ls_key-relid = 'MI'. +* ls_key-objid = 'WBLOGO'. +* lo_drawing->set_media_www( ip_key = ls_key +* ip_width = 140 +* ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " defne conditional styles + lo_style_green = lo_excel->add_new_style( ). + lo_style_green->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_green->fill->bgcolor-rgb = zcl_excel_style_color=>c_green. + lv_style_green_guid = lo_style_green->get_guid( ). + + lo_style_yellow = lo_excel->add_new_style( ). + lo_style_yellow->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_yellow->fill->bgcolor-rgb = zcl_excel_style_color=>c_yellow. + lv_style_yellow_guid = lo_style_yellow->get_guid( ). + + lo_style_red = lo_excel->add_new_style( ). + lo_style_red->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_red->fill->bgcolor-rgb = zcl_excel_style_color=>c_red. + lv_style_red_guid = lo_style_red->get_guid( ). + + " add conditional formatting + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_green_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 1. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_yellow_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '0'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_red_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 3. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_style_green TYPE REF TO zcl_excel_style, + lo_style_yellow TYPE REF TO zcl_excel_style, + lo_style_red TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lv_style_title_guid TYPE zexcel_cell_style, + lv_style_green_guid TYPE zexcel_cell_style, + lv_style_yellow_guid TYPE zexcel_cell_style, + lv_style_red_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis, + ls_key TYPE wwwdatatab. + +DATA: lo_send_request TYPE REF TO cl_bcs, + lo_document TYPE REF TO cl_document_bcs, + lo_sender TYPE REF TO cl_sapuser_bcs, + lo_recipient TYPE REF TO cl_sapuser_bcs, + lo_recipient_i TYPE REF TO CL_CAM_ADDRESS_BCS. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lv_bytecount_c TYPE sood-objlen, + lt_file_tab TYPE solix_tab. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_value = 'Total score' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 10 ip_formula = 'SUM(C7:C8)' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " defne conditional styles + lo_style_green = lo_excel->add_new_style( ). + lo_style_green->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_green->fill->bgcolor-rgb = zcl_excel_style_color=>c_green. + lv_style_green_guid = lo_style_green->get_guid( ). + + lo_style_yellow = lo_excel->add_new_style( ). + lo_style_yellow->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_yellow->fill->bgcolor-rgb = zcl_excel_style_color=>c_yellow. + lv_style_yellow_guid = lo_style_yellow->get_guid( ). + + lo_style_red = lo_excel->add_new_style( ). + lo_style_red->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_red->fill->bgcolor-rgb = zcl_excel_style_color=>c_red. + lv_style_red_guid = lo_style_red->get_guid( ). + + " add conditional formatting + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_green_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 1. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_yellow_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '0'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_red_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 3. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + lv_bytecount_c = lv_bytecount. + + " Send via email + lo_document = cl_document_bcs=>create_document( i_type = 'RAW' + i_subject = 'Demo TechEd' ). + + lo_document->add_attachment( i_attachment_type = 'EXT' + i_attachment_subject = 'abap2xlsx.xlsx' + i_attachment_size = lv_bytecount_c + i_att_content_hex = lt_file_tab ). + + lo_sender = cl_sapuser_bcs=>create( sy-uname ). + lo_recipient = cl_sapuser_bcs=>create( sy-uname ). +* lo_recipient_i = cl_cam_address_bcs=>create_internet_address( 'ivan.femia@techedge.it' ). + + lo_send_request = cl_bcs=>create_persistent( ). + lo_send_request->set_document( lo_document ). + lo_send_request->set_sender( lo_sender ). + lo_send_request->add_recipient( lo_recipient ). + lo_send_request->set_send_immediately( abap_true ). + lo_send_request->send( ). + + + + + + + + + + + + + + + + PROCESS BEFORE OUTPUT. + MODULE STATUS_9000. + +PROCESS AFTER INPUT. + MODULE USER_COMMAND_9000 AT EXIT-COMMAND. + MODULE USER_COMMAND_9000. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + REPORT. + +CONSTANTS: gc_save_file_name TYPE string VALUE 'ABAP2XLSX Inheritance.xlsx'. + +*--------------------------------------------------------------------* +* Demo inheritance ZCL_EXCEL1 +* Variation of ZCL_EXCEL that creates numerous sheets +*--------------------------------------------------------------------* +CLASS lcl_my_zcl_excel1 DEFINITION INHERITING FROM zcl_excel. + PUBLIC SECTION. + METHODS: constructor IMPORTING iv_sheetcount TYPE i DEFAULT 5. +ENDCLASS. + +CLASS lcl_my_zcl_excel1 IMPLEMENTATION. + METHOD constructor. + DATA: lv_sheets_to_create TYPE i. + super->constructor( ). + lv_sheets_to_create = iv_sheetcount - 1. " one gets created by standard class + DO lv_sheets_to_create TIMES. + TRY. + me->add_new_worksheet( ). + CATCH zcx_excel. + ENDTRY. + ENDDO. + me->set_active_sheet_index( 1 ). + + ENDMETHOD. +ENDCLASS. + +*--------------------------------------------------------------------* +* Demo inheritance ZCL_EXCEL_WORKSHEET +* Variation of ZCL_EXCEL_WORKSHEET ( and ZCL_EXCEL that calls the new type of worksheet ) +* that sets a fixed title +*--------------------------------------------------------------------* +CLASS lcl_my_zcl_excel2 DEFINITION INHERITING FROM zcl_excel. + PUBLIC SECTION. + METHODS: constructor. +ENDCLASS. + +CLASS lcl_my_zcl_excel_worksheet DEFINITION INHERITING FROM zcl_excel_worksheet. + PUBLIC SECTION. + METHODS: constructor IMPORTING ip_excel TYPE REF TO zcl_excel + ip_title TYPE zexcel_sheet_title OPTIONAL " Will be ignored - keep parameter for demonstration purpose + RAISING zcx_excel. +ENDCLASS. + +CLASS lcl_my_zcl_excel2 IMPLEMENTATION. + METHOD constructor. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet. + + super->constructor( ). + +* To use own worksheet we have to remove the standard worksheet + lo_worksheet = get_active_worksheet( ). + me->worksheets->remove( lo_worksheet ). +* and replace it with own version + CREATE OBJECT lo_worksheet TYPE lcl_my_zcl_excel_worksheet + EXPORTING + ip_excel = me + ip_title = 'This title will be ignored'. + me->worksheets->add( lo_worksheet ). + + ENDMETHOD. +ENDCLASS. + +CLASS lcl_my_zcl_excel_worksheet IMPLEMENTATION. + METHOD constructor. + super->constructor( ip_excel = ip_excel + ip_title = 'Inherited Worksheet' ). + + ENDMETHOD. +ENDCLASS. + +DATA: go_excel1 TYPE REF TO lcl_my_zcl_excel1. +DATA: go_excel2 TYPE REF TO lcl_my_zcl_excel2. + + +SELECTION-SCREEN BEGIN OF BLOCK bli WITH FRAME TITLE text-bli. +PARAMETERS: rbi_1 RADIOBUTTON GROUP rbi DEFAULT 'X' , " Simple inheritance + rbi_2 RADIOBUTTON GROUP rbi. +SELECTION-SCREEN END OF BLOCK bli. + +INCLUDE zdemo_excel_outputopt_incl. + +END-OF-SELECTION. + + CASE 'X'. + + WHEN rbi_1. " Simple inheritance of zcl_excel, object created directly + CREATE OBJECT go_excel1 + EXPORTING + iv_sheetcount = 5. + lcl_output=>output( go_excel1 ). + + WHEN rbi_2. " Inheritance of zcl_excel_worksheet, inheritance of zcl_excel needed to allow this + CREATE OBJECT go_excel2. + lcl_output=>output( go_excel2 ). + + + ENDCASE. + + + + + + + + *&---------------------------------------------------------------------* +*& 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 "#EC CI_SUBMIT + 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 "#EC CI_SUBMIT + 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 + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZANGRY_BIRDS +*& Just for fun +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zangry_birds. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_border_light TYPE REF TO zcl_excel_style_border, + lo_style_color0 TYPE REF TO zcl_excel_style, + lo_style_color1 TYPE REF TO zcl_excel_style, + lo_style_color2 TYPE REF TO zcl_excel_style, + lo_style_color3 TYPE REF TO zcl_excel_style, + lo_style_color4 TYPE REF TO zcl_excel_style, + lo_style_color5 TYPE REF TO zcl_excel_style, + lo_style_color6 TYPE REF TO zcl_excel_style, + lo_style_color7 TYPE REF TO zcl_excel_style, + lo_style_credit TYPE REF TO zcl_excel_style, + lo_style_link TYPE REF TO zcl_excel_style, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink. + +DATA: lv_style_color0_guid TYPE zexcel_cell_style, + lv_style_color1_guid TYPE zexcel_cell_style, + lv_style_color2_guid TYPE zexcel_cell_style, + lv_style_color3_guid TYPE zexcel_cell_style, + lv_style_color4_guid TYPE zexcel_cell_style, + lv_style_color5_guid TYPE zexcel_cell_style, + lv_style_color6_guid TYPE zexcel_cell_style, + lv_style_color7_guid TYPE zexcel_cell_style, + lv_style_credit_guid TYPE zexcel_cell_style, + lv_style_link_guid TYPE zexcel_cell_style, + lv_style TYPE zexcel_cell_style. + +DATA: lv_col_str TYPE zexcel_cell_column_alpha, + lv_row TYPE i, + lv_col TYPE i, + lt_mapper TYPE TABLE OF zexcel_cell_style, + ls_mapper TYPE zexcel_cell_style. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'angry_birds.xlsx'. + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + " Creates active sheet + CREATE OBJECT lo_excel. + + CREATE OBJECT lo_border_light. + lo_border_light->border_color-rgb = zcl_excel_style_color=>c_white. + lo_border_light->border_style = zcl_excel_style_border=>c_border_thin. + + " Create color white + lo_style_color0 = lo_excel->add_new_style( ). + lo_style_color0->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color0->fill->fgcolor-rgb = 'FFFFFFFF'. + lo_style_color0->borders->allborders = lo_border_light. + lv_style_color0_guid = lo_style_color0->get_guid( ). + + " Create color black + lo_style_color1 = lo_excel->add_new_style( ). + lo_style_color1->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color1->fill->fgcolor-rgb = 'FF252525'. + lo_style_color1->borders->allborders = lo_border_light. + lv_style_color1_guid = lo_style_color1->get_guid( ). + + " Create color dark green + lo_style_color2 = lo_excel->add_new_style( ). + lo_style_color2->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color2->fill->fgcolor-rgb = 'FF75913A'. + lo_style_color2->borders->allborders = lo_border_light. + lv_style_color2_guid = lo_style_color2->get_guid( ). + + " Create color light green + lo_style_color3 = lo_excel->add_new_style( ). + lo_style_color3->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color3->fill->fgcolor-rgb = 'FF9DFB73'. + lo_style_color3->borders->allborders = lo_border_light. + lv_style_color3_guid = lo_style_color3->get_guid( ). + + " Create color green + lo_style_color4 = lo_excel->add_new_style( ). + lo_style_color4->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color4->fill->fgcolor-rgb = 'FF92CF56'. + lo_style_color4->borders->allborders = lo_border_light. + lv_style_color4_guid = lo_style_color4->get_guid( ). + + " Create color 2dark green + lo_style_color5 = lo_excel->add_new_style( ). + lo_style_color5->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color5->fill->fgcolor-rgb = 'FF506228'. + lo_style_color5->borders->allborders = lo_border_light. + lv_style_color5_guid = lo_style_color5->get_guid( ). + + " Create color yellow + lo_style_color6 = lo_excel->add_new_style( ). + lo_style_color6->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color6->fill->fgcolor-rgb = 'FFC3E224'. + lo_style_color6->borders->allborders = lo_border_light. + lv_style_color6_guid = lo_style_color6->get_guid( ). + + " Create color yellow + lo_style_color7 = lo_excel->add_new_style( ). + lo_style_color7->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color7->fill->fgcolor-rgb = 'FFB3C14F'. + lo_style_color7->borders->allborders = lo_border_light. + lv_style_color7_guid = lo_style_color7->get_guid( ). + + " Credits + lo_style_credit = lo_excel->add_new_style( ). + lo_style_credit->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_credit->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lo_style_credit->font->size = 20. + lv_style_credit_guid = lo_style_credit->get_guid( ). + + " Link + lo_style_link = lo_excel->add_new_style( ). + lo_style_link->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_link->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. +* lo_style_link->font->size = 20. + lv_style_link_guid = lo_style_link->get_guid( ). + + " Create image map " line 2 + DO 30 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 3 + DO 28 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 4 + DO 27 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 5 + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 15 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 6 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 13 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 7 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 8 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 9 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 10 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 11 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 7 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 12 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 13 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 14 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 12 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 15 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 16 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 7 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 17 + DO 8 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 13 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 18 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 23 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 19 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 27 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 20 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 23 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 21 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 19 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 22 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 17 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 23 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 17 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 24 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 25 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 26 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color6_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 27 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color6_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 28 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color6_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 29 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 30 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 31 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 32 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 33 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 34 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 35 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 36 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 37 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 38 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 39 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 22 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 40 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 17 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 41 + DO 8 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 15 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 42 + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 43 + DO 11 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 7 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 44 + DO 13 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 45 + DO 16 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 13 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 46 + DO 18 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Angry Birds' ). + + lv_row = 1. + lv_col = 1. + + LOOP AT lt_mapper INTO ls_mapper. + lv_col_str = zcl_excel_common=>convert_column2alpha( lv_col ). + IF ls_mapper IS INITIAL. + lo_row_dimension = lo_worksheet->get_row_dimension( ip_row = lv_row ). + lo_row_dimension->set_row_height( ip_row_height = 8 ). + lv_col = 1. + lv_row = lv_row + 1. + CONTINUE. + ENDIF. + lo_worksheet->set_cell( ip_column = lv_col_str + ip_row = lv_row + ip_value = space + ip_style = ls_mapper ). + lv_col = lv_col + 1. + + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = lv_col_str ). + lo_column_dimension->set_width( ip_width = 2 ). + ENDLOOP. + + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_false ). + + lo_worksheet->set_cell( ip_column = 'AP' + ip_row = 15 + ip_value = 'Created with abap2xlsx' + ip_style = lv_style_credit_guid ). + + lo_hyperlink = zcl_excel_hyperlink=>create_external_link( iv_url = 'http://www.abap2xlsx.org' ). + lo_worksheet->set_cell( ip_column = 'AP' + ip_row = 24 + ip_value = 'http://www.abap2xlsx.org' + ip_style = lv_style_link_guid + ip_hyperlink = lo_hyperlink ). + + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'AP' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_worksheet->set_merge( ip_row = 15 ip_column_start = 'AP' ip_row_to = 22 ip_column_end = 'AR' ). + lo_worksheet->set_merge( ip_row = 24 ip_column_start = 'AP' ip_row_to = 26 ip_column_end = 'AR' ). + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + + + + + + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_CALENDAR +*& abap2xlsx Demo: Create Calendar with Pictures +*&---------------------------------------------------------------------* +*& This report creates a monthly calendar in the specified date range. +*& Each month is put on a seperate worksheet. The pictures for each +*& month can be specified in a tab delimited file called "Calendar.txt" +*& which is saved in the Export Directory. By default this is the SAP +*& Workdir. The file contains 3 fields: +*& +*& Month (with leading 0) +*& Image Filename +*& Image Description +*& URL for the Description +*& +*& The Images should be landscape JPEG's with a 3:2 ratio and min. +*& 450 pixel height. They must also be saved in the Export Directory. +*& In my tests I've discovered a limit of 20 MB in the +*& cl_gui_frontend_services=>gui_download method. So keep your images +*& smaller or change to a server export using OPEN DATASET. +*&---------------------------------------------------------------------* + +REPORT zdemo_calendar. + +TYPE-POOLS: abap. +CONSTANTS: gc_save_file_name TYPE string VALUE 'Calendar.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. +INCLUDE zdemo_calendar_classes. + +DATA: lv_workdir TYPE string. + +PARAMETERS: p_from TYPE dfrom DEFAULT '20130101', + p_to TYPE dto DEFAULT '20131231'. + +SELECTION-SCREEN BEGIN OF BLOCK orientation WITH FRAME TITLE orient. +PARAMETERS: p_portr TYPE flag RADIOBUTTON GROUP orie, + p_lands TYPE flag RADIOBUTTON GROUP orie DEFAULT 'X'. +SELECTION-SCREEN END OF BLOCK orientation. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + orient = 'Orientation'(000). + +START-OF-SELECTION. + + DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + hyperlink TYPE REF TO zcl_excel_hyperlink, + lo_drawing TYPE REF TO zcl_excel_drawing. + + DATA: lo_style_month TYPE REF TO zcl_excel_style, + lv_style_month_guid TYPE zexcel_cell_style. + DATA: lo_style_border TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + lv_style_border_guid TYPE zexcel_cell_style. + DATA: lo_style_center TYPE REF TO zcl_excel_style, + lv_style_center_guid TYPE zexcel_cell_style. + + DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + + DATA: lv_full_path TYPE string, + image_descr_path TYPE string, + lv_file_separator TYPE c. + DATA: lv_content TYPE xstring, + width TYPE i, + lv_height TYPE i, + lv_from_row TYPE zexcel_cell_row. + + DATA: month TYPE i, + month_nr TYPE fcmnr, + count TYPE i VALUE 1, + title TYPE zexcel_sheet_title, + value TYPE string, + image_path TYPE string, + date_from TYPE datum, + date_to TYPE datum, + row TYPE zexcel_cell_row, + to_row TYPE zexcel_cell_row, + to_col TYPE zexcel_cell_column_alpha, + to_col_end TYPE zexcel_cell_column_alpha, + to_col_int TYPE i. + + DATA: month_names TYPE TABLE OF t247. + FIELD-SYMBOLS: <month_name> LIKE LINE OF month_names. + + TYPES: BEGIN OF tt_datatab, + month_nr TYPE fcmnr, + filename TYPE string, + descr TYPE string, + url TYPE string, + END OF tt_datatab. + + DATA: image_descriptions TYPE TABLE OF tt_datatab. + FIELD-SYMBOLS: <img_descr> LIKE LINE OF image_descriptions. + + CONSTANTS: lv_default_file_name TYPE string VALUE 'Calendar', "#EC NOTEXT + c_from_row_portrait TYPE zexcel_cell_row VALUE 28, + c_from_row_landscape TYPE zexcel_cell_row VALUE 38, + from_col TYPE zexcel_cell_column_alpha VALUE 'C', + c_height_portrait TYPE i VALUE 450, " Image Height in Portrait Mode + c_height_landscape TYPE i VALUE 670, " Image Height in Landscape Mode + c_factor TYPE f VALUE '1.5'. " Image Ratio, default 3:2 + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name '.xlsx' INTO lv_full_path. "#EC NOTEXT + + " Read Image Names for Month and Description + CONCATENATE p_path lv_file_separator lv_default_file_name '.txt' INTO image_descr_path. "#EC NOTEXT + cl_gui_frontend_services=>gui_upload( + EXPORTING + filename = image_descr_path " Name of file + filetype = 'ASC' " File Type (ASCII, Binary) + has_field_separator = 'X' + read_by_line = 'X' " File Written Line-By-Line to the Internal Table + CHANGING + data_tab = image_descriptions " Transfer table for file contents + 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. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create Styles + " Create an underline double style + lo_style_month = lo_excel->add_new_style( ). + " lo_style_month->font->underline = abap_true. + " lo_style_month->font->underline_mode = zcl_excel_style_font=>c_underline_single. + lo_style_month->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_month->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_month->font->family = zcl_excel_style_font=>c_family_roman. + lo_style_month->font->bold = abap_true. + lo_style_month->font->size = 36. + lv_style_month_guid = lo_style_month->get_guid( ). + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + "Create style with border + lo_style_border = lo_excel->add_new_style( ). + lo_style_border->borders->allborders = lo_border_dark. + lo_style_border->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_right. + lo_style_border->alignment->vertical = zcl_excel_style_alignment=>c_vertical_top. + lv_style_border_guid = lo_style_border->get_guid( ). + "Create style alignment center + lo_style_center = lo_excel->add_new_style( ). + lo_style_center->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_center->alignment->vertical = zcl_excel_style_alignment=>c_vertical_top. + lv_style_center_guid = lo_style_center->get_guid( ). + + " Get Month Names + CALL FUNCTION 'MONTH_NAMES_GET' + TABLES + month_names = month_names. + + zcl_date_calculation=>months_between_two_dates( + EXPORTING + i_date_from = p_from + i_date_to = p_to + i_incl_to = abap_true + IMPORTING + e_month = month + ). + + date_from = p_from. + + WHILE count <= month. + IF count = 1. + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + ELSE. + lo_worksheet = lo_excel->add_new_worksheet( ). + ENDIF. + + lo_worksheet->zif_excel_sheet_properties~selected = zif_excel_sheet_properties=>c_selected. + + title = count. + value = count. + CONDENSE title. + CONDENSE value. + lo_worksheet->set_title( title ). + lo_worksheet->set_print_gridlines( abap_false ). + lo_worksheet->sheet_setup->paper_size = zcl_excel_sheet_setup=>c_papersize_a4. + lo_worksheet->sheet_setup->horizontal_centered = abap_true. + lo_worksheet->sheet_setup->vertical_centered = abap_true. + lo_col_dim = lo_worksheet->get_column_dimension( 'A' ). + lo_col_dim->set_width( '1.0' ). + lo_col_dim = lo_worksheet->get_column_dimension( 'B' ). + lo_col_dim->set_width( '2.0' ). + IF p_lands = abap_true. + lo_worksheet->sheet_setup->orientation = zcl_excel_sheet_setup=>c_orientation_landscape. + lv_height = c_height_landscape. + lv_from_row = c_from_row_landscape. + lo_worksheet->sheet_setup->margin_top = '0.10'. + lo_worksheet->sheet_setup->margin_left = '0.10'. + lo_worksheet->sheet_setup->margin_right = '0.10'. + lo_worksheet->sheet_setup->margin_bottom = '0.10'. + ELSE. + lo_col_dim = lo_worksheet->get_column_dimension( 'K' ). + lo_col_dim->set_width( '3.0' ). + lo_worksheet->sheet_setup->margin_top = '0.80'. + lo_worksheet->sheet_setup->margin_left = '0.55'. + lo_worksheet->sheet_setup->margin_right = '0.05'. + lo_worksheet->sheet_setup->margin_bottom = '0.30'. + lv_height = c_height_portrait. + lv_from_row = c_from_row_portrait. + ENDIF. + + " Add Month Name + month_nr = date_from+4(2). + IF p_portr = abap_true. + READ TABLE month_names WITH KEY mnr = month_nr ASSIGNING <month_name>. + CONCATENATE <month_name>-ltx ` ` date_from(4) INTO value. + row = lv_from_row - 2. + to_col = from_col. + ELSE. + row = lv_from_row - 1. + to_col_int = zcl_excel_common=>convert_column2int( from_col ) + 32. + to_col = zcl_excel_common=>convert_column2alpha( to_col_int ). + to_col_int = to_col_int + 1. + to_col_end = zcl_excel_common=>convert_column2alpha( to_col_int ). + CONCATENATE month_nr '/' date_from+2(2) INTO value. + to_row = row + 2. + lo_worksheet->set_merge( + EXPORTING + ip_column_start = to_col " Cell Column Start + ip_column_end = to_col_end " Cell Column End + ip_row = row " Cell Row + ip_row_to = to_row " Cell Row + ). + ENDIF. + lo_worksheet->set_cell( + EXPORTING + ip_column = to_col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = lv_style_month_guid + ). + +* to_col_int = zcl_excel_common=>convert_column2int( from_col ) + 7. +* to_col = zcl_excel_common=>convert_column2alpha( to_col_int ). +* +* lo_worksheet->set_merge( +* EXPORTING +* ip_column_start = from_col " Cell Column Start +* ip_column_end = to_col " Cell Column End +* ip_row = row " Cell Row +* ip_row_to = row " Cell Row +* ). + + " Add drawing from a XSTRING read from a file + UNASSIGN <img_descr>. + READ TABLE image_descriptions WITH KEY month_nr = month_nr ASSIGNING <img_descr>. + IF <img_descr> IS ASSIGNED. + value = <img_descr>-descr. + IF p_portr = abap_true. + row = lv_from_row - 3. + ELSE. + row = lv_from_row - 2. + ENDIF. + IF NOT <img_descr>-url IS INITIAL. + hyperlink = zcl_excel_hyperlink=>create_external_link( <img_descr>-url ). + lo_worksheet->set_cell( + EXPORTING + ip_column = from_col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_hyperlink = hyperlink + ). + ELSE. + lo_worksheet->set_cell( + EXPORTING + ip_column = from_col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ). + ENDIF. + lo_row_dim = lo_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '22.0' ). + + " In Landscape mode the row between the description and the + " dates should be not so high + IF p_lands = abap_true. + row = lv_from_row - 3. + lo_worksheet->set_cell( + EXPORTING + ip_column = from_col " Cell Column + ip_row = row " Cell Row + ip_value = ' ' " Cell Value + ). + lo_row_dim = lo_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '7.0' ). + row = lv_from_row - 1. + lo_row_dim = lo_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '5.0' ). + ENDIF. + + CONCATENATE p_path lv_file_separator <img_descr>-filename INTO image_path. + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 1 + ip_from_col = 'B' ). + + lv_content = zcl_helper=>load_image( image_path ). + width = lv_height * c_factor. + lo_drawing->set_media( ip_media = lv_content + ip_media_type = zcl_excel_drawing=>c_media_type_jpg + ip_width = width + ip_height = lv_height ). + lo_worksheet->add_drawing( lo_drawing ). + ENDIF. + + " Add Calendar +* CALL FUNCTION 'SLS_MISC_GET_LAST_DAY_OF_MONTH' +* EXPORTING +* day_in = date_from +* IMPORTING +* last_day_of_month = date_to. + date_to = date_from. + date_to+6(2) = '01'. " First of month + add 31 to date_to. " Somewhere in following month + date_to = date_to - date_to+6(2). " Last of month + IF p_portr = abap_true. + zcl_helper=>add_calendar( + EXPORTING + i_date_from = date_from + i_date_to = date_to + i_from_row = lv_from_row + i_from_col = from_col + i_day_style = lv_style_border_guid + i_cw_style = lv_style_center_guid + CHANGING + c_worksheet = lo_worksheet + ). + ELSE. + zcl_helper=>add_calendar_landscape( + EXPORTING + i_date_from = date_from + i_date_to = date_to + i_from_row = lv_from_row + i_from_col = from_col + i_day_style = lv_style_border_guid + i_cw_style = lv_style_center_guid + CHANGING + c_worksheet = lo_worksheet + ). + ENDIF. + count = count + 1. + date_from = date_to + 1. + ENDWHILE. + + lo_excel->set_active_sheet_index_by_name( '1' ). +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Include ZDEMO_CALENDAR_CLASSES +*&---------------------------------------------------------------------* + +*&---------------------------------------------------------------------* +*& Class ZCL_DATE_CALCULATION +*&---------------------------------------------------------------------* +* Text +*----------------------------------------------------------------------* +CLASS zcl_date_calculation DEFINITION. + PUBLIC SECTION. + CLASS-METHODS: months_between_two_dates + IMPORTING + i_date_from TYPE datum + i_date_to TYPE datum + i_incl_to TYPE flag + EXPORTING + e_month TYPE i. +ENDCLASS. "ZCL_DATE_CALCULATION + + +*----------------------------------------------------------------------* +* CLASS ZCL_DATE_CALCULATION IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_date_calculation IMPLEMENTATION. + METHOD months_between_two_dates. + DATA: date_to TYPE datum. + DATA: BEGIN OF datum_von, + jjjj(4) TYPE n, + mm(2) TYPE n, + tt(2) TYPE n, + END OF datum_von. + + DATA: BEGIN OF datum_bis, + jjjj(4) TYPE n, + mm(2) TYPE n, + tt(2) TYPE n, + END OF datum_bis. + + e_month = 0. + + CHECK NOT ( i_date_from IS INITIAL ) + AND NOT ( i_date_to IS INITIAL ). + + date_to = i_date_to. + IF i_incl_to = abap_true. + date_to = date_to + 1. + ENDIF. + + datum_von = i_date_from. + datum_bis = date_to. + + e_month = ( datum_bis-jjjj - datum_von-jjjj ) * 12 + + ( datum_bis-mm - datum_von-mm ). + ENDMETHOD. "MONTHS_BETWEEN_TWO_DATES +ENDCLASS. "ZCL_DATE_CALCULATION IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS zcl_date_calculation_test DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_date_calculation_test DEFINITION FOR TESTING + " DURATION SHORT + " RISK LEVEL HARMLESS + "#AU Duration Medium + "#AU Risk_Level Harmless + . + PUBLIC SECTION. + METHODS: + months_between_two_dates FOR TESTING. +ENDCLASS. "zcl_date_calculation_test DEFINITION +*----------------------------------------------------------------------* +* CLASS zcl_date_calculation_test IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_date_calculation_test IMPLEMENTATION. + METHOD months_between_two_dates. + + DATA: date_from TYPE datum VALUE '20120101', + date_to TYPE datum VALUE '20121231'. + DATA: month TYPE i. + + zcl_date_calculation=>months_between_two_dates( + EXPORTING + i_date_from = date_from + i_date_to = date_to + i_incl_to = abap_true + IMPORTING + e_month = month + ). + + cl_aunit_assert=>assert_equals( + exp = 12 " Data Object with Expected Type + act = month " Data Object with Current Value + msg = 'Calculated date is wrong' " Message in Case of Error + ). + + ENDMETHOD. "months_between_two_dates +ENDCLASS. "zcl_date_calculation_test IMPLEMENTATION +*----------------------------------------------------------------------* +* CLASS zcl_helper DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_helper DEFINITION. + PUBLIC SECTION. + CLASS-METHODS: + load_image + IMPORTING + filename TYPE string + RETURNING value(r_image) TYPE xstring, + add_calendar + IMPORTING + i_date_from TYPE datum + i_date_to TYPE datum + i_from_row TYPE zexcel_cell_row + i_from_col TYPE zexcel_cell_column_alpha + i_day_style TYPE zexcel_cell_style + i_cw_style TYPE zexcel_cell_style + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet, + add_calendar_landscape + IMPORTING + i_date_from TYPE datum + i_date_to TYPE datum + i_from_row TYPE zexcel_cell_row + i_from_col TYPE zexcel_cell_column_alpha + i_day_style TYPE zexcel_cell_style + i_cw_style TYPE zexcel_cell_style + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet, + add_a2x_footer + IMPORTING + i_from_row TYPE zexcel_cell_row + i_from_col TYPE zexcel_cell_column_alpha + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet, + add_calender_week + IMPORTING + i_date TYPE datum + i_row TYPE zexcel_cell_row + i_col TYPE zexcel_cell_column_alpha + i_style TYPE zexcel_cell_style + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet. +ENDCLASS. "zcl_helper DEFINITION + +*----------------------------------------------------------------------* +* CLASS zcl_helper IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_helper IMPLEMENTATION. + METHOD load_image. + "Load samle image + DATA: lt_bin TYPE solix_tab, + lv_len TYPE i. + + CALL METHOD cl_gui_frontend_services=>gui_upload + EXPORTING + filename = filename + filetype = 'BIN' + IMPORTING + filelength = lv_len + CHANGING + data_tab = lt_bin + 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. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_len + IMPORTING + buffer = r_image + TABLES + binary_tab = lt_bin + EXCEPTIONS + failed = 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. + ENDMETHOD. "load_image + METHOD add_calendar. + DATA: day_names TYPE TABLE OF t246. + DATA: row TYPE zexcel_cell_row, + row_max TYPE i, + col_int TYPE zexcel_cell_column, + col_max TYPE i, + from_col_int TYPE zexcel_cell_column, + col TYPE zexcel_cell_column_alpha, + lr_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lr_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi. + DATA: lv_date TYPE datum, + value TYPE string, + weekday TYPE wotnr, + weekrow TYPE wotnr VALUE 1, + day TYPE i, + width TYPE f, + height TYPE f. + DATA: hyperlink TYPE REF TO zcl_excel_hyperlink. + + FIELD-SYMBOLS: <day_name> LIKE LINE OF day_names. + + lv_date = i_date_from. + from_col_int = zcl_excel_common=>convert_column2int( i_from_col ). + " Add description for Calendar Week + c_worksheet->set_cell( + EXPORTING + ip_column = i_from_col " Cell Column + ip_row = i_from_row " Cell Row + ip_value = 'CW'(001) " Cell Value + ip_style = i_cw_style + ). + + " Add Days + CALL FUNCTION 'DAY_NAMES_GET' + TABLES + day_names = day_names. + + LOOP AT day_names ASSIGNING <day_name>. + row = i_from_row. + col_int = from_col_int + <day_name>-wotnr. + col = zcl_excel_common=>convert_column2alpha( col_int ). + value = <day_name>-langt. + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_cw_style + ). + ENDLOOP. + + WHILE lv_date <= i_date_to. + day = lv_date+6(2). + CALL FUNCTION 'FIMA_X_DAY_IN_MONTH_COMPUTE' + EXPORTING + i_datum = lv_date + IMPORTING + e_wochentag_nr = weekday. + + row = i_from_row + weekrow. + col_int = from_col_int + weekday. + col = zcl_excel_common=>convert_column2alpha( col_int ). + + value = day. + CONDENSE value. + + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_day_style " Single-Character Indicator + ). + + IF weekday = 7. + " Add Calender Week + zcl_helper=>add_calender_week( + EXPORTING + i_date = lv_date + i_row = row + i_col = i_from_col + i_style = i_cw_style + CHANGING + c_worksheet = c_worksheet + ). + weekrow = weekrow + 1. + ENDIF. + lv_date = lv_date + 1. + ENDWHILE. + " Add Calender Week + zcl_helper=>add_calender_week( + EXPORTING + i_date = lv_date + i_row = row + i_col = i_from_col + i_style = i_cw_style + CHANGING + c_worksheet = c_worksheet + ). + " Add Created with abap2xlsx + row = row + 2. + zcl_helper=>add_a2x_footer( + EXPORTING + i_from_row = row + i_from_col = i_from_col + CHANGING + c_worksheet = c_worksheet + ). + col_int = from_col_int. + col_max = from_col_int + 7. + WHILE col_int <= col_max. + col = zcl_excel_common=>convert_column2alpha( col_int ). + IF sy-index = 1. + width = '5.0'. + ELSE. + width = '11.4'. + ENDIF. + lr_col_dim = c_worksheet->get_column_dimension( col ). + lr_col_dim->set_width( width ). + col_int = col_int + 1. + ENDWHILE. + row = i_from_row + 1. + row_max = i_from_row + 6. + WHILE row <= row_max. + height = 50. + lr_row_dim = c_worksheet->get_row_dimension( row ). + lr_row_dim->set_row_height( height ). + row = row + 1. + ENDWHILE. + ENDMETHOD. "add_calendar + METHOD add_a2x_footer. + DATA: value TYPE string, + hyperlink TYPE REF TO zcl_excel_hyperlink. + + value = 'Created with abap2xlsx. Find more information at http://abap2xlsx.org.'(002). + hyperlink = zcl_excel_hyperlink=>create_external_link( 'http://abap2xlsx.org' ). "#EC NOTEXT + c_worksheet->set_cell( + EXPORTING + ip_column = i_from_col " Cell Column + ip_row = i_from_row " Cell Row + ip_value = value " Cell Value + ip_hyperlink = hyperlink + ). + + ENDMETHOD. "add_a2x_footer + METHOD add_calendar_landscape. + DATA: day_names TYPE TABLE OF t246. + + DATA: lv_date TYPE datum, + day TYPE i, + value TYPE string, + weekday TYPE wotnr. + DATA: row TYPE zexcel_cell_row, + from_col_int TYPE zexcel_cell_column, + col_int TYPE zexcel_cell_column, + col TYPE zexcel_cell_column_alpha. + DATA: lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi. + + FIELD-SYMBOLS: <day_name> LIKE LINE OF day_names. + + lv_date = i_date_from. + " Add Days + CALL FUNCTION 'DAY_NAMES_GET' + TABLES + day_names = day_names. + + WHILE lv_date <= i_date_to. + day = lv_date+6(2). + CALL FUNCTION 'FIMA_X_DAY_IN_MONTH_COMPUTE' + EXPORTING + i_datum = lv_date + IMPORTING + e_wochentag_nr = weekday. + " Day name row + row = i_from_row. + col_int = from_col_int + day + 2. + col = zcl_excel_common=>convert_column2alpha( col_int ). + READ TABLE day_names ASSIGNING <day_name> + WITH KEY wotnr = weekday. + value = <day_name>-kurzt. + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_cw_style + ). + + " Day row + row = i_from_row + 1. + value = day. + CONDENSE value. + + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_day_style " Single-Character Indicator + ). + " width + lo_col_dim = c_worksheet->get_column_dimension( col ). + lo_col_dim->set_width( '3.6' ). + + + lv_date = lv_date + 1. + ENDWHILE. + " Add ABAP2XLSX Footer + row = i_from_row + 2. + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = ' ' " Cell Value + ). + lo_row_dim = c_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '5.0' ). + row = i_from_row + 3. + zcl_helper=>add_a2x_footer( + EXPORTING + i_from_row = row + i_from_col = i_from_col + CHANGING + c_worksheet = c_worksheet + ). + + " Set with for all 31 coulumns + WHILE day < 32. + day = day + 1. + col_int = from_col_int + day + 2. + col = zcl_excel_common=>convert_column2alpha( col_int ). + " width + lo_col_dim = c_worksheet->get_column_dimension( col ). + lo_col_dim->set_width( '3.6' ). + ENDWHILE. + ENDMETHOD. "ADD_CALENDAR_LANDSCAPE + + METHOD add_calender_week. + DATA: week TYPE kweek, + week_int TYPE i, + value TYPE string. + " Add Calender Week + CALL FUNCTION 'DATE_GET_WEEK' + EXPORTING + date = i_date " Date for which the week should be calculated + IMPORTING + week = week. " Week for date (format:YYYYWW) + value = week+4(2). + week_int = value. + value = week_int. + CONDENSE value. + c_worksheet->set_cell( + EXPORTING + ip_column = i_col " Cell Column + ip_row = i_row " Cell Row + ip_value = value " Cell Value + ip_style = i_style + ). + ENDMETHOD. "add_calender_week +ENDCLASS. "zcl_helper IMPLEMENTATION + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel. + +DATA: lv_workdir TYPE string, + lv_upfile TYPE string. + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = sy-lisel ). + CONCATENATE p_path sy-lisel '01_HelloWorld.xlsx' INTO lv_upfile. + + SUBMIT zdemo_excel1 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Hello world + SUBMIT zdemo_excel2 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Styles + SUBMIT zdemo_excel3 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: iTab binding + SUBMIT zdemo_excel4 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Multi sheets, page setup and sheet properties + SUBMIT zdemo_excel5 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Conditional formatting + SUBMIT zdemo_excel6 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Formulas + SUBMIT zdemo_excel7 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Conditional formatting + SUBMIT zdemo_excel8 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Ranges + SUBMIT zdemo_excel9 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Data validation + SUBMIT zdemo_excel10 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Bind table with field catalog + " zdemo_excel11 is not added because it has a selection screen and + " you also need to have business partners maintained in transaction BP + SUBMIT zdemo_excel12 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Column size + SUBMIT zdemo_excel13 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Merge cell + SUBMIT zdemo_excel14 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Alignment + " zdemo_excel15 added at the end + SUBMIT zdemo_excel16 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Drawing + SUBMIT zdemo_excel17 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Lock sheet + SUBMIT zdemo_excel18 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Lock workbook + SUBMIT zdemo_excel19 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Set active sheet + " zdemo_excel20 is not added because it uses ALV and cannot be processed (OLE2) + SUBMIT zdemo_excel21 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Color Picker + SUBMIT zdemo_excel22 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Bind table with field catalog & sheet style + SUBMIT zdemo_excel23 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Multiple sheets with and w/o grid lines, print options + SUBMIT zdemo_excel24 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Multiple sheets with different default date formats + SUBMIT zdemo_excel25 AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Create and xlsx on Application Server (could be executed in batch mode) + " zdemo_excel26 is not added because it uses ALV and cannot be processed (Native) + SUBMIT zdemo_excel27 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Conditional Formatting + SUBMIT zdemo_excel28 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: CSV writer + " SUBMIT zdemo_excel29 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Macro enabled workbook + SUBMIT zdemo_excel30 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: ABAP Cell data types + leading blanks string + SUBMIT zdemo_excel31 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Autosize Column with different Font sizes + " zdemo_excel32 is not added because it uses ALV and cannot be processed (Native) + SUBMIT zdemo_excel33 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Table autofilter + SUBMIT zdemo_excel34 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Static Styles Chess + SUBMIT zdemo_excel35 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Static Styles + SUBMIT zdemo_excel36 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Style applied to sheet, column and single cell + SUBMIT zdemo_excel37 WITH p_upfile = lv_upfile + WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Simplest call of the reader and writer - passthrough data + SUBMIT zdemo_excel38 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Show off integration of drawings ( here using the SAP-Icons ) + SUBMIT zdemo_excel39 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Charts + SUBMIT zdemo_excel40 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Demo Printsettings + SUBMIT zdemo_excel41 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Inheritance + " + " Reader/Writer Demo must always run at the end + " to make sure all documents where created + " + SUBMIT zdemo_excel15 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT Read Excel and write it back + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel1. + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +CONSTANTS: gc_save_file_name TYPE string VALUE '01_HelloWorld.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). +* lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = sy-datum ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = sy-uzeit ). + lo_hyperlink = zcl_excel_hyperlink=>create_external_link( iv_url = 'http://www.abap2xlsx.org' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 4 ip_value = 'Click here to visit abap2xlsx homepage' ip_hyperlink = lo_hyperlink ). + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + column_dimension->set_width( ip_width = 11 ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL10 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel10. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional2 TYPE REF TO zcl_excel_style_conditional, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +DATA: lt_field_catalog TYPE zexcel_t_fieldcatalog, + ls_table_settings TYPE zexcel_s_table_settings, + ls_iconset TYPE zexcel_conditional_iconset. + +CONSTANTS: gc_save_file_name TYPE string VALUE '10_iTabFieldCatalog.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + FIELD-SYMBOLS: <fs_field_catalog> TYPE zexcel_s_fieldcatalog. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Internal table' ). + + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_5arrows. + 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'. + ls_iconset-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + "Conditional style + lo_style_conditional2 = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional2->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional2->mode_iconset = ls_iconset. + lo_style_conditional2->priority = 1. + + DATA lt_test TYPE TABLE OF sflight. + SELECT * FROM sflight INTO TABLE lt_test. "#EC CI_NOWHERE + + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_test ). + + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog>. + CASE <fs_field_catalog>-fieldname. + WHEN 'CARRID'. + <fs_field_catalog>-position = 3. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-totals_function = zcl_excel_table=>totals_function_count. + WHEN 'CONNID'. + <fs_field_catalog>-position = 4. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FLDATE'. + <fs_field_catalog>-position = 2. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'PRICE'. + <fs_field_catalog>-position = 1. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-totals_function = zcl_excel_table=>totals_function_sum. + <fs_field_catalog>-cond_style = lo_style_conditional2. + WHEN OTHERS. + <fs_field_catalog>-dynpfld = abap_false. + ENDCASE. + ENDLOOP. + + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium5. + + lo_worksheet->bind_table( ip_table = lt_test + is_table_settings = ls_table_settings + it_field_catalog = lt_field_catalog ). + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'D' ). "make date field a bit wider + column_dimension->set_width( ip_width = 13 ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL11 +*& Export Organisation and Contact Persons using ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel11. + +TYPE-POOLS: abap. + +DATA: central_search TYPE bapibus1006_central_search, + addressdata_search TYPE bapibus1006_addr_search, + others_search TYPE bapibus1006_other_data. +DATA: searchresult TYPE TABLE OF bapibus1006_bp_addr, + return TYPE TABLE OF bapiret2. +DATA: lines TYPE i. +FIELD-SYMBOLS: <searchresult_line> LIKE LINE OF searchresult. +DATA: centraldata TYPE bapibus1006_central, + centraldataperson TYPE bapibus1006_central_person, + centraldataorganization TYPE bapibus1006_central_organ. +DATA: addressdata TYPE bapibus1006_address. +DATA: relationships TYPE TABLE OF bapibus1006_relations. +FIELD-SYMBOLS: <relationship> LIKE LINE OF relationships. +DATA: relationship_centraldata TYPE bapibus1006002_central. +DATA: relationship_addresses TYPE TABLE OF bapibus1006002_addresses. +FIELD-SYMBOLS: <relationship_address> LIKE LINE OF relationship_addresses. + +DATA: lt_download TYPE TABLE OF zexcel_s_org_rel. +FIELD-SYMBOLS: <download> LIKE LINE OF lt_download. + +CONSTANTS: gc_save_file_name TYPE string VALUE '11_Export_Org_and_Contact.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +PARAMETERS: md TYPE flag RADIOBUTTON GROUP act. + +SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME TITLE text-00a. +PARAMETERS: partnerc TYPE bu_type DEFAULT 2, " Organizations + postlcod TYPE ad_pstcd1 DEFAULT '8334*', + country TYPE land1 DEFAULT 'DE', + maxsel TYPE bu_maxsel DEFAULT 100. +SELECTION-SCREEN END OF BLOCK a. + +PARAMETERS: rel TYPE flag RADIOBUTTON GROUP act DEFAULT 'X'. + +SELECTION-SCREEN BEGIN OF BLOCK b WITH FRAME TITLE text-00b. +PARAMETERS: reltyp TYPE bu_reltyp DEFAULT 'BUR011', + partner TYPE bu_partner DEFAULT '191'. +SELECTION-SCREEN END OF BLOCK b. + +START-OF-SELECTION. + IF md = abap_true. + " Read all Companies by Master Data + central_search-partnercategory = partnerc. + addressdata_search-postl_cod1 = postlcod. + addressdata_search-country = country. + others_search-maxsel = maxsel. + others_search-no_search_for_contactperson = 'X'. + + CALL FUNCTION 'BAPI_BUPA_SEARCH_2' + EXPORTING + centraldata = central_search + addressdata = addressdata_search + OTHERS = others_search + TABLES + searchresult = searchresult + return = return. + + SORT searchresult BY partner. + DELETE ADJACENT DUPLICATES FROM searchresult COMPARING partner. + ELSEIF rel = abap_true. + " Read by Relationship + SELECT but050~partner1 AS partner FROM but050 + INNER JOIN but000 ON but000~partner = but050~partner1 AND but000~type = '2' + INTO CORRESPONDING FIELDS OF TABLE searchresult + WHERE but050~partner2 = partner + AND but050~reltyp = reltyp. + ENDIF. + + DESCRIBE TABLE searchresult LINES lines. + WRITE: / 'Number of search results: ', lines. + + LOOP AT searchresult ASSIGNING <searchresult_line>. + " Read Details of Organization + CALL FUNCTION 'BAPI_BUPA_CENTRAL_GETDETAIL' + EXPORTING + businesspartner = <searchresult_line>-partner + IMPORTING + centraldataorganization = centraldataorganization. + " Read Standard Address of Organization + CALL FUNCTION 'BAPI_BUPA_ADDRESS_GETDETAIL' + EXPORTING + businesspartner = <searchresult_line>-partner + IMPORTING + addressdata = addressdata. + + " Add Organization to Download + APPEND INITIAL LINE TO lt_download ASSIGNING <download>. + " Fill Organization Partner Numbers + CALL FUNCTION 'BAPI_BUPA_GET_NUMBERS' + EXPORTING + businesspartner = <searchresult_line>-partner + IMPORTING + businesspartnerout = <download>-org_number + businesspartnerguidout = <download>-org_guid. + + MOVE-CORRESPONDING centraldataorganization TO <download>. + MOVE-CORRESPONDING addressdata TO <download>. + CLEAR: addressdata. + + " Read all Relationships + CLEAR: relationships. + CALL FUNCTION 'BAPI_BUPA_RELATIONSHIPS_GET' + EXPORTING + businesspartner = <searchresult_line>-partner + TABLES + relationships = relationships. + DELETE relationships WHERE relationshipcategory <> 'BUR001'. + LOOP AT relationships ASSIGNING <relationship>. + " Read details of Contact person + CALL FUNCTION 'BAPI_BUPA_CENTRAL_GETDETAIL' + EXPORTING + businesspartner = <relationship>-partner2 + IMPORTING + centraldata = centraldata + centraldataperson = centraldataperson. + " Read details of the Relationship + CALL FUNCTION 'BAPI_BUPR_CONTP_GETDETAIL' + EXPORTING + businesspartner = <relationship>-partner1 + contactperson = <relationship>-partner2 + IMPORTING + centraldata = relationship_centraldata. + " Read relationship address + CLEAR: relationship_addresses. + + CALL FUNCTION 'BAPI_BUPR_CONTP_ADDRESSES_GET' + EXPORTING + businesspartner = <relationship>-partner1 + contactperson = <relationship>-partner2 + TABLES + addresses = relationship_addresses. + + READ TABLE relationship_addresses + ASSIGNING <relationship_address> + WITH KEY standardaddress = 'X'. + + IF <relationship_address> IS ASSIGNED. + " Read Relationship Address + CLEAR addressdata. + CALL FUNCTION 'BAPI_BUPA_ADDRESS_GETDETAIL' + EXPORTING + businesspartner = <searchresult_line>-partner + addressguid = <relationship_address>-addressguid + IMPORTING + addressdata = addressdata. + + APPEND INITIAL LINE TO lt_download ASSIGNING <download>. + CALL FUNCTION 'BAPI_BUPA_GET_NUMBERS' + EXPORTING + businesspartner = <relationship>-partner1 + IMPORTING + businesspartnerout = <download>-org_number + businesspartnerguidout = <download>-org_guid. + + CALL FUNCTION 'BAPI_BUPA_GET_NUMBERS' + EXPORTING + businesspartner = <relationship>-partner2 + IMPORTING + businesspartnerout = <download>-contpers_number + businesspartnerguidout = <download>-contpers_guid. + + MOVE-CORRESPONDING centraldataorganization TO <download>. + MOVE-CORRESPONDING addressdata TO <download>. + MOVE-CORRESPONDING centraldataperson TO <download>. + MOVE-CORRESPONDING relationship_centraldata TO <download>. + + WRITE: / <relationship>-partner1, <relationship>-partner2. + WRITE: centraldataorganization-name1(20), centraldataorganization-name2(10). + WRITE: centraldataperson-firstname(15), centraldataperson-lastname(15). + WRITE: addressdata-street(25), addressdata-house_no, + addressdata-postl_cod1, addressdata-city(25). + ENDIF. + ENDLOOP. + + ENDLOOP. + + DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_body TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + + DATA: lv_style_body_even_guid TYPE zexcel_cell_style, + lv_style_body_green TYPE zexcel_cell_style. + + DATA: row TYPE zexcel_cell_row. + + DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + + DATA: lt_field_catalog TYPE zexcel_t_fieldcatalog, + ls_table_settings TYPE zexcel_s_table_settings. + + DATA: column TYPE zexcel_cell_column, + column_alpha TYPE zexcel_cell_column_alpha, + value TYPE zexcel_cell_value. + + FIELD-SYMBOLS: <fs_field_catalog> TYPE zexcel_s_fieldcatalog. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + "Create style with border even + lo_style_body = lo_excel->add_new_style( ). + lo_style_body->fill->fgcolor-rgb = zcl_excel_style_color=>c_yellow. + lo_style_body->borders->allborders = lo_border_dark. + lv_style_body_even_guid = lo_style_body->get_guid( ). + "Create style with border and green fill + lo_style_body = lo_excel->add_new_style( ). + lo_style_body->fill->fgcolor-rgb = zcl_excel_style_color=>c_green. + lo_style_body->borders->allborders = lo_border_dark. + lv_style_body_green = lo_style_body->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Internal table' ). + + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_download ). + + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog>. + CASE <fs_field_catalog>-fieldname. + WHEN 'ORG_NUMBER'. + <fs_field_catalog>-position = 1. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'CONTPERS_NUMBER'. + <fs_field_catalog>-position = 2. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'NAME1'. + <fs_field_catalog>-position = 3. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'NAME2'. + <fs_field_catalog>-position = 4. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'STREET'. + <fs_field_catalog>-position = 5. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'HOUSE_NO'. + <fs_field_catalog>-position = 6. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'POSTL_COD1'. + <fs_field_catalog>-position = 7. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'CITY'. + <fs_field_catalog>-position = 8. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'COUNTRYISO'. + <fs_field_catalog>-position = 9. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FIRSTNAME'. + <fs_field_catalog>-position = 10. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'LASTNAME'. + <fs_field_catalog>-position = 11. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FUNCTIONNAME'. + <fs_field_catalog>-position = 12. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'DEPARTMENTNAME'. + <fs_field_catalog>-position = 13. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'TEL1_NUMBR'. + <fs_field_catalog>-position = 14. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'TEL1_EXT'. + <fs_field_catalog>-position = 15. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FAX_NUMBER'. + <fs_field_catalog>-position = 16. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FAX_EXTENS'. + <fs_field_catalog>-position = 17. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'E_MAIL'. + <fs_field_catalog>-position = 18. + <fs_field_catalog>-dynpfld = abap_true. + WHEN OTHERS. + <fs_field_catalog>-dynpfld = abap_false. + ENDCASE. + ENDLOOP. + + ls_table_settings-top_left_column = 'A'. + ls_table_settings-top_left_row = '2'. + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium5. + + lo_worksheet->bind_table( ip_table = lt_download + is_table_settings = ls_table_settings + it_field_catalog = lt_field_catalog ). + LOOP AT lt_download ASSIGNING <download>. + row = sy-tabix + 2. + IF NOT <download>-org_number IS INITIAL + AND <download>-contpers_number IS INITIAL. + " Mark fields of Organization which can be changed green + lo_worksheet->set_cell_style( + ip_column = 'C' + ip_row = row + ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'D' + ip_row = row + ip_style = lv_style_body_green + ). +* CATCH zcx_excel. " Exceptions for ABAP2XLSX + ELSEIF NOT <download>-org_number IS INITIAL + AND NOT <download>-contpers_number IS INITIAL. + " Mark fields of Relationship which can be changed green + lo_worksheet->set_cell_style( + ip_column = 'L' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'M' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'N' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'O' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'P' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'Q' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'R' ip_row = row ip_style = lv_style_body_green + ). + ENDIF. + ENDLOOP. + " Add Fieldnames in first row and hide the row + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog> + WHERE position <> '' AND dynpfld = abap_true. + column = <fs_field_catalog>-position. + column_alpha = zcl_excel_common=>convert_column2alpha( column ). + value = <fs_field_catalog>-fieldname. + lo_worksheet->set_cell( ip_column = column_alpha + ip_row = 1 + ip_value = value + ip_style = lv_style_body_even_guid ). + ENDLOOP. + " Hide first row + row_dimension = lo_worksheet->get_row_dimension( 1 ). + row_dimension->set_visible( abap_false ). + + DATA: highest_column TYPE zexcel_cell_column, + count TYPE int4, + col_alpha TYPE zexcel_cell_column_alpha. + + highest_column = lo_worksheet->get_highest_column( ). + count = 1. + WHILE count <= highest_column. + col_alpha = zcl_excel_common=>convert_column2alpha( ip_column = count ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = col_alpha ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + count = count + 1. + ENDWHILE. +* " Set Column width manuall +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). +* column_dimension->set_width( ip_width = 11 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). +* column_dimension->set_width( ip_width = 11 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). +* column_dimension->set_width( ip_width = 35 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'E' ). +* column_dimension->set_width( ip_width = 18 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'F' ). +* column_dimension->set_width( ip_width = 5 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'G' ). +* column_dimension->set_width( ip_width = 6 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'H' ). +* column_dimension->set_width( ip_width = 12 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'I' ). +* column_dimension->set_width( ip_width = 3 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'J' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'K' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'L' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'M' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'N' ). +* column_dimension->set_width( ip_width = 12 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'O' ). +* column_dimension->set_width( ip_width = 9 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'P' ). +* column_dimension->set_width( ip_width = 12 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'Q' ). +* column_dimension->set_width( ip_width = 9 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'R' ). +* column_dimension->set_width( ip_width = 40 ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL12 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel12. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: gc_save_file_name TYPE string VALUE '12_HideSizeOutlineRowsAndColumns.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world in AutoSize column' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Hello world in a column width size 50' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 4 ip_value = 'Hello world (hidden column)' ). + lo_worksheet->set_cell( ip_column = 'F' ip_row = 2 ip_value = 'Outline column level 0' ). + lo_worksheet->set_cell( ip_column = 'G' ip_row = 2 ip_value = 'Outline column level 1' ). + lo_worksheet->set_cell( ip_column = 'H' ip_row = 2 ip_value = 'Outline column level 2' ). + lo_worksheet->set_cell( ip_column = 'I' ip_row = 2 ip_value = 'Small' ). + + + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Hello world (hidden row)' ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = 5 ip_value = 'Hello world in a row height size 20' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 9 ip_value = 'Simple outline rows 10-16 ( collapsed )' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 19 ip_value = '3 Outlines - Outlinelevel 1 is collapsed' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 19 ip_value = 'One of the two inner outlines is expanded, one collapsed' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 20 ip_value = 'Inner outline level - expanded' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 24 ip_value = 'Inner outline level - lines 25-28 are collapsed' ). + + lo_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_off. " By default is on + lo_worksheet->zif_excel_sheet_properties~summaryright = zif_excel_sheet_properties=>c_right_off. " By default is on + + " Column Settings + " Auto size + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'I' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + " Manual Width + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + column_dimension->set_width( ip_width = 50 ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'D' ). + column_dimension->set_visible( ip_visible = abap_false ). + " Implementation in the Writer is not working yet ===== TODO ===== + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'F' ). + column_dimension->set_outline_level( ip_outline_level = 0 ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'G' ). + column_dimension->set_outline_level( ip_outline_level = 1 ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'H' ). + column_dimension->set_outline_level( ip_outline_level = 2 ). + + row_dimension = lo_worksheet->get_row_dimension( ip_row = 1 ). + row_dimension->set_visible( ip_visible = abap_false ). + row_dimension = lo_worksheet->get_row_dimension( ip_row = 5 ). + row_dimension->set_row_height( ip_row_height = 20 ). +* obsolete, not intuitive. Use new method shown below +* " Implementation in the Writer is not working yet ===== TODO ===== +* row_dimension = lo_worksheet->get_row_dimension( ip_row = 6 ). +* row_dimension->set_outline_level( ip_outline_level = 0 ). +* row_dimension = lo_worksheet->get_row_dimension( ip_row = 7 ). +* row_dimension->set_outline_level( ip_outline_level = 1 ). +* row_dimension = lo_worksheet->get_row_dimension( ip_row = 8 ). +* row_dimension->set_outline_level( ip_outline_level = 2 ). + +* Define an outline rows 10-16, collapsed on startup + lo_worksheet->set_row_outline( iv_row_from = 10 + iv_row_to = 16 + iv_collapsed = abap_true ). " collapsed + +* Define an inner outline rows 21-22, expanded when outer outline becomes extended + lo_worksheet->set_row_outline( iv_row_from = 21 + iv_row_to = 22 + iv_collapsed = abap_false ). " expanded + +* Define an inner outline rows 25-28, collapsed on startup + lo_worksheet->set_row_outline( iv_row_from = 25 + iv_row_to = 28 + iv_collapsed = abap_true ). " collapsed + +* Define an outer outline rows 20-30, collapsed on startup + lo_worksheet->set_row_outline( iv_row_from = 20 + iv_row_to = 30 + iv_collapsed = abap_true ). " collapsed + +* Hint: the order you create the outlines can be arbitrary +* You can start with inner outlines or with outer outlines + +*--------------------------------------------------------------------* +* Hide columns right of column M +*--------------------------------------------------------------------* + lo_worksheet->zif_excel_sheet_properties~hide_columns_from = 'M'. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL13 +*& +*&---------------------------------------------------------------------* +*& Example by: Alvaro "Blag" Tejada Galindo. +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel13. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_style_bold_border_guid TYPE zexcel_cell_style, + lo_style_bold_border TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '13_MergedCells.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'sheet1' ). + + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + + lo_style_bold_border = lo_excel->add_new_style( ). + lo_style_bold_border->font->bold = abap_true. + lo_style_bold_border->font->italic = abap_false. + lo_style_bold_border->font->color-rgb = zcl_excel_style_color=>c_black. + lo_style_bold_border->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_bold_border->borders->allborders = lo_border_dark. + lv_style_bold_border_guid = lo_style_bold_border->get_guid( ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = 'Test' ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'B' ip_value = 'Banana' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'C' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'D' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'E' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'F' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'G' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'Apple' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'F' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'G' ip_value = '' ip_style = lv_style_bold_border_guid ). + + lo_worksheet->set_merge( ip_row = 4 ip_column_start = 'B' ip_column_end = 'G' ). + + " Test also if merge works when oher merged chells are empty + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 'Tomato' ). + lo_worksheet->set_merge( ip_row = 6 ip_column_start = 'B' ip_column_end = 'G' ). + + " Test the patch provided by Victor Alekhin to merge cells in one column + lo_worksheet->set_cell( ip_row = 8 ip_column = 'B' ip_value = 'Merge cells also over multiple rows by Victor Alekhin' ). + lo_worksheet->set_merge( ip_row = 8 ip_column_start = 'B' ip_column_end = 'G' ip_row_to = 10 ). + + " Test the patch provided by Alexander Budeyev with different column merges + lo_worksheet->set_cell( ip_row = 12 ip_column = 'B' ip_value = 'Merge cells with different merges by Alexander Budeyev' ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'B' ip_value = 'Test' ). + + lo_worksheet->set_cell( ip_row = 13 ip_column = 'D' ip_value = 'Banana' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'D' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'E' ip_value = 'Apple' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'F' ip_value = '' ip_style = lv_style_bold_border_guid ). + + " Test merge (issue) + lo_worksheet->set_merge( ip_row = 13 ip_column_start = 'B' ip_column_end = 'C' ip_row_to = 15 ). + lo_worksheet->set_merge( ip_row = 13 ip_column_start = 'D' ip_column_end = 'D' ip_row_to = 14 ). + lo_worksheet->set_merge( ip_row = 13 ip_column_start = 'E' ip_column_end = 'F' ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL14 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel14. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_center TYPE REF TO zcl_excel_style, + lo_style_right TYPE REF TO zcl_excel_style, + lo_style_left TYPE REF TO zcl_excel_style, + lo_style_general TYPE REF TO zcl_excel_style, + lo_style_bottom TYPE REF TO zcl_excel_style, + lo_style_middle TYPE REF TO zcl_excel_style, + lo_style_top TYPE REF TO zcl_excel_style, + lo_style_justify TYPE REF TO zcl_excel_style, + lo_style_mixed TYPE REF TO zcl_excel_style, + lo_style_mixed_wrap TYPE REF TO zcl_excel_style, + lo_style_rotated TYPE REF TO zcl_excel_style, + lo_style_shrink TYPE REF TO zcl_excel_style, + lo_style_indent TYPE REF TO zcl_excel_style, + lv_style_center_guid TYPE zexcel_cell_style, + lv_style_right_guid TYPE zexcel_cell_style, + lv_style_left_guid TYPE zexcel_cell_style, + lv_style_general_guid TYPE zexcel_cell_style, + lv_style_bottom_guid TYPE zexcel_cell_style, + lv_style_middle_guid TYPE zexcel_cell_style, + lv_style_top_guid TYPE zexcel_cell_style, + lv_style_justify_guid TYPE zexcel_cell_style, + lv_style_mixed_guid TYPE zexcel_cell_style, + lv_style_mixed_wrap_guid TYPE zexcel_cell_style, + lv_style_rotated_guid TYPE zexcel_cell_style, + lv_style_shrink_guid TYPE zexcel_cell_style, + lv_style_indent_guid TYPE zexcel_cell_style. + +DATA: lo_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + +CONSTANTS: gc_save_file_name TYPE string VALUE '14_Alignment.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'sheet1' ). + + "Center + lo_style_center = lo_excel->add_new_style( ). + lo_style_center->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lv_style_center_guid = lo_style_center->get_guid( ). + "Right + lo_style_right = lo_excel->add_new_style( ). + lo_style_right->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_right. + lv_style_right_guid = lo_style_right->get_guid( ). + "Left + lo_style_left = lo_excel->add_new_style( ). + lo_style_left->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_left. + lv_style_left_guid = lo_style_left->get_guid( ). + "General + lo_style_general = lo_excel->add_new_style( ). + lo_style_general->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_general. + lv_style_general_guid = lo_style_general->get_guid( ). + "Bottom + lo_style_bottom = lo_excel->add_new_style( ). + lo_style_bottom->alignment->vertical = zcl_excel_style_alignment=>c_vertical_bottom. + lv_style_bottom_guid = lo_style_bottom->get_guid( ). + "Middle + lo_style_middle = lo_excel->add_new_style( ). + lo_style_middle->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lv_style_middle_guid = lo_style_middle->get_guid( ). + "Top + lo_style_top = lo_excel->add_new_style( ). + lo_style_top->alignment->vertical = zcl_excel_style_alignment=>c_vertical_top. + lv_style_top_guid = lo_style_top->get_guid( ). + "Justify + lo_style_justify = lo_excel->add_new_style( ). + lo_style_justify->alignment->vertical = zcl_excel_style_alignment=>c_vertical_justify. + lv_style_justify_guid = lo_style_justify->get_guid( ). + + "Shrink + lo_style_shrink = lo_excel->add_new_style( ). + lo_style_shrink->alignment->shrinktofit = abap_true. + lv_style_shrink_guid = lo_style_shrink->get_guid( ). + + "Indent + lo_style_indent = lo_excel->add_new_style( ). + lo_style_indent->alignment->indent = 5. + lv_style_indent_guid = lo_style_indent->get_guid( ). + + "Middle / Centered / Wrap + lo_style_mixed_wrap = lo_excel->add_new_style( ). + lo_style_mixed_wrap->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_mixed_wrap->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lo_style_mixed_wrap->alignment->wraptext = abap_true. + lv_style_mixed_wrap_guid = lo_style_mixed_wrap->get_guid( ). + + "Middle / Centered / Wrap + lo_style_mixed = lo_excel->add_new_style( ). + lo_style_mixed->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_mixed->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lv_style_mixed_guid = lo_style_mixed->get_guid( ). + + "Center + 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° + lv_style_rotated_guid = lo_style_rotated->get_guid( ). + + + " Set row size for first 7 rows to 40 + DO 7 TIMES. + lo_row_dimension = lo_worksheet->get_row_dimension( sy-index ). + lo_row_dimension->set_row_height( 40 ). + ENDDO. + + "Horizontal alignment + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'Centered Text' ip_style = lv_style_center_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'B' ip_value = 'Right Text' ip_style = lv_style_right_guid ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 'Left Text' ip_style = lv_style_left_guid ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'B' ip_value = 'General Text' ip_style = lv_style_general_guid ). + + " Shrink & indent + lo_worksheet->set_cell( ip_row = 4 ip_column = 'F' ip_value = 'Text shrinked' ip_style = lv_style_shrink_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'F' ip_value = 'Text indented' ip_style = lv_style_indent_guid ). + + "Vertical alignment + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'Bottom Text' ip_style = lv_style_bottom_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 'Middle Text' ip_style = lv_style_middle_guid ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'D' ip_value = 'Top Text' ip_style = lv_style_top_guid ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'D' ip_value = 'Justify Text' ip_style = lv_style_justify_guid ). + + " Wrapped + lo_worksheet->set_cell( ip_row = 10 ip_column = 'B' + ip_value = 'This is a wrapped text centered in the middle' + ip_style = lv_style_mixed_wrap_guid ). + + " Rotated + lo_worksheet->set_cell( ip_row = 10 ip_column = 'D' + ip_value = 'This is a centered text rotated by -75°' + ip_style = lv_style_rotated_guid ). + + " forced line break + DATA: lv_value TYPE string. + CONCATENATE 'This is a wrapped text centered in the middle' cl_abap_char_utilities=>cr_lf + 'and a manuall line break.' INTO lv_value. + lo_worksheet->set_cell( ip_row = 11 ip_column = 'B' + ip_value = lv_value + ip_style = lv_style_mixed_guid ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL15 +*& +*&---------------------------------------------------------------------* +*& 2010-10-30, Gregor Wolf: +*& Added the functionality to ouput the read table content +*& 2011-12-19, Shahrin Shahrulzaman: +*& Added the functionality to have multiple input and output files +*&---------------------------------------------------------------------* + +REPORT zdemo_excel15. + +TYPE-POOLS: abap. + +TYPES: + BEGIN OF t_demo_excel15, + input TYPE string, + END OF t_demo_excel15. + +DATA: excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + reader TYPE REF TO zif_excel_reader. + +DATA: ex TYPE REF TO zcx_excel, + msg TYPE string. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_workdir TYPE string, + output_file_path TYPE string, + input_file_path TYPE string, + lv_file_separator TYPE c. + +DATA: worksheet TYPE REF TO zcl_excel_worksheet, + highest_column TYPE zexcel_cell_column, + highest_row TYPE int4, + column TYPE zexcel_cell_column VALUE 1, + col_str TYPE zexcel_cell_column_alpha, + row TYPE int4 VALUE 1, + value TYPE zexcel_cell_value. + +DATA: + lt_files TYPE TABLE OF t_demo_excel15. +FIELD-SYMBOLS: <wa_files> TYPE t_demo_excel15. + +PARAMETERS: p_path TYPE zexcel_export_dir, + p_noout TYPE xfeld DEFAULT abap_true. + + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '01_HelloWorld.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '02_Styles.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '03_iTab.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '04_Sheets.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '08_Range.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '13_MergedCells.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '31_AutosizeWithDifferentFontSizes.xlsx'. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + + LOOP AT lt_files ASSIGNING <wa_files>. + CONCATENATE p_path lv_file_separator <wa_files>-input INTO input_file_path. + CONCATENATE p_path lv_file_separator '15_' <wa_files>-input INTO output_file_path. + REPLACE '.xlsx' IN output_file_path WITH 'FromReader.xlsx'. + + TRY. + CREATE OBJECT reader TYPE zcl_excel_reader_2007. + excel = reader->load_file( input_file_path ). + + IF p_noout EQ abap_false. + worksheet = excel->get_active_worksheet( ). + highest_column = worksheet->get_highest_column( ). + highest_row = worksheet->get_highest_row( ). + + WRITE: 'Highest column: ', highest_column, 'Highest row: ', highest_row. + WRITE: /. + + WHILE row <= highest_row. + WHILE column <= highest_column. + col_str = zcl_excel_common=>convert_column2alpha( column ). + worksheet->get_cell( + EXPORTING + ip_column = col_str + ip_row = row + IMPORTING + ep_value = value + ). + WRITE: value. + column = column + 1. + ENDWHILE. + WRITE: /. + column = 1. + row = row + 1. + ENDWHILE. + ENDIF. + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = output_file_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + CATCH zcx_excel INTO ex. " Exceptions for ABAP2XLSX + msg = ex->get_text( ). + WRITE: / msg. + ENDTRY. + ENDLOOP. + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL16 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel16. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_drawing TYPE REF TO zcl_excel_drawing. + + +DATA: ls_io TYPE skwf_io. + +CONSTANTS: gc_save_file_name TYPE string VALUE '16_Drawings.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_objid TYPE sdok_docid DEFAULT '456694429165174BE10000000A1550C0', " Question mark in standard Web Dynpro WDT_QUIZ + p_class TYPE sdok_class DEFAULT 'M_IMAGE_P', + pobjtype TYPE skwf_ioty DEFAULT 'P'. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + "Load samle image + DATA: lt_bin TYPE solix_tab, + lv_len TYPE i, + lv_content TYPE xstring, + ls_key TYPE wwwdatatab. + + CALL METHOD cl_gui_frontend_services=>gui_upload + EXPORTING + filename = 'c:\Program Files\SAP\FrontEnd\SAPgui\wwi\graphics\W_bio.bmp' + filetype = 'BIN' + IMPORTING + filelength = lv_len + CHANGING + data_tab = lt_bin + 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. +* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno +* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_len + IMPORTING + buffer = lv_content + TABLES + binary_tab = lt_bin + EXCEPTIONS + failed = 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. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Image from web repository (SMW0)' ). + + " create global drawing, set position and media from web repository + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 3 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'SAPLOGO.GIF'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 166 + ip_height = 75 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " another drawing from a XSTRING read from a file + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Image from a file (c:\Program Files\SAP\FrontEnd\SAPgui\wwi\graphics\W_bio.bmp)' ). + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 9 + ip_from_col = 'B' ). + lo_drawing->set_media( ip_media = lv_content + ip_media_type = zcl_excel_drawing=>c_media_type_bmp + ip_width = 83 + ip_height = 160 ). + + lo_worksheet->add_drawing( lo_drawing ). + + ls_io-objid = p_objid. + ls_io-class = p_class. + ls_io-objtype = pobjtype. + IF ls_io IS NOT INITIAL. + " another drawing from a XSTRING read from a file + lo_worksheet->set_cell( ip_column = 'B' ip_row = 18 ip_value = 'Mime repository (by default Question mark in standard Web Dynpro WDT_QUIZ)' ). + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 19 + ip_from_col = 'B' ). + lo_drawing->set_media_mime( ip_io = ls_io + ip_width = 126 + ip_height = 145 ). + + lo_worksheet->add_drawing( lo_drawing ). + ENDIF. + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL26 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel29. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_excel_reader TYPE REF TO zif_excel_reader. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_filename TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +PARAMETERS: p_path TYPE zexcel_export_dir OBLIGATORY. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + + DATA: lt_filetable TYPE filetable, + lv_rc TYPE i. + + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + + CALL METHOD cl_gui_frontend_services=>file_open_dialog + EXPORTING + window_title = 'Select Macro-Enabled Workbook template' + default_extension = '*.xlsm' + file_filter = 'Excel Macro-Enabled Workbook (*.xlsm)|*.xlsm' + initial_directory = lv_workdir + CHANGING + file_table = lt_filetable + rc = lv_rc + EXCEPTIONS + file_open_dialog_failed = 1 + cntl_error = 2 + error_no_gui = 3 + not_supported_by_gui = 4 + OTHERS = 5. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + READ TABLE lt_filetable INTO lv_filename INDEX 1. + p_path = lv_filename. + +START-OF-SELECTION. + + lv_full_path = p_path. + + CREATE OBJECT lo_excel_reader TYPE zcl_excel_reader_xlsm. + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_xlsm. + lo_excel = lo_excel_reader->load_file( lv_full_path ). + lv_file = lo_excel_writer->write_file( lo_excel ). + REPLACE '.xlsm' IN lv_full_path WITH 'FromReader.xlsm'. + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL28 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel28. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_file_name TYPE string, + lv_file_path TYPE string, + lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE '28_HelloWorld.csv'. + +PARAMETERS: p_path TYPE string. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = p_path + CHANGING selected_folder = p_path ). + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = sy-datum ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = sy-uzeit ). + + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_width( 11 ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the second sheet' ). + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_csv. + zcl_excel_writer_csv=>set_delimiter( ip_value = cl_abap_char_utilities=>horizontal_tab ). + zcl_excel_writer_csv=>set_enclosure( ip_value = '''' ). + zcl_excel_writer_csv=>set_endofline( ip_value = cl_abap_char_utilities=>cr_lf ). + + zcl_excel_writer_csv=>set_active_sheet_index( i_active_worksheet = 2 ). +* zcl_excel_writer_csv=>set_active_sheet_index_by_name( I_WORKSHEET_NAME = 'Sheet2' ). + + lv_file = lo_excel_writer->write_file( lo_excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + REPLACE FIRST OCCURRENCE OF '.csv' IN lv_full_path WITH '_Sheet2.csv'. + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + +* zcl_excel_writer_csv=>set_active_sheet_index( i_active_worksheet = 2 ). + zcl_excel_writer_csv=>set_active_sheet_index_by_name( I_WORKSHEET_NAME = 'Sheet1' ). + lv_file = lo_excel_writer->write_file( lo_excel ). + REPLACE FIRST OCCURRENCE OF '_Sheet2.csv' IN lv_full_path WITH '_Sheet1.csv'. + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL27 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel27. + +CONSTANTS: c_fish TYPE string VALUE 'Fish'. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_style_1 TYPE REF TO zcl_excel_style, + lo_style_2 TYPE REF TO zcl_excel_style, + lv_style_1_guid TYPE zexcel_cell_style, + lv_style_2_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis. + + +DATA: lv_title TYPE zexcel_sheet_title. + +CONSTANTS: gc_save_file_name TYPE string VALUE '27_ConditionalFormatting.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + lo_style_1 = lo_excel->add_new_style( ). + lo_style_1->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_1->fill->bgcolor-rgb = zcl_excel_style_color=>c_green. + lv_style_1_guid = lo_style_1->get_guid( ). + + lo_style_2 = lo_excel->add_new_style( ). + lo_style_2->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_2->fill->bgcolor-rgb = zcl_excel_style_color=>c_red. + lv_style_2_guid = lo_style_2->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lv_title = 'Data Validation'. + lo_worksheet->set_title( lv_title ). + " Set values for dropdown + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = c_fish ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 'Anchovy' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 'Carp' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 'Catfish' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 'Cod' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 'Eel' ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'A' ip_value = 'Haddock' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_fish. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 9 ). + + " 1st validation + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_fish. + lo_data_validation->cell_row = 2. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 2 ip_column = 'C' ip_value = 'Select a value' ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '"Anchovy"'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_1_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 1. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 2 + ip_stop_column = 'C' + ip_stop_row = 2 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '"Carp"'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_2_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 2 + ip_stop_column = 'C' + ip_stop_row = 2 ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *--------------------------------------------------------------------* +* REPORT ZDEMO_EXCEL26 +* Demo for method zcl_excel_worksheet-bind_object: +* export data from ALV (CL_GUI_ALV_GRID) object or cl_salv_table object +* to Excel. +*--------------------------------------------------------------------* +report zdemo_excel26. + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +class lcl_handle_events definition. + public section. + methods: + on_user_command for event added_function of cl_salv_events + importing e_salv_function. +endclass. "lcl_handle_events DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +class lcl_handle_events implementation. + method on_user_command. + perform user_command." using e_salv_function text-i08. + endmethod. "on_user_command +endclass. "lcl_handle_events IMPLEMENTATION + +*--------------------------------------------------------------------* +* DATA DECLARATION +*--------------------------------------------------------------------* + +data: lo_excel type ref to zcl_excel, + lo_worksheet type ref to zcl_excel_worksheet, + lo_salv type ref to cl_salv_table, + gr_events type ref to lcl_handle_events, + lr_events type ref to cl_salv_events_table, + gt_sbook type table of sbook. + +data: l_path type string, " local dir + lv_workdir type string, + lv_file_separator type c. + +constants: + lv_default_file_name type string value '26_Bind_ALV.xlsx'. +*--------------------------------------------------------------------* +*START-OF-SELECTION +*--------------------------------------------------------------------* + +start-of-selection. + +* get data +* ------------------------------------------ + + select * + into table gt_sbook[] + from sbook "#EC CI_NOWHERE + up to 10 rows. + +* Display ALV +* ------------------------------------------ + + try. + cl_salv_table=>factory( + exporting + list_display = abap_false + importing + r_salv_table = lo_salv + changing + t_table = gt_sbook[] ). + catch cx_salv_msg . + endtry. + + try. + lo_salv->set_screen_status( + exporting + report = sy-repid + pfstatus = 'ALV_STATUS' + set_functions = lo_salv->c_functions_all ). + catch cx_salv_msg . + endtry. + + lr_events = lo_salv->get_event( ). + create object gr_events. + set handler gr_events->on_user_command for lr_events. + + lo_salv->display( ). + + +*&---------------------------------------------------------------------* +*& Form USER_COMMAND +*&---------------------------------------------------------------------* +* ALV user command +*--------------------------------------------------------------------* +form user_command . + if sy-ucomm = 'EXCEL'. + +* get save file path + cl_gui_frontend_services=>get_sapgui_workdir( changing sapworkdir = l_path ). + cl_gui_cfw=>flush( ). + cl_gui_frontend_services=>directory_browse( + exporting initial_folder = l_path + changing selected_folder = l_path ). + + if l_path is initial. + cl_gui_frontend_services=>get_sapgui_workdir( + changing sapworkdir = lv_workdir ). + l_path = lv_workdir. + endif. + + cl_gui_frontend_services=>get_file_separator( + changing file_separator = lv_file_separator ). + + concatenate l_path lv_file_separator lv_default_file_name + into l_path. + +* export file to save file path + perform export_to_excel. + + endif. +endform. " USER_COMMAND + +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +form export_to_excel. + data: lo_converter type ref to zcl_excel_converter. +* create zcl_excel_worksheet object + + create object lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + +* write to excel using method Bin_object + try. + lo_worksheet->bind_alv( + io_alv = lo_salv + it_table = gt_sbook + i_top = 2 + i_left = 1 + ). + catch zcx_excel . + endtry. + + perform write_file. + +endform. "EXPORT_TO_EXCEL +*&---------------------------------------------------------------------* +*& Form WRITE_FILE +*&---------------------------------------------------------------------* +* text +*----------------------------------------------------------------------* +* --> p1 text +* <-- p2 text +*----------------------------------------------------------------------* +form write_file . + data: lt_file type solix_tab, + l_bytecount type i, + l_file type xstring. + + data: lo_excel_writer type ref to zif_excel_writer. + + data: ls_seoclass type seoclass. + + create object lo_excel_writer type zcl_excel_writer_2007. + l_file = lo_excel_writer->write_file( lo_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 = l_file + receiving + et_solix = lt_file. + + l_bytecount = xstrlen( l_file ). + else. + " Convert to binary + call function 'SCMS_XSTRING_TO_BINARY' + exporting + buffer = l_file + importing + output_length = l_bytecount + tables + binary_tab = lt_file. + endif. + + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_path + filetype = 'BIN' + changing data_tab = lt_file ). + +endform. " WRITE_FILE + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL25 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel25. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_exception TYPE REF TO cx_root. + +DATA: lv_file TYPE xstring. + +CONSTANTS: lv_file_name TYPE string VALUE '25_HelloWorld.xlsx'. +DATA: lv_default_file_name TYPE string. +DATA: lv_error TYPE string. + +CALL FUNCTION 'FILE_GET_NAME_USING_PATH' + EXPORTING + logical_path = 'LOCAL_TEMPORARY_FILES' " Logical path' + file_name = lv_file_name " File name + IMPORTING + file_name_with_path = lv_default_file_name. " File name with path +" Creates active sheet +CREATE OBJECT lo_excel. + +" Get active sheet +lo_worksheet = lo_excel->get_active_worksheet( ). +lo_worksheet->set_title( ip_title = 'Sheet1' ). +lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + +CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. +lv_file = lo_excel_writer->write_file( lo_excel ). + +TRY. + OPEN DATASET lv_default_file_name FOR OUTPUT IN BINARY MODE. + TRANSFER lv_file TO lv_default_file_name. + CLOSE DATASET lv_default_file_name. + CATCH cx_root INTO lo_exception. + lv_error = lo_exception->get_text( ). + MESSAGE lv_error TYPE 'I'. +ENDTRY. + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL23 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel24. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +DATA: lv_value TYPE string. + +CONSTANTS: gc_save_file_name TYPE string VALUE '24_Sheets_with_different_default_date_formats.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Default Date Format' ). + " Insert current date + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Current Date:' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 4 ip_value = sy-datum ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet2!A1' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 6 ip_value = 'This is a link to the second sheet' ip_hyperlink = lo_hyperlink ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + + " Second sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_default_excel_date_format( zcl_excel_style_number_format=>c_format_date_yyyymmdd ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Date Format set to YYYYMMDD' ). + " Insert current date + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Current Date:' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 4 ip_value = sy-datum ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet3!B2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 6 ip_value = 'This is link to the third sheet' ip_hyperlink = lo_hyperlink ). + + " Third sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + " TODO: It seems that the zcl_excel_style_number_format=>c_format_date_yyyymmddslash + " does not produce a valid output + lo_worksheet->set_default_excel_date_format( zcl_excel_style_number_format=>c_format_date_yyyymmddslash ). + lo_worksheet->set_title( ip_title = 'Sheet3' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Date Format set to YYYY/MM/DD' ). + " Insert current date + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Current Date:' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 4 ip_value = sy-datum ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet4!B2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 6 ip_value = 'This is link to the 4th sheet' ip_hyperlink = lo_hyperlink ). + + " 4th sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + " Illustrate the Problem caused by: + " Excel 2000 incorrectly assumes that the year 1900 is a leap year. + " http://support.microsoft.com/kb/214326/en-us + lo_worksheet->set_title( ip_title = 'Sheet4' ). + " Loop from Start Date to the Max Date current data in daily steps + CONSTANTS: lv_max type d VALUE '19000302'. + + DATA: lv_date TYPE d VALUE '19000226', + lv_row TYPE i. + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'Formated date' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Integer value for this date' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 3 ip_value = 'Date as string' ). + + lv_row = 4. + WHILE lv_date < lv_max. + lo_worksheet->set_cell( ip_column = 'B' ip_row = lv_row ip_value = lv_date ). + lv_value = zcl_excel_common=>date_to_excel_string( lv_date ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = lv_row ip_value = lv_value ). + lv_value = lv_date. + lo_worksheet->set_cell( ip_column = 'D' ip_row = lv_row ip_value = lv_value ). + lv_date = lv_date + 1. + lv_row = lv_row + 1. + ENDWHILE. + + lv_row = lv_row + 1. + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet1!B2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = lv_row ip_value = 'This is link to the first sheet' ip_hyperlink = lo_hyperlink ). + + lo_excel->set_active_sheet_index_by_name( 'Sheet1' ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL23 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel23. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '23_Sheets_with_and_without_grid_lines.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the first sheet with grid lines and print centered horizontal & vertical' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_true ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet2!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is a link to the second sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 150. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_NORMAL = 150. + + lo_worksheet->sheet_setup->vertical_centered = abap_true. + lo_worksheet->sheet_setup->horizontal_centered = abap_true. + + " Second sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the second sheet with grid lines in display and print' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_true ). + lo_worksheet->set_print_gridlines( i_print_gridlines = abap_true ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet3!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to the third sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 160. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_PAGELAYOUTVIEW = 200. + + " Third sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet3' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the third sheet without grid lines in display and print' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_false ). + lo_worksheet->set_print_gridlines( i_print_gridlines = abap_false ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet4!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to the fourth sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 170. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_SHEETLAYOUTVIEW = 150. + + " Fourth sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet4' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the fourth sheet with grid lines and print centered ONLY horizontal' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_true ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet1!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to the first sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 150. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_NORMAL = 150. + +" lo_worksheet->sheet_setup->vertical_centered = abap_true. + lo_worksheet->sheet_setup->horizontal_centered = abap_true. + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL17 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel17. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_protection TYPE REF TO zcl_excel_style, + lv_style_protection_guid TYPE zexcel_cell_style, + lo_style TYPE REF TO zcl_excel_style, + lv_style TYPE zexcel_cell_style. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '17_SheetProtection.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_pwd TYPE zexcel_aes_password LOWER CASE DEFAULT 'secret'. + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. +* lo_worksheet->zif_excel_sheet_protection~password = 'DAA7'. "it is the encoded word "secret" + lo_worksheet->zif_excel_sheet_protection~password = zcl_excel_common=>encrypt_password( p_pwd ). + lo_worksheet->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_active. + " First style to unlock a cell + lo_style_protection = lo_excel->add_new_style( ). + lo_style_protection->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. + lv_style_protection_guid = lo_style_protection->get_guid( ). + " Another style which should not affect the unlock style + lo_style = lo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = 'FFCC3333'. + lv_style = lo_style->get_guid( ). + lo_worksheet->set_cell( ip_row = 3 ip_column = 'C' ip_value = 'This cell is locked locked and has the second formating' ip_style = lv_style ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 'This cell is locked as all the others empty cell' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'This cell is locked as all the others empty cell' ). + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL18 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel18. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_style_protection_guid TYPE zexcel_cell_style. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '18_BookProtection.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_excel->zif_excel_book_protection~protected = zif_excel_book_protection=>c_protected. + lo_excel->zif_excel_book_protection~lockrevision = zif_excel_book_protection=>c_locked. + lo_excel->zif_excel_book_protection~lockstructure = zif_excel_book_protection=>c_locked. + lo_excel->zif_excel_book_protection~lockwindows = zif_excel_book_protection=>c_locked. + + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL19 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel19. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '19_SetActiveSheet.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_noout TYPE xfeld DEFAULT abap_true. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " First Worksheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'First' ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'This is Sheet 1' ). + + " Second Worksheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Second' ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'This is Sheet 2' ). + + " Third Worksheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Third' ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'This is Sheet 3' ). + + IF p_noout EQ abap_false. + " lo_excel->set_active_sheet_index_by_name( data_sheet_name ). + DATA: active_sheet_index TYPE zexcel_active_worksheet. + active_sheet_index = lo_excel->get_active_sheet_index( ). + WRITE: 'Sheet Index before: ', active_sheet_index. + ENDIF. + lo_excel->set_active_sheet_index( '2' ). + IF p_noout EQ abap_false. + active_sheet_index = lo_excel->get_active_sheet_index( ). + WRITE: 'Sheet Index after: ', active_sheet_index. + ENDIF. + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL2 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel2. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_bold TYPE REF TO zcl_excel_style, + lo_style_underline TYPE REF TO zcl_excel_style, + lo_style_filled TYPE REF TO zcl_excel_style, + lo_style_border TYPE REF TO zcl_excel_style, + lo_style_button TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + lo_border_light TYPE REF TO zcl_excel_style_border. + +DATA: lv_style_bold_guid TYPE zexcel_cell_style, + lv_style_underline_guid TYPE zexcel_cell_style, + lv_style_filled_guid TYPE zexcel_cell_style, + lv_style_filled_green_guid TYPE zexcel_cell_style, + lv_style_border_guid TYPE zexcel_cell_style, + lv_style_button_guid TYPE zexcel_cell_style, + lv_style_filled_turquoise_guid TYPE zexcel_cell_style, + lv_style_gr_cornerlb_guid TYPE zexcel_cell_style, + lv_style_gr_cornerlt_guid TYPE zexcel_cell_style, + lv_style_gr_cornerrb_guid TYPE zexcel_cell_style, + lv_style_gr_cornerrt_guid TYPE zexcel_cell_style, + lv_style_gr_horizontal90_guid TYPE zexcel_cell_style, + lv_style_gr_horizontal270_guid TYPE zexcel_cell_style, + lv_style_gr_horizontalb_guid TYPE zexcel_cell_style, + lv_style_gr_vertical_guid TYPE zexcel_cell_style, + lv_style_gr_vertical2_guid TYPE zexcel_cell_style, + lv_style_gr_fromcenter_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal45_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal45b_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal135_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal135b_guid TYPE zexcel_cell_style . + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. +DATA: lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi. + +CONSTANTS: gc_save_file_name TYPE string VALUE '02_Styles.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + CREATE OBJECT lo_border_light. + lo_border_light->border_color-rgb = zcl_excel_style_color=>c_gray. + lo_border_light->border_style = zcl_excel_style_border=>c_border_thin. + " Create a bold / italic style + lo_style_bold = lo_excel->add_new_style( ). + lo_style_bold->font->bold = abap_true. + lo_style_bold->font->italic = abap_true. + lo_style_bold->font->name = zcl_excel_style_font=>c_name_arial. + lo_style_bold->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_bold->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_bold_guid = lo_style_bold->get_guid( ). + " Create an underline double style + lo_style_underline = lo_excel->add_new_style( ). + lo_style_underline->font->underline = abap_true. + lo_style_underline->font->underline_mode = zcl_excel_style_font=>c_underline_double. + lo_style_underline->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_underline->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_underline->font->family = zcl_excel_style_font=>c_family_roman. + lv_style_underline_guid = lo_style_underline->get_guid( ). + " Create filled style yellow + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-theme = zcl_excel_style_color=>c_theme_accent6. + lv_style_filled_guid = lo_style_filled->get_guid( ). + " Create border with button effects + lo_style_button = lo_excel->add_new_style( ). + lo_style_button->borders->right = lo_border_dark. + lo_style_button->borders->down = lo_border_dark. + lo_style_button->borders->left = lo_border_light. + lo_style_button->borders->top = lo_border_light. + lv_style_button_guid = lo_style_button->get_guid( ). + "Create style with border + lo_style_border = lo_excel->add_new_style( ). + lo_style_border->borders->allborders = lo_border_dark. + lo_style_border->borders->diagonal = lo_border_dark. + lo_style_border->borders->diagonal_mode = zcl_excel_style_borders=>c_diagonal_both. + lv_style_border_guid = lo_style_border->get_guid( ). + " Create filled style green + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_green. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_filled_green_guid = lo_style_filled->get_guid( ). + + " Create filled with gradients + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerlb. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerlb_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerlt. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerlt_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerrb. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerrb_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerrt. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerrt_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_horizontal90. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_horizontal90_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_horizontal270. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_horizontal270_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_horizontalb. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_horizontalb_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_vertical. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_vertical_guid = lo_style_filled->get_guid( ). + + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_vertical. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_vertical2_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_fromcenter. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_fromcenter_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal45. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal45_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal45b. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal45b_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal135. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal135_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal135b. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal135b_guid = lo_style_filled->get_guid( ). + + + + " Create filled style turquoise using legacy excel ver <= 2003 palette. (https://code.sdn.sap.com/spaces/abap2xlsx/tickets/92) + lo_style_filled = lo_excel->add_new_style( ). + lo_excel->legacy_palette->set_color( "replace built-in color from palette with out custom RGB turquoise + ip_index = 16 + ip_color = '0040E0D0' ). + + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-indexed = 16. + lv_style_filled_turquoise_guid = lo_style_filled->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Styles' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Bold text' ip_style = lv_style_bold_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 4 ip_value = 'Underlined text' ip_style = lv_style_underline_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 6 ip_value = 'Borders' ip_style = lv_style_border_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 7 ip_value = 'I''m not a button :)' ip_style = lv_style_button_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 9 ip_value = 'Modified color for Excel 2003' ip_style = lv_style_filled_turquoise_guid ). + " Fill the cell and apply one style + lo_worksheet->set_cell( ip_column = 'B' ip_row = 6 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + " Change the style + lo_worksheet->set_cell_style( ip_column = 'B' ip_row = 6 ip_style = lv_style_filled_green_guid ). + " Add Style to an empty cell to test Fix for Issue + "#44 Exception ZCX_EXCEL thrown when style is set for an empty cell + " https://code.sdn.sap.com/spaces/abap2xlsx/tickets/44-exception-zcx_excel-thrown-when-style-is-set-for-an-empty-cell + lo_worksheet->set_cell_style( ip_column = 'E' ip_row = 6 ip_style = lv_style_filled_green_guid ). + + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_style = lv_style_gr_cornerlb_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerlb ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 10 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 11 ip_style = lv_style_gr_cornerlt_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerlt ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 11 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 12 ip_style = lv_style_gr_cornerrb_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerrb ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 12 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 13 ip_style = lv_style_gr_cornerrt_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerrt ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 13 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 14 ip_style = lv_style_gr_horizontal90_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_horizontal90 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 14 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 15 ip_style = lv_style_gr_horizontal270_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_horizontal270 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 15 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 16 ip_style = lv_style_gr_horizontalb_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_horizontalb ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 16 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 17 ip_style = lv_style_gr_vertical_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_vertical ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 17 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 18 ip_style = lv_style_gr_vertical2_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_vertical ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 18 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 19 ip_style = lv_style_gr_fromcenter_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_fromcenter ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 19 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 20 ip_style = lv_style_gr_diagonal45_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal45 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 20 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 21 ip_style = lv_style_gr_diagonal45b_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal45b ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 21 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 22 ip_style = lv_style_gr_diagonal135_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal135 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 22 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 23 ip_style = lv_style_gr_diagonal135b_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal135b ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 23 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + + + +* CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. +* lv_file = lo_excel_writer->write_file( lo_excel ). +* +* " Convert to binary +* CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' +* EXPORTING +* buffer = lv_file +* IMPORTING +* output_length = lv_bytecount +* TABLES +* binary_tab = lt_file_tab. +** " This method is only available on AS ABAP > 6.40 +** lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +** lv_bytecount = xstrlen( lv_file ). +* +* " Save the file +* cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount +* filename = lv_full_path +* filetype = 'BIN' +* CHANGING data_tab = lt_file_tab ). + + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL22 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel22. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style TYPE REF TO zcl_excel_style, + lo_style_date TYPE REF TO zcl_excel_style, + lo_style_editable TYPE REF TO zcl_excel_style, + lo_data_validation TYPE REF TO zcl_excel_data_validation. + +DATA: lt_field_catalog TYPE zexcel_t_fieldcatalog, + ls_table_settings TYPE zexcel_s_table_settings, + ls_table_settings_out TYPE zexcel_s_table_settings. + +DATA: lv_style_guid TYPE zexcel_cell_style. + +DATA: lv_row TYPE char10. + +FIELD-SYMBOLS: <fs_field_catalog> TYPE zexcel_s_fieldcatalog. + +CONSTANTS: gc_save_file_name TYPE string VALUE '22_itab_fieldcatalog.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'PN_MASSIVE'). + + DATA lt_test TYPE TABLE OF sflight. + SELECT * FROM sflight INTO TABLE lt_test. "#EC CI_NOWHERE + + " sheet style (white background) + lo_style = lo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = zcl_excel_style_color=>c_white. + lv_style_guid = lo_style->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->zif_excel_sheet_properties~set_style( lv_style_guid ). + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_protection~password = zcl_excel_common=>encrypt_password( 'test' ). + lo_worksheet->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_active. + + " Create cell style for display only fields + lo_style = lo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = zcl_excel_style_color=>c_gray. + lo_style->number_format->format_code = zcl_excel_style_number_format=>c_format_text. + + " Create cell style for display only date field + lo_style_date = lo_excel->add_new_style( ). + lo_style_date->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_date->fill->fgcolor-rgb = zcl_excel_style_color=>c_gray. + lo_style_date->number_format->format_code = zcl_excel_style_number_format=>c_format_date_ddmmyyyy. + + " Create cell style for editable fields + lo_style_editable = lo_excel->add_new_style( ). + lo_style_editable->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. + + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_test ). + + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog>. + CASE <fs_field_catalog>-fieldname. + WHEN 'CARRID'. + <fs_field_catalog>-position = 3. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style->get_guid( ). + WHEN 'CONNID'. + <fs_field_catalog>-position = 1. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style->get_guid( ). + WHEN 'FLDATE'. + <fs_field_catalog>-position = 2. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style_date->get_guid( ). + WHEN 'PRICE'. + <fs_field_catalog>-position = 4. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style_editable->get_guid( ). + <fs_field_catalog>-totals_function = zcl_excel_table=>totals_function_sum. + WHEN OTHERS. + <fs_field_catalog>-dynpfld = abap_false. + ENDCASE. + ENDLOOP. + + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ls_table_settings-show_row_stripes = abap_true. + + lo_worksheet->bind_table( EXPORTING + ip_table = lt_test + it_field_catalog = lt_field_catalog + is_table_settings = ls_table_settings + IMPORTING + es_table_settings = ls_table_settings_out ). + + lo_worksheet->freeze_panes( ip_num_rows = 3 ). "freeze column headers when scrolling + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_custom. + lv_row = ls_table_settings_out-top_left_row. + CONDENSE lv_row. + CONCATENATE 'ISNUMBER(' ls_table_settings_out-top_left_column lv_row ')' INTO lo_data_validation->formula1. + lo_data_validation->cell_row = ls_table_settings_out-top_left_row. + lo_data_validation->cell_column = ls_table_settings_out-top_left_column. + lo_data_validation->cell_row_to = ls_table_settings_out-bottom_right_row. + lo_data_validation->cell_column_to = ls_table_settings_out-bottom_right_column. + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL21 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel21. + +TYPES: + BEGIN OF t_color_style, + color TYPE zexcel_style_color_argb, + style TYPE zexcel_cell_style, + END OF t_color_style. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_filled TYPE REF TO zcl_excel_style. + +DATA: color_styles TYPE TABLE OF t_color_style. + +FIELD-SYMBOLS: <color_style> LIKE LINE OF color_styles. + +CONSTANTS: max TYPE i VALUE 255, + step TYPE i VALUE 51. + +DATA: red TYPE i, + green TYPE i, + blue TYPE i, + red_hex(1) TYPE x, + green_hex(1) TYPE x, + blue_hex(1) TYPE x, + red_str TYPE string, + green_str TYPE string, + blue_str TYPE string. + +DATA: color TYPE zexcel_style_color_argb, + tint TYPE zexcel_style_color_tint. + +DATA: row TYPE i, + row_tmp TYPE i, + column TYPE zexcel_cell_column VALUE 1, + col_str TYPE zexcel_cell_column_alpha. + +CONSTANTS: gc_save_file_name TYPE string VALUE '21_BackgroundColorPicker.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + WHILE red <= max. + green = 0. + WHILE green <= max. + blue = 0. + WHILE blue <= max. + red_hex = red. + red_str = red_hex. + green_hex = green. + green_str = green_hex. + blue_hex = blue. + blue_str = blue_hex. + " Create filled + CONCATENATE 'FF' red_str green_str blue_str INTO color. + APPEND INITIAL LINE TO color_styles ASSIGNING <color_style>. + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-rgb = color. + <color_style>-color = color. + <color_style>-style = lo_style_filled->get_guid( ). + blue = blue + step. + ENDWHILE. + green = green + step. + ENDWHILE. + red = red + step. + ENDWHILE. + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Color Picker' ). + LOOP AT color_styles ASSIGNING <color_style>. + row_tmp = ( max / step + 1 ) * 3. + IF row = row_tmp. + row = 0. + column = column + 1. + ENDIF. + row = row + 1. + col_str = zcl_excel_common=>convert_column2alpha( column ). + + " Fill the cell and apply one style + lo_worksheet->set_cell( ip_column = col_str + ip_row = row + ip_value = <color_style>-color + ip_style = <color_style>-style ). + ENDLOOP. + + row = row + 2. + tint = '-0.5'. + DO 10 TIMES. + column = 1. + DO 10 TIMES. + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-theme = sy-index - 1. + lo_style_filled->fill->fgcolor-tint = tint. + <color_style>-style = lo_style_filled->get_guid( ). + col_str = zcl_excel_common=>convert_column2alpha( column ). + lo_worksheet->set_cell_style( ip_column = col_str + ip_row = row + ip_style = <color_style>-style ). + + ADD 1 TO column. + ENDDO. + ADD '0.1' TO tint. + ADD 1 TO row. + ENDDO. + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *--------------------------------------------------------------------* +* REPORT ZDEMO_EXCEL20 +* Demo for method zcl_excel_worksheet-bind_alv: +* export data from ALV (CL_GUI_ALV_GRID) object to excel +*--------------------------------------------------------------------* +REPORT zdemo_excel20. + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events DEFINITION. + PUBLIC SECTION. + METHODS: + on_user_command FOR EVENT added_function OF cl_salv_events + IMPORTING e_salv_function. +ENDCLASS. "lcl_handle_events DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events IMPLEMENTATION. + METHOD on_user_command. + PERFORM user_command." using e_salv_function text-i08. + ENDMETHOD. "on_user_command +ENDCLASS. "lcl_handle_events IMPLEMENTATION + +*--------------------------------------------------------------------* +* DATA DECLARATION +*--------------------------------------------------------------------* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_alv TYPE REF TO cl_gui_alv_grid, + lo_salv TYPE REF TO cl_salv_table, + gr_events TYPE REF TO lcl_handle_events, + lr_events TYPE REF TO cl_salv_events_table, + gt_sbook TYPE TABLE OF sbook, + gt_listheader TYPE slis_t_listheader, + wa_listheader LIKE LINE OF gt_listheader. + +DATA: l_path TYPE string, " local dir + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: + lv_default_file_name TYPE string VALUE '20_BindAlv.xlsx'. +*--------------------------------------------------------------------* +*START-OF-SELECTION +*--------------------------------------------------------------------* + +START-OF-SELECTION. + +* get data +* ------------------------------------------ + + SELECT * + INTO TABLE gt_sbook[] + FROM sbook "#EC CI_NOWHERE + UP TO 10 ROWS. + +* Display ALV +* ------------------------------------------ + + TRY. + cl_salv_table=>factory( + EXPORTING + list_display = abap_false + IMPORTING + r_salv_table = lo_salv + CHANGING + t_table = gt_sbook[] ). + CATCH cx_salv_msg . + ENDTRY. + + TRY. + lo_salv->set_screen_status( + EXPORTING + report = sy-repid + pfstatus = 'ALV_STATUS' + set_functions = lo_salv->c_functions_all ). + CATCH cx_salv_msg . + ENDTRY. + + lr_events = lo_salv->get_event( ). + CREATE OBJECT gr_events. + SET HANDLER gr_events->on_user_command FOR lr_events. + + lo_salv->display( ). + + +*&---------------------------------------------------------------------* +*& Form USER_COMMAND +*&---------------------------------------------------------------------* +* ALV user command +*--------------------------------------------------------------------* +FORM user_command . + IF sy-ucomm = 'EXCEL'. + +* get save file path + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = l_path ). + cl_gui_cfw=>flush( ). + cl_gui_frontend_services=>directory_browse( + EXPORTING initial_folder = l_path + CHANGING selected_folder = l_path ). + + IF l_path IS INITIAL. + cl_gui_frontend_services=>get_sapgui_workdir( + CHANGING sapworkdir = lv_workdir ). + l_path = lv_workdir. + ENDIF. + + cl_gui_frontend_services=>get_file_separator( + CHANGING file_separator = lv_file_separator ). + + CONCATENATE l_path lv_file_separator lv_default_file_name + INTO l_path. + +* export file to save file path + + PERFORM export_to_excel. + + ENDIF. +ENDFORM. " USER_COMMAND + +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +FORM export_to_excel. + +* create zcl_excel_worksheet object + + CREATE OBJECT lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + +* get ALV object from screen + + CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR' + IMPORTING + e_grid = lo_alv. + +* build list header + + wa_listheader-typ = 'H'. + wa_listheader-info = sy-title. + APPEND wa_listheader TO gt_listheader. + + wa_listheader-typ = 'S'. + wa_listheader-info = 'Created by: ABAP2XLSX Group'. + APPEND wa_listheader TO gt_listheader. + + wa_listheader-typ = 'A'. + wa_listheader-info = + 'Project hosting at https://cw.sdn.sap.com/cw/groups/abap2xlsx'. + APPEND wa_listheader TO gt_listheader. + +* write to excel using method Bin_ALV + + lo_worksheet->bind_alv_ole2( + EXPORTING +* I_DOCUMENT_URL = SPACE " excel template +* I_XLS = 'X' " create in xls format? + i_save_path = l_path + io_alv = lo_alv + it_listheader = gt_listheader + i_top = 2 + i_left = 1 +* I_COLUMNS_HEADER = 'X' +* I_COLUMNS_AUTOFIT = 'X' +* I_FORMAT_COL_HEADER = +* I_FORMAT_SUBTOTAL = +* I_FORMAT_TOTAL = + EXCEPTIONS + miss_guide = 1 + ex_transfer_kkblo_error = 2 + fatal_error = 3 + inv_data_range = 4 + dim_mismatch_vkey = 5 + dim_mismatch_sema = 6 + error_in_sema = 7 + OTHERS = 8 + ). + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + +ENDFORM. "EXPORT_TO_EXCEL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/ABAP2XLSX_V_7_0_4.nugg.zip b/build/ABAP2XLSX_V_7_0_4.nugg.zip new file mode 100644 index 0000000000000000000000000000000000000000..d9d4b422e2c728387f89d1a023c1b9404b8d836e GIT binary patch literal 324753 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 knKKTTbk_PxVC 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

mY&ZZr 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%0DYHcf5p=uzx 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 z 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%0A`39wri_;{x#DYG7HM%UKz)LQjnTw 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 Y{zp~hVPOAz2;}E&^GPx9p+D3A0~+lEy#N3J literal 0 HcmV?d00001 diff --git a/build/ABAP2XLSX_V_7_0_3.nugg b/build/old_releases/ABAP2XLSX_V_7_0_3.nugg similarity index 100% rename from build/ABAP2XLSX_V_7_0_3.nugg rename to build/old_releases/ABAP2XLSX_V_7_0_3.nugg diff --git a/build/ABAP2XLSX_V_7_0_3.nugg.zip b/build/old_releases/ABAP2XLSX_V_7_0_3.nugg.zip similarity index 100% rename from build/ABAP2XLSX_V_7_0_3.nugg.zip rename to build/old_releases/ABAP2XLSX_V_7_0_3.nugg.zip diff --git a/build/ABAP2XLSX_V_7_0_3.zip b/build/old_releases/ABAP2XLSX_V_7_0_3.zip similarity index 100% rename from build/ABAP2XLSX_V_7_0_3.zip rename to build/old_releases/ABAP2XLSX_V_7_0_3.zip