From 30ac9277f2c243f4f4bebe73176b1266f3121f33 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 5 Mar 2014 13:53:30 -0600 Subject: [PATCH] New daily build --- build/ABAP2XLSX_V_7_0.nugg | 37882 ++++++++++++++++++++++++++++++++++- build/ABAP2XLSX_V_7_0.zip | Bin 288183 -> 291459 bytes 2 files changed, 37881 insertions(+), 1 deletion(-) diff --git a/build/ABAP2XLSX_V_7_0.nugg b/build/ABAP2XLSX_V_7_0.nugg index bd5bb89..220d7db 100644 --- a/build/ABAP2XLSX_V_7_0.nugg +++ b/build/ABAP2XLSX_V_7_0.nugg @@ -1,2 +1,37882 @@ - + + + + + + + + + + + + + + + + + + + + + *"* 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. + *"* 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 + + + + + + + + + IXML + + + + + + + + method ZIF_EXCEL_READER~CAN_READ_FILE. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-07 +* - ... +* changes: nothing done in code +* but started discussion about killing this method +*--------------------------------------------------------------------* +* For now always Unknown + r_readable = abap_undefined. + endmethod. + + + method ZIF_EXCEL_READER~LOAD. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Map Document Properties to ZCL_EXCEL +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-07 +* - ... +* changes: renaming variables to naming conventions +* removing unused variables +* aligning code +* adding comments to explain what we are trying to achieve +* commenting on problems/future enhancements/todos we already know of or should decide upon +* adding me-> where possible +*--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office +* - Stefan Schmöcker, 2012-11-07 +* changes: passing new optional input parameter to private attribute +*--------------------------------------------------------------------* + + 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 +*--------------------------------------------------------------------* + CREATE OBJECT r_excel. + +*--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office + me->zif_excel_reader~gv_use_alternate_zip = i_use_alternate_zip. +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* §2 Get file in folderstructure +*--------------------------------------------------------------------* + me->excel2007 = i_excel2007. + lo_rels = me->get_ixml_from_zip_archive( '_rels/.rels' ). + +*--------------------------------------------------------------------* +* §3 Cycle through the Relationship Tags and use the ones we need +*--------------------------------------------------------------------* + lo_node ?= lo_rels->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. + + WHEN lcv_core_properties. + " 2do§1 Map Document Properties to ZCL_EXCEL + + WHEN lcv_office_document. + me->load_workbook( iv_workbook_full_filename = ls_relationship-target + io_excel = r_excel ). + + WHEN OTHERS. + + ENDCASE. + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + + + endmethod. + + + METHOD zif_excel_reader~load_file. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 decision whether to load from frontend or backend +* current behavior ( autodecide ) should be default +* add optional parameter to allow user to choose +* to load from backend even when online +* 2do§2 loosen typing of i_filename to CLIKE +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-05 +* - ... +* changes: renaming variables to naming conventions +* renaming variables to indicate what they are used for +* adding comments to explain what we are trying to achieve +* message made to support multilinguality +* aligning code +* commenting on problems/future enhancements/todos we already know of or should decide upon +* adding issue # that has initiated the change - date provided to allow cleaning of code after a certain period +* explicit declaration of type of table instead of implicit declaration +* added errorhandling for open dataset +*--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office +* - Stefan Schmöcker, 2012-11-07 +* changes: passing new optional input parameter to private attribute +*--------------------------------------------------------------------* + + DATA: lv_excel_data TYPE xstring. + +* issue#234 - error reading xlsx written by libre office + me->zif_excel_reader~gv_use_alternate_zip = i_use_alternate_zip. + + IF i_from_applserver = abap_true. + lv_excel_data = me->read_from_applserver( i_filename = i_filename ). + ELSE. + lv_excel_data = me->read_from_local_file( i_filename = i_filename ). + ENDIF. + +*--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office + r_excel = me->zif_excel_reader~load( i_excel2007 = lv_excel_data + i_use_alternate_zip = i_use_alternate_zip ). +*--------------------------------------------------------------------* + + 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_FROM_ZIP_ARCHIVE. +*--------------------------------------------------------------------* +* 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 +* changed message passed with exception +* message made to support multilinguality +*--------------------------------------------------------------------**--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office +* - Stefan Schmöcker, 2012-11-07 +* changes: copying coding and using ALTERNATE_ZIP in ELSE-Branch +*--------------------------------------------------------------------* + + DATA: lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + + +*--------------------------------------------------------------------* +* An xlsx-file is basically a zip-archive +* From this zip-archive we need to extract one file in binary form +*--------------------------------------------------------------------* + IF me->zif_excel_reader~gv_use_alternate_zip IS INITIAL. "+#234 +*--------------------------------------------------------------------* +* Setup ABAP zip-class with binary exceldata if not done already +*--------------------------------------------------------------------* + IF me->zip IS NOT BOUND. + CREATE OBJECT me->zip. + zip->load( EXPORTING + zip = me->excel2007 + 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. + ENDIF. + +*--------------------------------------------------------------------* +* Extract requested filename from archive if possible +*--------------------------------------------------------------------* + zip->get( EXPORTING + name = i_filename + IMPORTING + content = r_content " Contents + 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. +*--------------------------------------------------------------------* +* issue#234 - begin of insertion +*--------------------------------------------------------------------* + ELSE. +*--------------------------------------------------------------------* +* Setup alternate ABAP zip-class with binary exceldata if not done already +* May become obsolete if SAP fixes standard CL_ABAP_ZIP +*--------------------------------------------------------------------* + IF me->alternate_zip IS NOT BOUND. + CREATE OBJECT me->alternate_zip TYPE (zif_excel_reader~gv_use_alternate_zip). + TRY. + CALL METHOD me->alternate_zip->('LOAD') + EXPORTING + zip = me->excel2007 + 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. + ENDIF. + +*--------------------------------------------------------------------* +* Extract requested filename from archive if possible +*--------------------------------------------------------------------* + TRY. + CALL METHOD me->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. + ENDIF. +*--------------------------------------------------------------------* +* issue#234 - end of insertion +*--------------------------------------------------------------------* + + endmethod. + + + + + + + method GET_IXML_FROM_ZIP_ARCHIVE. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Add comment what is being achieved here +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (done) 2012-11-07 +* - ... +* changes: renaming variables to naming conventions +* removing unnecessary type-pool +* aligning code +*--------------------------------------------------------------------* + + 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. + + +*--------------------------------------------------------------------* +* 2do§1 ???? Something happens here ??? +*--------------------------------------------------------------------* + 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_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_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'. + " 2do§1 Support gradientFill + + 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' ). + 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 ). + + 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) +*--------------------------------------------------------------------* + 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_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. + + 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_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_pagemargins_elem TYPE REF TO if_ixml_element, + ls_pagemargins TYPE lty_page_margins, + 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, + + 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 + me->load_worksheet_drawing( ip_path = lv_path + io_worksheet = io_worksheet ). + + WHEN lc_rel_printer. + " Read Printer settings + + 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. +* Fix 207 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 +* IF column-hidden = lc_xml_attr_true OR +* column-hidden = lc_xml_attr_true_int. +* index = column-min. +* WHILE index <= column-max. +* column_alpha = zcl_excel_common=>convert_column2alpha( index ). +* column_dimension = io_worksheet->get_column_dimension( column_alpha ). +* column_dimension->set_visible( abap_false ). +* ADD 1 TO index. +* ENDWHILE. +* 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 + lo_ixml_pagemargins_elem = lo_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 = ls_pagemargins-bottom. + io_worksheet->sheet_setup->margin_footer = ls_pagemargins-footer. + io_worksheet->sheet_setup->margin_header = ls_pagemargins-header. + io_worksheet->sheet_setup->margin_left = ls_pagemargins-left. + io_worksheet->sheet_setup->margin_right = ls_pagemargins-right. + io_worksheet->sheet_setup->margin_top = ls_pagemargins-top. + ENDIF. + + " 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 + + 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 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 CONSTRUCTOR. + endmethod. + + + + method IS_SECURITY_ENABLED. + IF lockrevision EQ abap_true OR lockstructure EQ abap_true OR lockwindows EQ abap_true. + ep_security_enabled = abap_true. + ENDIF. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + orientation = me->c_orientation_default. + +* default margins + margin_bottom = '0.75'. + margin_footer = '0.3'. + margin_header = '0.3'. + margin_left = '0.7'. + margin_right = '0.7'. + margin_top = '0.75'. + +* clear page settings + CLEAR: black_and_white, + cell_comments, + copies, + draft, + errors, + first_page_number, + fit_to_page, + fit_to_height, + fit_to_width, + horizontal_dpi, + orientation, + page_order, + paper_height, + paper_size, + paper_width, + scale, + use_first_page_num, + use_printer_defaults, + vertical_dpi. + endmethod. + + + + + + + method GET_HEADER_FOOTER_STRING. +* ---------------------------------------------------------------------- + DATA: lc_marker_left(2) TYPE c VALUE '&L' + , lc_marker_right(2) TYPE c VALUE '&R' + , lc_marker_center(2) TYPE c VALUE '&C' + , lv_value TYPE string + . +* ---------------------------------------------------------------------- + IF ep_odd_header IS SUPPLIED. + + IF me->odd_header-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_odd_header. + ENDIF. + + IF me->odd_header-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'CENTER' ). + CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_header. + ENDIF. + + IF me->odd_header-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'RIGHT' ). + CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_header. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_odd_footer IS SUPPLIED. + + IF me->odd_footer-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_odd_footer. + ENDIF. + + IF me->odd_footer-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'CENTER' ). + CONCATENATE ep_odd_footer lc_marker_center lv_value INTO ep_odd_footer. + ENDIF. + + IF me->odd_footer-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'RIGHT' ). + CONCATENATE ep_odd_footer lc_marker_right lv_value INTO ep_odd_footer. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_even_header IS SUPPLIED. + + IF me->even_header-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_even_header. + ENDIF. + + IF me->even_header-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'CENTER' ). + CONCATENATE ep_even_header lc_marker_center lv_value INTO ep_even_header. + ENDIF. + + IF me->even_header-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'RIGHT' ). + CONCATENATE ep_even_header lc_marker_right lv_value INTO ep_even_header. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_even_footer IS SUPPLIED. + + IF me->even_footer-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_even_footer. + ENDIF. + + IF me->even_footer-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'CENTER' ). + CONCATENATE ep_even_footer lc_marker_center lv_value INTO ep_even_footer. + ENDIF. + + IF me->even_footer-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'RIGHT' ). + CONCATENATE ep_even_footer lc_marker_right lv_value INTO ep_even_footer. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + endmethod. + + + + + + method PROCESS_HEADER_FOOTER. + +* ---------------------------------------------------------------------- +* Only Basic font/text formatting possible: +* Bold (yes / no), Font Type, Font Size + + DATA: lv_fname(12) TYPE c + , lv_string TYPE string + . + + FIELD-SYMBOLS: <lv_value> TYPE string + , <ls_font> TYPE zexcel_s_style_font + . + +* ---------------------------------------------------------------------- + CONCATENATE ip_side '_VALUE' INTO lv_fname. + ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <lv_value>. + + CONCATENATE ip_side '_FONT' INTO lv_fname. + ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <ls_font>. + + IF <ls_font> IS ASSIGNED AND <lv_value> IS ASSIGNED. + + IF <ls_font>-name IS NOT INITIAL. + CONCATENATE '&"' <ls_font>-name ',' INTO rv_processed_string. + ELSE. + rv_processed_string = '&"-,'. + ENDIF. + + IF <ls_font>-bold = abap_true. + CONCATENATE rv_processed_string 'Bold"' INTO rv_processed_string. + ELSE. + CONCATENATE rv_processed_string 'Standard"' INTO rv_processed_string. + ENDIF. + + IF <ls_font>-size IS NOT INITIAL. + lv_string = <ls_font>-size. + CONCATENATE rv_processed_string '&' lv_string INTO rv_processed_string. + ENDIF. + + CONCATENATE rv_processed_string <lv_value> INTO rv_processed_string. + + ENDIF. +* ---------------------------------------------------------------------- + + endmethod. + + + + + + + method SET_HEADER_FOOTER. + +* Only Basic font/text formatting possible: +* Bold (yes / no), Font Type, Font Size +* +* usefull placeholders, which can be used in header/footer value strings +* '&P' - page number +* '&N' - total number of pages +* '&D' - Date +* '&T' - Time +* '&F' - File Name +* '&Z' - Path +* '&A' - Sheet name +* new line via class constant CL_ABAP_CHAR_UTILITIES=>newline +* +* Example Value String 'page &P of &N' +* +* DO NOT USE &L , &C or &R which automatically created as position markers + + me->odd_header = ip_odd_header. + me->odd_footer = ip_odd_footer. + me->even_header = ip_even_header. + me->even_footer = ip_even_footer. + + IF me->even_header IS NOT INITIAL OR me->even_footer IS NOT INITIAL. + me->diff_oddeven_headerfooter = abap_true. + ENDIF. + + + endmethod. + + + + + + + + + + method SET_PAGE_MARGINS. + DATA: lv_coef TYPE f, + lv_unit TYPE string. + + lv_unit = ip_unit. + TRANSLATE lv_unit TO UPPER CASE. + + CASE lv_unit. + WHEN 'IN'. lv_coef = 1. + WHEN 'CM'. lv_coef = '0.393700787'. + WHEN 'MM'. lv_coef = '0.0393700787'. + ENDCASE. + + IF ip_bottom IS SUPPLIED. margin_bottom = lv_coef * ip_bottom. ENDIF. + IF ip_footer IS SUPPLIED. margin_footer = lv_coef * ip_footer. ENDIF. + IF ip_header IS SUPPLIED. margin_header = lv_coef * ip_header. ENDIF. + IF ip_left IS SUPPLIED. margin_left = lv_coef * ip_left. ENDIF. + IF ip_right IS SUPPLIED. margin_right = lv_coef * ip_right. ENDIF. + IF ip_top IS SUPPLIED. margin_top = lv_coef * ip_top. ENDIF. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + method CONSTRUCTOR. + + + CREATE OBJECT font. + CREATE OBJECT fill. + CREATE OBJECT borders. + CREATE OBJECT alignment. + CREATE OBJECT number_format. + CREATE OBJECT protection. + +* Start of insertion # issue 139 - Dateretention of cellstyles + IF ip_guid IS NOT INITIAL. + me->guid = ip_guid. + ELSE. +* End of insertion # issue 139 - Dateretention of cellstyles + CALL FUNCTION 'GUID_CREATE' + IMPORTING + ev_guid_16 = me->guid. +* Start of insertion # issue 139 - Dateretention of cellstyles + ENDIF. +* End of insertion # issue 139 - Dateretention of cellstyles + + endmethod. + + + + method GET_GUID. + + + ep_guid = me->guid. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + + + styles->add( ip_style ). + endmethod. + + + method CLEAR. + + + styles->clear( ). + endmethod. + + + method CONSTRUCTOR. + + + CREATE OBJECT styles. + endmethod. + + + + + method GET. + + + eo_style ?= styles->if_object_collection~get( ip_index ). + endmethod. + + + + method GET_ITERATOR. + + + eo_iterator ?= styles->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + + + is_empty = styles->if_object_collection~is_empty( ). + endmethod. + + + + + method REGISTER_NEW_STYLE. + + + me->add( io_style ). + ep_style_code = me->size( ) - 1. "style count starts from 0 + endmethod. + + + + method REMOVE. + + + styles->remove( ip_style ). + endmethod. + + + + method SIZE. + + + ep_size = styles->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + styles_conditional->add( ip_style_conditional ). + endmethod. + + + method CLEAR. + styles_conditional->clear( ). + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT styles_conditional. + + endmethod. + + + + + method GET. + DATA lv_index TYPE i. + lv_index = ip_index. + eo_style_conditional ?= styles_conditional->if_object_collection~get( lv_index ). + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= styles_conditional->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = styles_conditional->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + styles_conditional->remove( ip_style_conditional ). + endmethod. + + + + method SIZE. + ep_size = styles_conditional->if_object_collection~size( ). + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + horizontal = me->c_horizontal_general. + vertical = me->c_vertical_bottom. + wrapText = abap_false. + shrinkToFit = abap_false. + endmethod. + + + + method GET_STRUCTURE. + + es_alignment-horizontal = me->horizontal. + es_alignment-vertical = me->vertical. + es_alignment-textrotation = me->textrotation. + es_alignment-wraptext = me->wraptext. + es_alignment-shrinktofit = me->shrinktofit. + es_alignment-indent = me->indent. + + endmethod. + + + + *"* 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 CONSTRUCTOR. + endmethod. + + + + method GET_STRUCTURE. +*initialize colors to 'not set' + es_fill-left_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-left_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-right_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-right_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-top_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-top_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-bottom_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-bottom_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-diagonal_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-diagonal_color-theme = zcl_excel_style_color=>c_theme_not_set. + +* Check if all borders is set otherwise check single border + IF me->allborders IS BOUND. + es_fill-left_color = me->allborders->border_color. + es_fill-left_style = me->allborders->border_style. + es_fill-right_color = me->allborders->border_color. + es_fill-right_style = me->allborders->border_style. + es_fill-top_color = me->allborders->border_color. + es_fill-top_style = me->allborders->border_style. + es_fill-bottom_color = me->allborders->border_color. + es_fill-bottom_style = me->allborders->border_style. + ELSE. + IF me->left IS BOUND. + es_fill-left_color = me->left->border_color. + es_fill-left_style = me->left->border_style. + ENDIF. + IF me->right IS BOUND. + es_fill-right_color = me->right->border_color. + es_fill-right_style = me->right->border_style. + ENDIF. + IF me->top IS BOUND. + es_fill-top_color = me->top->border_color. + es_fill-top_style = me->top->border_style. + ENDIF. + IF me->down IS BOUND. + es_fill-bottom_color = me->down->border_color. + es_fill-bottom_style = me->down->border_style. + ENDIF. + ENDIF. + +* Check if diagonal is set + IF me->diagonal IS BOUND. + es_fill-diagonal_color = me->diagonal->border_color. + es_fill-diagonal_style = me->diagonal->border_style. + CASE me->diagonal_mode. + WHEN 1. + es_fill-diagonalup = 1. + es_fill-diagonaldown = 0. + WHEN 2. + es_fill-diagonalup = 0. + es_fill-diagonaldown = 1. + WHEN 3. + es_fill-diagonalup = 1. + es_fill-diagonaldown = 1. + WHEN OTHERS. + es_fill-diagonalup = 0. + es_fill-diagonaldown = 0. + ENDCASE. + ENDIF. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + + endmethod. + + + + + + + method CREATE_NEW_ARGB. + + + CONCATENATE zcl_excel_style_color=>c_alpha ip_red ip_green ip_blu INTO ep_color_argb. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + DATA: ls_iconset TYPE zexcel_conditional_iconset. + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights. + ls_iconset-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo1_value = '0'. + ls_iconset-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo2_value = '20'. + ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo3_value = '40'. + ls_iconset-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo4_value = '60'. + ls_iconset-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo5_value = '80'. + + + me->rule = zcl_excel_style_conditional=>c_rule_none. +* me->iconset->operator = zcl_excel_style_conditional=>c_operator_none. + me->mode_iconset = ls_iconset. + me->priority = 1. + +* inizialize dimension range + me->stop_cell-cell_row = 1. + me->stop_cell-cell_column = 1. + me->start_cell-cell_row = 1. + me->start_cell-cell_column = 1. + endmethod. + + + + method GET_DIMENSION_RANGE. + IF stop_cell EQ start_cell. "only one cell + ep_dimension_range = start_cell-cell_coords. + ELSE. + CONCATENATE start_cell-cell_coords ':' stop_cell-cell_coords INTO ep_dimension_range. + ENDIF. + endmethod. + + + + + + + method SET_RANGE. + DATA: lv_column TYPE zexcel_cell_column, + lv_row_alpha TYPE string. + + lv_column = zcl_excel_common=>convert_column2int( ip_stop_column ). + stop_cell-cell_row = 1. + stop_cell-cell_column = lv_column. + lv_row_alpha = ip_stop_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_stop_column lv_row_alpha INTO stop_cell-cell_coords. + + lv_column = zcl_excel_common=>convert_column2int( ip_start_column ). + start_cell-cell_row = 1. + start_cell-cell_column = lv_column. + lv_row_alpha = ip_start_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_start_column lv_row_alpha INTO start_cell-cell_coords. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + filltype = zcl_excel_style_fill=>c_fill_none. + fgcolor-theme = zcl_excel_style_color=>c_theme_not_set. + fgcolor-indexed = zcl_excel_style_color=>c_indexed_not_set. + bgcolor-theme = zcl_excel_style_color=>c_theme_not_set. + bgcolor-indexed = zcl_excel_style_color=>c_indexed_sys_foreground. + rotation = 0. + endmethod. + + + + method GET_STRUCTURE. + es_fill-rotation = me->rotation. + es_fill-filltype = me->filltype. + es_fill-fgColor = me->fgColor. + es_fill-bgColor = me->bgColor. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CALCULATE_TEXT_WIDTH. + " Addition to solve issue #120, contribution by Stefan Schmöcker + r_width = strlen( i_text ). + " use scale factor based on default 11 + " ( don't know where defaultsetting is stored currently ) + r_width = r_width * me->size / 11. + endmethod. + + + method CONSTRUCTOR. + me->color-rgb = zcl_excel_style_color=>c_black. + me->color-theme = zcl_excel_style_color=>c_theme_not_set. + me->color-indexed = zcl_excel_style_color=>c_indexed_not_set. + me->scheme = zcl_excel_style_font=>c_scheme_minor. + me->underline_mode = zcl_excel_style_font=>c_underline_single. + endmethod. + + + + method GET_STRUCTURE. + + es_font-bold = me->bold. + es_font-italic = me->italic. + es_font-underline = me->underline. + es_font-underline_mode = me->underline_mode. + es_font-strikethrough = me->strikethrough. + es_font-size = me->size. + es_font-color = me->color. + es_font-name = me->name. + es_font-family = me->family. + es_font-scheme = me->scheme. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + format_code = me->c_format_general. + endmethod. + + + + method GET_STRUCTURE. + ep_number_format-numfmt = me->format_code. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + method CONSTRUCTOR. + locked = me->c_protection_locked. + hidden = me->c_protection_unhidden. + endmethod. + + + + method GET_STRUCTURE. + ep_protection-locked = me->locked. + ep_protection-hidden = me->hidden. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + endmethod. + + + + method GET_BOTTOM_ROW_INTEGER. + DATA: lv_table_lines TYPE i. + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + + IF settings-bottom_right_row IS NOT INITIAL. +* ev_row = zcl_excel_common=>convert_column2int( settings-bottom_right_row ). " del issue #246 + ev_row = settings-bottom_right_row . " ins issue #246 + EXIT. + ENDIF. + + ASSIGN table_data->* TO <fs_table>. + DESCRIBE TABLE <fs_table> LINES lv_table_lines. + IF lv_table_lines = 0. + lv_table_lines = 1. "table needs at least 1 data row + ENDIF. + + ev_row = settings-top_left_row + lv_table_lines. + + IF me->has_totals( ) = abap_true." ???? AND ip_include_totals_row = abap_true. + ADD 1 TO ev_row. + ENDIF. + endmethod. + + + + method GET_ID. + ov_id = id. + endmethod. + + + + method GET_NAME. + + IF me->name IS INITIAL. + me->name = zcl_excel_common=>number_to_excel_string( ip_value = me->id ). + CONCATENATE 'table' me->name INTO me->name. + ENDIF. + + ov_name = me->name. + endmethod. + + + + + method GET_REFERENCE. + DATA: lv_column TYPE zexcel_cell_column, + lv_table_lines TYPE i, + lv_right_column TYPE zexcel_cell_column_alpha, + ls_field_catalog TYPE zexcel_s_fieldcatalog, + lv_bottom_row TYPE zexcel_cell_row, + lv_top_row_string(10) TYPE c, + lv_bottom_row_string(10) TYPE c. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + +*column + lv_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). + lv_table_lines = 0. + LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. + ADD 1 TO lv_table_lines. + ENDLOOP. + lv_column = lv_column + lv_table_lines - 1. + lv_right_column = zcl_excel_common=>convert_column2alpha( lv_column ). + +*row + ASSIGN table_data->* TO <fs_table>. + DESCRIBE TABLE <fs_table> LINES lv_table_lines. + IF lv_table_lines = 0. + lv_table_lines = 1. "table needs at least 1 data row + ENDIF. + lv_bottom_row = settings-top_left_row + lv_table_lines . + + IF me->has_totals( ) = abap_true AND ip_include_totals_row = abap_true. + ADD 1 TO lv_bottom_row. + ENDIF. + + lv_top_row_string = zcl_excel_common=>number_to_excel_string( settings-top_left_row ). + lv_bottom_row_string = zcl_excel_common=>number_to_excel_string( lv_bottom_row ). + + CONCATENATE settings-top_left_column lv_top_row_string + ':' + lv_right_column lv_bottom_row_string INTO ov_reference. + + endmethod. + + + + + method GET_RIGHT_COLUMN_INTEGER. + DATA: lv_column TYPE zexcel_cell_column, + lv_table_lines TYPE i, + ls_field_catalog TYPE zexcel_s_fieldcatalog. + + IF settings-bottom_right_column IS NOT INITIAL. + ev_column = zcl_excel_common=>convert_column2int( settings-bottom_right_column ). + EXIT. + ENDIF. + + ev_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). + LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. + ADD 1 TO ev_column. + ENDLOOP. + + endmethod. + + + + + + method GET_TOTALS_FORMULA. + CONSTANTS: lc_function_id_sum TYPE string VALUE '109', + lc_function_id_min TYPE string VALUE '105', + lc_function_id_max TYPE string VALUE '104', + lc_function_id_count TYPE string VALUE '103', + lc_function_id_average TYPE string VALUE '101'. + + DATA: lv_function_id TYPE string. + + CASE ip_function. + WHEN zcl_excel_table=>totals_function_sum. + lv_function_id = lc_function_id_sum. + + WHEN zcl_excel_table=>totals_function_min. + lv_function_id = lc_function_id_min. + + WHEN zcl_excel_table=>totals_function_max. + lv_function_id = lc_function_id_max. + + WHEN zcl_excel_table=>totals_function_count. + lv_function_id = lc_function_id_count. + + WHEN zcl_excel_table=>totals_function_average. + lv_function_id = lc_function_id_average. + + WHEN zcl_excel_table=>totals_function_custom. " issue #292 + RETURN. + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid totals formula. See ZCL_ for possible values'. + ENDCASE. + + CONCATENATE 'SUBTOTAL(' lv_function_id ',[' ip_column '])' INTO ep_formula. + endmethod. + + + + method HAS_TOTALS. + DATA: ls_field_catalog TYPE zexcel_s_fieldcatalog. + + ep_result = abap_false. + + LOOP AT fieldcat INTO ls_field_catalog. + IF ls_field_catalog-totals_function IS NOT INITIAL. + ep_result = abap_true. + EXIT. + ENDIF. + ENDLOOP. + + endmethod. + + + + method SET_DATA. + GET REFERENCE OF ir_data INTO me->table_data. + endmethod. + + + + method SET_ID. + id = iv_id. + endmethod. + + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + +*&---------------------------------------------------------------------* +*& Class (Implementation) C_OI_PROXY_ERROR +*&---------------------------------------------------------------------* +CLASS c_oi_proxy_error IMPLEMENTATION. + METHOD constructor. +* IMPORTING object_name TYPE c +* method_name TYPE c. + error_nr = ret_call_not_flushed. + me->i_oi_error~error_code = c_oi_errors=>ret_call_not_flushed. + me->i_oi_error~is_flushed = ' '. + me->i_oi_error~has_failed = 'X'. + me->i_oi_error~has_succeeded = ' '. + me->message_id = 'SOFFICEINTEGRATION'. + me->message_nr = '899'. + me->param1 = object_name. + me->param2 = method_name. + ENDMETHOD. "constructor + + METHOD i_oi_error~flush_error. + IF error_nr EQ 0. + me->i_oi_error~error_code = c_oi_errors=>ret_ok. + me->i_oi_error~is_flushed = 'X'. + me->i_oi_error~has_failed = ' '. + me->i_oi_error~has_succeeded = 'X'. + me->message_id = ''. + me->message_nr = '000'. + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + IMPORTING + retcode = me->i_oi_error~error_code. + ELSEIF error_nr EQ ret_call_not_flushed. + "call still not flushed + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + errorstring = me->param2 "method name + objectname = me->param1 + IMPORTING + retcode = me->i_oi_error~error_code. + ELSE. + me->i_oi_error~is_flushed = 'X'. + me->i_oi_error~has_succeeded = ' '. + me->i_oi_error~has_failed = 'X'. + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + errorstring = error_string + IMPORTING + retcode = me->i_oi_error~error_code. + CALL METHOD c_oi_errors=>get_message + IMPORTING + message_id = me->message_id + message_number = me->message_nr + param1 = me->param1 + param2 = me->param2 + param3 = me->param3 + param4 = me->param4. + ENDIF. + ENDMETHOD. "i_oi_error~flush_error + + METHOD i_oi_error~raise_message. +* IMPORTING type TYPE c. +* EXCEPTIONS message_raised flush_failed. + IF me->i_oi_error~has_succeeded IS INITIAL. + IF NOT me->i_oi_error~is_flushed IS INITIAL. + MESSAGE ID message_id TYPE type + NUMBER message_nr WITH param1 param2 param3 param4 + RAISING message_raised. + ELSE. + RAISE flush_failed. + ENDIF. + ENDIF. + ENDMETHOD. "i_oi_error~raise_message + + METHOD i_oi_error~get_message. +* EXPORTING message_id TYPE c +* message_number TYPE c +* param1 TYPE c +* param2 TYPE c +* param3 TYPE c +* param4 TYPE c. + param1 = me->param1. param2 = me->param2. + param3 = me->param3. param4 = me->param4. + + message_id = me->message_id. + message_number = me->message_nr. + ENDMETHOD. "i_oi_error~get_message +ENDCLASS. "C_OI_PROXY_ERROR + +*&---------------------------------------------------------------------* +*& Class (Implementation) CL_GRID_ACCESSION +*&---------------------------------------------------------------------* +CLASS lcl_gui_alv_grid IMPLEMENTATION. + + METHOD get_alv_attributes. + CREATE DATA et_table LIKE io_grid->mt_outtab. + et_table = io_grid->mt_outtab. + ENDMETHOD. "get_data + +ENDCLASS. "CL_GRID_ACCESSION + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature +TYPE-POOLS: sydes. +TYPE-POOLS: slis. +*--------------------------------------------------------------------* +* CLASS c_oi_proxy_error +*--------------------------------------------------------------------* +* use for method bind_ALV +*--------------------------------------------------------------------* +CLASS c_oi_proxy_error DEFINITION. + PUBLIC SECTION. + INTERFACES: i_oi_error. + DATA: error_nr TYPE i. + DATA: error_string TYPE sy-msgv1. + + METHODS: constructor IMPORTING object_name TYPE c + method_name TYPE c. + PRIVATE SECTION. + CONSTANTS: + ret_call_not_flushed TYPE i VALUE -999999. + + DATA: message_id TYPE sy-msgid, + message_nr TYPE sy-msgno, + param1 TYPE sy-msgv1, + param2 TYPE sy-msgv2, + param3 TYPE sy-msgv3, + param4 TYPE sy-msgv4. +ENDCLASS. "c_oi_proxy_error DEFINITION + +*--------------------------------------------------------------------* +* CLASS lcl_gui_alv_grid +*--------------------------------------------------------------------* +* to get protected attribute and method of cl_gui_alv_grid +* use for method bind_ALV +*--------------------------------------------------------------------* +CLASS lcl_gui_alv_grid DEFINITION INHERITING FROM cl_gui_alv_grid. + + PUBLIC SECTION. +* get ALV grid data + METHODS: get_alv_attributes + IMPORTING + io_grid TYPE REF TO cl_gui_alv_grid " ALV grid + EXPORTING + et_table TYPE REF TO data. " dta table + +ENDCLASS. "lcl_gui_alv_grid DEFINITION + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABAP + SLIS + SOI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~CLEAR_PRINT_REPEAT_COLUMNS. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + CLEAR: me->print_title_col_from, + me->print_title_col_to . + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~CLEAR_PRINT_REPEAT_ROWS. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + CLEAR: me->print_title_row_from, + me->print_title_row_to . + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~GET_PRINT_REPEAT_COLUMNS. + ev_columns_from = me->print_title_col_from. + ev_columns_to = me->print_title_col_to. + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~GET_PRINT_REPEAT_ROWS. + ev_rows_from = me->print_title_row_from. + ev_rows_to = me->print_title_row_to. + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~SET_PRINT_REPEAT_COLUMNS. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + DATA: lv_col_from_int TYPE i, + lv_col_to_int TYPE i, + lv_errormessage TYPE string. + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range. + + + lv_col_from_int = zcl_excel_common=>convert_column2int( iv_columns_from ). + lv_col_to_int = zcl_excel_common=>convert_column2int( iv_columns_to ). + +*--------------------------------------------------------------------* +* Check if valid range is supplied +*--------------------------------------------------------------------* + IF lv_col_from_int < 1. + lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF lv_col_from_int > lv_col_to_int. + lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + me->print_title_col_from = iv_columns_from. + me->print_title_col_to = iv_columns_to. + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~SET_PRINT_REPEAT_ROWS. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + DATA: lv_errormessage TYPE string. + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range. + + + +*--------------------------------------------------------------------* +* Check if valid range is supplied +*--------------------------------------------------------------------* + IF iv_rows_from < 1. + lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF iv_rows_from > iv_rows_to. + lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + me->print_title_row_from = iv_rows_from. + me->print_title_row_to = iv_rows_to. + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~GET_STYLE. + IF zif_excel_sheet_properties~style IS NOT INITIAL. + ep_style = zif_excel_sheet_properties~style. + ELSE. + ep_style = me->excel->get_default_style( ). + ENDIF. + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~INITIALIZE. + + zif_excel_sheet_properties~show_zeros = zif_excel_sheet_properties=>c_showzero. + zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. + zif_excel_sheet_properties~summaryright = zif_excel_sheet_properties=>c_right_on. + +* inizialize zoomscale values + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale = 100. + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_normal = 100. + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_pagelayoutview = 100 . + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_sheetlayoutview = 100 . + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~SET_STYLE. + zif_excel_sheet_properties~style = ip_style. + endmethod. + + + method ZIF_EXCEL_SHEET_PROTECTION~INITIALIZE. + + me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_unprotected. + CLEAR me->zif_excel_sheet_protection~password. + me->zif_excel_sheet_protection~auto_filter = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~delete_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~delete_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_hyperlinks = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_noactive. +* me->zif_excel_sheet_protection~password = zif_excel_sheet_protection=>c_noactive. "issue #68 + me->zif_excel_sheet_protection~pivot_tables = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~select_locked_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~select_unlocked_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~sort = zif_excel_sheet_protection=>c_noactive. + + endmethod. + + + method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME. + me->zif_excel_sheet_vba_project~codename = ip_codename. + endmethod. + + + method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME_PR. + me->zif_excel_sheet_vba_project~codename_pr = ip_codename_pr. + endmethod. + + + + method ADD_DRAWING. + CASE ip_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. + drawings->include( ip_drawing ). + WHEN zcl_excel_drawing=>type_chart. + charts->include( ip_drawing ). + ENDCASE. + endmethod. + + + + method ADD_NEW_CONDITIONAL_STYLE. + + CREATE OBJECT eo_conditional_style. + conditional_styles->add( eo_conditional_style ). + endmethod. + + + + method ADD_NEW_DATA_VALIDATION. + + CREATE OBJECT eo_data_validation. + data_validations->add( eo_data_validation ). + endmethod. + + + + method ADD_NEW_RANGE. +* Create default blank range + CREATE OBJECT eo_range. + ranges->add( eo_range ). + endmethod. + + + + + + + + + method BIND_ALV. + data: lo_converter type ref to zcl_excel_converter. + + create object lo_converter. + + try. + lo_converter->convert( + exporting + io_alv = io_alv + it_table = it_table + i_row_int = i_top + i_column_int = i_left + i_table = abap_true + i_style_table = table_style + io_worksheet = me + changing + co_excel = excel ). + catch zcx_excel . + endtry. + + endmethod. + + + + + + + + + + + + + + + + + + + + + + method BIND_ALV_OLE2. +*--------------------------------------------------------------------* +* Method description: +* Method use to export a CL_GUI_ALV_GRID object to xlsx/xls file +* with list header and characteristics of ALV field catalog such as: +* + Total, group's subtotal +* + Quantity fields, amount fields (dependent fields) +* + No_out, no_zero, ... +* Technique use in method: +* SAP Desktop Office Integration (DOI) +*--------------------------------------------------------------------* + +* Data for session 0: DOI constructor +* ------------------------------------------ + + data: lo_control type ref to I_OI_CONTAINER_CONTROL. + data: lo_proxy type ref to I_OI_DOCUMENT_PROXY. + data: lo_spreadsheet type ref to I_OI_SPREADSHEET. + data: lo_error type ref to I_OI_ERROR. + data: lc_retcode type SOI_RET_STRING. + data: li_has type i. "Proxy has spreadsheet interface? + data: l_is_closed type i. + +* Data for session 1: Get LVC data from ALV object +* ------------------------------------------ + + data: l_has_activex, + l_doctype_excel_sheet(11) type c. + data: wa_DOC_HANDLE Type CNTL_HANDLE. + +* LVC + data: lt_fieldcat_lvc type LVC_T_FCAT. + data: wa_fieldcat_lvc type lvc_s_fcat. + data: lt_sort_lvc type LVC_T_SORT. + data: lt_filter_idx_lvc type LVC_T_FIDX. + data: lt_GROUPLEVELS_LVC type LVC_T_GRPL. + +* KKBLO + DATA: LT_FIELDCAT_KKBLO Type KKBLO_T_FIELDCAT. + DATA: LT_SORT_KKBLO Type KKBLO_T_SORTINFO. + DATA: LT_GROUPLEVELS_KKBLO Type KKBLO_T_GROUPLEVELS. + DATA: LT_FILTER_IDX_KKBLO Type KKBLO_T_SFINFO. + data: wa_listheader like line of it_listheader. + +* Subtotal + data: lt_collect00 type ref to data. + data: lt_collect01 type ref to data. + data: lt_collect02 type ref to data. + data: lt_collect03 type ref to data. + data: lt_collect04 type ref to data. + data: lt_collect05 type ref to data. + data: lt_collect06 type ref to data. + data: lt_collect07 type ref to data. + data: lt_collect08 type ref to data. + data: lt_collect09 type ref to data. + +* data table name + data: l_tabname type kkblo_tabname. + +* local object + data: lo_grid type ref to lcl_gui_alv_grid. + +* data table get from ALV + data: lt_alv type ref to data. + +* total / subtotal data + field-symbols: <f_collect00> type standard table. + field-symbols: <f_collect01> type standard table. + field-symbols: <f_collect02> type standard table. + field-symbols: <f_collect03> type standard table. + field-symbols: <f_collect04> type standard table. + field-symbols: <f_collect05> type standard table. + field-symbols: <f_collect06> type standard table. + field-symbols: <f_collect07> type standard table. + field-symbols: <f_collect08> type standard table. + field-symbols: <f_collect09> type standard table. + +* table before append subtotal lines + field-symbols: <f_alv_tab> type standard table. + +* data for session 2: sort, filter and calculate total/subtotal +* ------------------------------------------ + +* table to save index of subotal / total line in excel tanle +* this ideal to control index of subtotal / total line later +* for ex, when get subtotal / total line to format + types: begin of st_subtot_indexs, + index type i, + end of st_subtot_indexs. + data: lt_subtot_indexs type table of st_subtot_indexs. + data: wa_subtot_indexs like line of lt_subtot_indexs. + +* data table after append subtotal + data: lt_excel type ref to data. + + data: l_tabix type i. + data: l_save_index type i. + +* dyn subtotal table name + data: l_collect type string. + +* subtotal range, to format subtotal (and total) + data: subranges type soi_range_list. + data: subrangeitem type soi_range_item. + data: l_sub_index type i. + + +* table after append subtotal lines + field-symbols: <f_excel_tab> type standard table. + field-symbols: <f_excel_line> type any. + +* dyn subtotal tables + field-symbols: <f_collect_tab> type standard table. + field-symbols: <f_collect_line> type any. + + field-symbols: <f_filter_idx_line> like line of LT_FILTER_IDX_KKBLO. + field-symbols: <f_fieldcat_line> like line of LT_FIELDCAT_KKBLO. + field-symbols: <f_grouplevels_line> like line of LT_GROUPLEVELS_KKBLO. + field-symbols: <f_line> type any. + +* Data for session 3: map data to semantic table +* ------------------------------------------ + + types: begin of st_column_index, + fieldname type kkblo_fieldname, + tabname type kkblo_tabname, + col like sy-index, + end of st_column_index. + +* columns index + data: lt_column_index type table of st_column_index. + data: wa_column_index like line of lt_column_index. + +* table of dependent field ( currency and quantity unit field) + data: lt_fieldcat_depf type kkblo_t_fieldcat. + data: wa_fieldcat_depf type kkblo_fieldcat. + +* XXL interface: +* -XXL: contain exporting columns characteristic + data: lt_sema type table of gxxlt_s initial size 0. + data: wa_sema like line of lt_sema. + +* -XXL interface: header + data: lt_hkey type table of gxxlt_h initial size 0. + data: wa_hkey like line of lt_hkey. + +* -XXL interface: header keys + data: lt_vkey type table of gxxlt_v initial size 0. + data: wa_vkey like line of lt_vkey. + +* Number of H Keys: number of key columns + data: l_n_hrz_keys type i. +* Number of data columns in the list object: non-key columns no + data: l_n_att_cols type i. +* Number of V Keys: number of header row + data: l_n_vrt_keys type i. + +* curency to format amount + data: lt_tcurx type table of tcurx. + data: wa_tcurx like line of lt_tcurx. + data: l_def type flag. " currency / quantity flag + data: wa_t006 type t006. " decimal place of unit + + data: l_num type i. " table columns number + data: l_typ type c. " table type + data: wa type ref to data. + data: l_int type i. + data: l_counter type i. + + field-symbols: <f_excel_column> type any. + field-symbols: <f_fcat_column> type any. + +* Data for session 4: write to excel +* ------------------------------------------ + + data: data_starting_at type i value 1. + data: data_ending_at type i value -1. + data: sema_type type c. + + data l_error type ref to c_oi_proxy_error. + data count type i. + data datac type i. + data datareal type i. " exporting column number + data vkeycount type i. + data all type i. + data mit type i value 1. " index of recent row? + data li_col_pos type i value 1. " column position + data li_col_num type i. " table columns number + field-symbols: <line> type any. + field-symbols: <item> type any. + + data td type sydes_desc. + + data: typ. + data: ranges type soi_range_list. + data: rangeitem type soi_range_item. + data: contents type soi_generic_table. + data: contentsitem type soi_generic_item. + data: semaitem type gxxlt_s. + data: hkeyitem type gxxlt_h. + data: vkeyitem type gxxlt_v. + data: li_commentary_rows type i. "row number of title lines + 1 + data: lo_error_w type ref to i_oi_error. + data: l_retcode type soi_ret_string. + data: no_flush type c value 'X'. + data: li_head_top type i. "header rows position + +* Data for session 5: Save and clode document +* ------------------------------------------ + + data: li_document_size type i. + data: ls_path type RLGRAP-FILENAME. + +* MACRO: Close_document +*------------------------------------------- + + DEFINE close_document. + clear: l_is_closed. + IF lo_proxy is not initial. + +* check proxy detroyed adi + + call method lo_proxy->is_destroyed + IMPORTING + ret_value = l_is_closed. + +* if dun detroyed yet: close -> release proxy + + IF l_is_closed is initial. + call method lo_proxy->close_document +* EXPORTING +* do_save = do_save + IMPORTING + error = lo_error + retcode = lc_retcode. + ENDIF. + + call method lo_proxy->release_document + IMPORTING + error = lo_error + retcode = lC_retcode. + + else. + lc_retcode = c_oi_errors=>ret_document_not_open. + ENDIF. + +* Detroy control container + + IF lo_control is not initial. + CALL METHOD lo_control->destroy_control. + ENDIF. + + clear: + lo_spreadsheet, + lo_proxy, + lo_control. + +* free local + + clear: l_is_closed. + + END-OF-DEFINITION. + +* Macro to catch DOI error +*------------------------------------------- + + DEFINE error_doi. + if lc_retcode ne c_oi_errors=>ret_ok. + close_document. + call method lo_error->raise_message + EXPORTING + type = 'E'. + clear: lo_error. + endif. + END-OF-DEFINITION. + +*--------------------------------------------------------------------* +* SESSION 0: DOI CONSTRUCTOR +*--------------------------------------------------------------------* + +* check active windown + + call function 'GUI_HAS_ACTIVEX' + IMPORTING + return = l_has_activex. + + if l_has_activex is initial. + raise MISS_GUIDE. + endif. + +* Get Container Object of Screen + + call method c_oi_container_control_creator=>get_container_control + IMPORTING + control = lo_control + retcode = lC_retcode. + + error_doi. + +* Initialize Container control + + CALL METHOD lo_control->init_control + EXPORTING + parent = CL_GUI_CONTAINER=>DEFAULT_SCREEN + r3_application_name = '' + inplace_enabled = 'X' + no_flush = 'X' + register_on_close_event = 'X' + register_on_custom_event = 'X' + IMPORTING + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + +* Get Proxy Document: +* check exist of document proxy, if exist -> close first + + if not lo_proxy is initial. + close_document. + endif. + + IF i_xls is not initial. +* xls format, doctype = soi_doctype_excel97_sheet + l_doctype_excel_sheet = 'Excel.Sheet.8'. + else. +* xlsx format, doctype = soi_doctype_excel_sheet + l_doctype_excel_sheet = 'Excel.Sheet'. + ENDIF. + + CALL METHOD lo_control->get_document_proxy + EXPORTING + document_type = l_doctype_excel_sheet + register_container = 'X' + IMPORTING + document_proxy = lo_proxy + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + + IF I_DOCUMENT_URL is initial. + +* create new excel document + + call method lo_proxy->create_document + EXPORTING + create_view_data = 'X' + open_inplace = 'X' + no_flush = 'X' + IMPORTING + ERROR = lO_ERROR + retcode = lc_retcode. + + error_doi. + + else. + +* Read excel template for i_DOCUMENT_URL +* this excel template can be store in local or server + + CALL METHOD lo_proxy->open_document + EXPORTING + document_url = i_document_url + open_inplace = 'X' + no_flush = 'X' + IMPORTING + error = lo_error + retcode = lc_retcode. + + error_doi. + + endif. + +* Check Spreadsheet Interface of Document Proxy + + CALL METHOD lo_proxy->has_spreadsheet_interface + IMPORTING + is_available = li_has + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + +* create Spreadsheet object + + CHECK li_has IS NOT INITIAL. + + CALL METHOD lo_proxy->get_spreadsheet_interface + IMPORTING + sheet_interface = lo_spreadsheet + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + +*--------------------------------------------------------------------* +* SESSION 1: GET LVC DATA FROM ALV OBJECT +*--------------------------------------------------------------------* + +* data table + + create object lo_grid + EXPORTING + i_parent = CL_GUI_CONTAINER=>SCREEN0. + + call method lo_grid->get_alv_attributes + EXPORTING + io_grid = io_alv + IMPORTING + Et_table = lt_alv. + + assign lt_alv->* to <f_alv_tab>. + +* fieldcat + + CALL METHOD iO_alv->GET_FRONTEND_FIELDCATALOG + IMPORTING + ET_FIELDCATALOG = lt_fieldcat_LVC. + +* table name + + loop at lt_fieldcat_LVC into wa_fieldcat_lvc + where not tabname is initial. + l_tabname = wa_fieldcat_lvc-tabname. + exit. + endloop. + + if sy-subrc ne 0. + l_tabname = '1'. + endif. + clear: wa_fieldcat_lvc. + +* sort table + + CALL METHOD IO_ALV->GET_SORT_CRITERIA + IMPORTING + ET_SORT = lt_sort_lvc. + + +* filter index + + CALL METHOD IO_ALV->GET_FILTERED_ENTRIES + IMPORTING + ET_FILTERED_ENTRIES = lt_filter_idx_lvc. + +* group level + subtotal + + CALL METHOD IO_ALV->GET_SUBTOTALS + IMPORTING + EP_COLLECT00 = lt_collect00 + EP_COLLECT01 = lt_collect01 + EP_COLLECT02 = lt_collect02 + EP_COLLECT03 = lt_collect03 + EP_COLLECT04 = lt_collect04 + EP_COLLECT05 = lt_collect05 + EP_COLLECT06 = lt_collect06 + EP_COLLECT07 = lt_collect07 + EP_COLLECT08 = lt_collect08 + EP_COLLECT09 = lt_collect09 + ET_GROUPLEVELS = lt_GROUPLEVELS_LVC. + + assign lt_collect00->* to <f_collect00>. + assign lt_collect01->* to <f_collect01>. + assign lt_collect02->* to <f_collect02>. + assign lt_collect03->* to <f_collect03>. + assign lt_collect04->* to <f_collect04>. + assign lt_collect05->* to <f_collect05>. + assign lt_collect06->* to <f_collect06>. + assign lt_collect07->* to <f_collect07>. + assign lt_collect08->* to <f_collect08>. + assign lt_collect09->* to <f_collect09>. + +* transfer to KKBLO struct + + CALL FUNCTION 'LVC_TRANSFER_TO_KKBLO' + EXPORTING + IT_FIELDCAT_LVC = lt_fieldcat_lvc + IT_SORT_LVC = lt_sort_lvc + IT_FILTER_INDEX_LVC = lt_filter_idx_lvc + IT_GROUPLEVELS_LVC = lt_grouplevels_lvc + IMPORTING + ET_FIELDCAT_KKBLO = lt_fieldcat_kkblo + ET_SORT_KKBLO = lt_sort_kkblo + ET_FILTERED_ENTRIES_KKBLO = lt_filter_idx_kkblo + ET_GROUPLEVELS_KKBLO = lt_grouplevels_kkblo + TABLES + IT_DATA = <f_alv_tab> + EXCEPTIONS + IT_DATA_MISSING = 1 + IT_FIELDCAT_LVC_MISSING = 2 + OTHERS = 3. + IF SY-SUBRC <> 0. + raise ex_transfer_KKBLO_ERROR. + ENDIF. + + clear: + wa_fieldcat_lvc, + lt_fieldcat_lvc, + lt_sort_lvc, + lt_filter_idx_lvc, + lt_GROUPLEVELS_LVC. + + clear: + lo_grid. + + +*--------------------------------------------------------------------* +* SESSION 2: SORT, FILTER AND CALCULATE TOTAL / SUBTOTAL +*--------------------------------------------------------------------* + +* append subtotal & total line + + create data lt_excel like <f_ALV_TAB>. + assign lt_excel->* to <f_excel_tab>. + + loop at <f_alv_tab> assigning <f_line>. + l_save_index = sy-tabix. + +* filter base on filter index table + + read table LT_FILTER_IDX_KKBLO assigning <f_filter_idx_line> + with key index = l_save_index + binary search. + if sy-subrc ne 0. + append <f_line> to <f_excel_tab>. + endif. + +* append subtotal lines + + read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> + with key index_to = l_save_index + binary search. + if sy-subrc = 0. + l_tabix = sy-tabix. + do. + if <f_grouplevels_line>-subtot eq 'X' and + <f_grouplevels_line>-hide_level is initial and + <f_grouplevels_line>-cindex_from ne 0. + +* dynamic append subtotal line to excel table base on grouplevel table +* ex <f_GROUPLEVELS_line>-level = 1 +* then <f_collect_tab> = '<F_COLLECT01>' + + l_collect = <f_grouplevels_line>-level. + condense l_collect. + concatenate '<F_COLLECT0' + l_collect '>' +* '->*' + into l_collect. + + assign (l_collect) to <f_collect_tab>. + +* incase there're more than 1 total line of group, at the same level +* for example: subtotal of multi currency + + LOOP AT <f_collect_tab> assigning <f_collect_line>. + IF sy-tabix between <f_grouplevels_line>-cindex_from + and <f_grouplevels_line>-cindex_to. + + + append <f_collect_line> to <f_excel_tab>. + +* save subtotal lines index + + wa_subtot_indexs-index = sy-tabix. + append wa_subtot_indexs to lt_subtot_indexs. + +* append sub total ranges table for format later + + add 1 to l_sub_index. + subrangeitem-name = l_sub_index. + condense subrangeitem-name. + concatenate 'SUBTOT' + subrangeitem-name + into subrangeitem-name. + + subrangeitem-rows = wa_subtot_indexs-index. + subrangeitem-columns = 1. " start col + append subrangeitem to subranges. + clear: subrangeitem. + + ENDIF. + ENDLOOP. + unassign: <f_collect_tab>. + unassign: <f_collect_line>. + clear: l_collect. + endif. + +* check next subtotal level of group + + unassign: <f_grouplevels_line>. + add 1 to l_tabix. + + read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> + index l_tabix. + if sy-subrc ne 0 + or <f_grouplevels_line>-index_to ne l_save_index. + exit. + endif. + + unassign: + <f_collect_tab>, + <f_collect_line>. + + enddo. + endif. + + clear: + l_tabix, + l_save_index. + + unassign: + <f_filter_idx_line>, + <f_grouplevels_line>. + + endloop. + +* free local data + + unassign: + <f_line>, + <f_collect_tab>, + <f_collect_line>, + <f_fieldcat_line>. + +* append grand total line + + IF <f_collect00> is assigned. + assign <f_collect00> to <f_collect_tab>. + if <f_collect_tab> is not initial. + LOOP AT <f_collect_tab> assigning <f_collect_line>. + + append <f_collect_line> to <f_excel_tab>. + +* save total line index + + wa_subtot_indexs-index = sy-tabix. + append wa_subtot_indexs to lt_subtot_indexs. + +* append grand total range (to format) + + add 1 to l_sub_index. + subrangeitem-name = l_sub_index. + condense subrangeitem-name. + concatenate 'TOTAL' + subrangeitem-name + into subrangeitem-name. + + subrangeitem-rows = wa_subtot_indexs-index. + subrangeitem-columns = 1. " start col + append subrangeitem to subranges. + ENDLOOP. + endif. + ENDIF. + + clear: + subrangeitem, + LT_SORT_KKBLO, + <f_collect00>, + <f_collect01>, + <f_collect02>, + <f_collect03>, + <f_collect04>, + <f_collect05>, + <f_collect06>, + <f_collect07>, + <f_collect08>, + <f_collect09>. + + unassign: + <f_collect00>, + <f_collect01>, + <f_collect02>, + <f_collect03>, + <f_collect04>, + <f_collect05>, + <f_collect06>, + <f_collect07>, + <f_collect08>, + <f_collect09>, + <f_collect_tab>, + <f_collect_line>. + +*--------------------------------------------------------------------* +* SESSION 3: MAP DATA TO SEMANTIC TABLE +*--------------------------------------------------------------------* + +* get dependent field field: currency and quantity + + create data wa like line of <f_excel_tab>. + assign wa->* to <f_excel_line>. + + describe field <f_excel_line> type l_typ components l_num. + + do l_num times. + l_save_index = sy-index. + assign component l_save_index of structure <f_excel_line> + to <f_excel_column>. + if sy-subrc ne 0. + message e059(0k) with 'FATAL ERROR' raising fatal_error. + endif. + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname. + assign component <f_fieldcat_line>-fieldname + of structure <f_excel_line> to <f_fcat_column>. + + describe distance between <f_excel_column> and <f_fcat_column> + into l_int in byte mode. + +* append column index +* this columns index is of table, not fieldcat + + if l_int = 0. + wa_column_index-fieldname = <f_fieldcat_line>-fieldname. + wa_column_index-tabname = <f_fieldcat_line>-tabname. + wa_column_index-col = l_save_index. + append wa_column_index to lt_column_index. + endif. + +* append dependent fields (currency and quantity unit) + + if <f_fieldcat_line>-cfieldname is not initial. + clear wa_fieldcat_depf. + wa_fieldcat_depf-fieldname = <f_fieldcat_line>-cfieldname. + wa_fieldcat_depf-tabname = <f_fieldcat_line>-ctabname. + collect wa_fieldcat_depf into lt_fieldcat_depf. + endif. + + if <f_fieldcat_line>-qfieldname is not initial. + clear wa_fieldcat_depf. + wa_fieldcat_depf-fieldname = <f_fieldcat_line>-qfieldname. + wa_fieldcat_depf-tabname = <f_fieldcat_line>-qtabname. + collect wa_fieldcat_depf into lt_fieldcat_depf. + endif. + +* rewrite field data type + + if <f_fieldcat_line>-inttype = 'X' + and <f_fieldcat_line>-datatype(3) = 'INT'. + <f_fieldcat_line>-inttype = 'I'. + endif. + + endloop. + + clear: l_save_index. + unassign: <f_fieldcat_line>. + + enddo. + +* build semantic tables + + l_n_hrz_keys = 1. + +* Get keyfigures + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname + and tech ne 'X' + and no_out ne 'X'. + + clear wa_sema. + clear wa_hkey. + +* Units belong to keyfigures -> display as str + + read table lt_fieldcat_depf into wa_fieldcat_depf with key + fieldname = <f_fieldcat_line>-fieldname + tabname = <f_fieldcat_line>-tabname. + + if sy-subrc = 0. + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. + +* Keyfigures + + else. + case <f_fieldcat_line>-datatype. + when 'QUAN'. + wa_sema-col_typ = 'N03'. + + if <f_fieldcat_line>-no_sum ne 'X'. + wa_sema-col_ops = 'ADD'. + else. + wa_sema-col_ops = 'NOP'. " no dependent field + endif. + + when 'DATS'. + wa_sema-col_typ = 'DAT'. + wa_sema-col_ops = 'NOP'. + + when 'CHAR' OR 'UNIT' OR 'CUKY'. " Added fieldformats UNIT and CUKY - dd. 26-10-2012 Wouter Heuvelmans + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. " dependent field + +* incase numeric, ex '00120' -> display as '12' + + when 'NUMC'. + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. + + when others. + wa_sema-col_typ = 'NUM'. + + if <f_fieldcat_line>-no_sum ne 'X'. + wa_sema-col_ops = 'ADD'. + else. + wa_sema-col_ops = 'NOP'. + endif. + endcase. + endif. + + l_counter = l_counter + 1. + l_n_att_cols = l_n_att_cols + 1. + + wa_sema-col_no = l_counter. + + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-fieldname + tabname = <f_fieldcat_line>-tabname. + + if sy-subrc = 0. + wa_sema-col_src = wa_column_index-col. + else. + raise fatal_error. + endif. + +* columns index of ref currency field in table + + if not <f_fieldcat_line>-cfieldname is initial. + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-cfieldname + tabname = <f_fieldcat_line>-ctabname. + + if sy-subrc = 0. + wa_sema-col_cur = wa_column_index-col. + endif. + +* quantities fields +* treat as currency when display on excel + + elseif not <f_fieldcat_line>-qfieldname is initial. + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-qfieldname + tabname = <f_fieldcat_line>-qtabname. + if sy-subrc = 0. + wa_sema-col_cur = wa_column_index-col. + endif. + + endif. + +* Treat of fixed currency in the fieldcatalog for column + + data: l_num_help(2) type n. + + if not <f_fieldcat_line>-currency is initial. + + select * from tcurx into table lt_tcurx. + sort lt_tcurx. + read table lt_tcurx into wa_tcurx + with key currkey = <f_fieldcat_line>-currency. + if sy-subrc = 0. + l_num_help = wa_tcurx-currdec. + concatenate 'N' l_num_help into wa_sema-col_typ. + wa_sema-col_cur = sy-tabix * ( -1 ). + endif. + + endif. + + wa_hkey-col_no = l_n_att_cols. + wa_hkey-row_no = l_n_hrz_keys. + wa_hkey-col_name = <f_fieldcat_line>-reptext. + append wa_hkey to lt_hkey. + append wa_sema to lt_sema. + + endloop. + +* free local data + + clear: + lt_column_index, + wa_column_index, + lt_fieldcat_depf, + wa_fieldcat_depf, + lt_tcurx, + wa_tcurx, + l_num, + l_typ, + wa, + l_int, + l_counter. + + unassign: + <f_fieldcat_line>, + <f_excel_line>, + <f_excel_column>, + <f_fcat_column>. + +*--------------------------------------------------------------------* +* SESSION 4: WRITE TO EXCEL +*--------------------------------------------------------------------* + + clear: wa_tcurx. + refresh: lt_tcurx. + +* if spreadsheet dun have proxy yet + + if li_has is initial. + l_retcode = c_oi_errors=>ret_interface_not_supported. + call method c_oi_errors=>create_error_for_retcode + EXPORTING + retcode = l_retcode + no_flush = no_flush + IMPORTING + error = lo_error_w. + exit. + endif. + + create object l_error + EXPORTING + object_name = 'OLE_DOCUMENT_PROXY' + method_name = 'get_ranges_names'. + + call method c_oi_errors=>add_error + EXPORTING + error = l_error. + + + describe table lt_sema lines datareal. + describe table <f_excel_tab> lines datac. + describe table lt_vkey lines vkeycount. + + if datac = 0. + raise inv_data_range. + endif. + + + if vkeycount ne l_n_vrt_keys. + raise dim_mismatch_vkey. + endif. + + all = l_n_vrt_keys + l_n_att_cols. + + if datareal ne all. + raise dim_mismatch_sema. + endif. + + data: decimal type c. + +* get decimal separator format ('.', ',', ...) in Office config + + call method lo_proxy->get_application_property + EXPORTING + property_name = 'INTERNATIONAL' + subproperty_name = 'DECIMAL_SEPARATOR' + CHANGING + retvalue = decimal. + + data: wa_usr type usr01. + select * from usr01 into wa_usr where bname = sy-uname. + endselect. + + data: comma_elim(4) type c. + data: help6 type i. + field-symbols <g> type any. + data search_item(4) value ' #'. + + concatenate ',' decimal '.' decimal into comma_elim. + + data help type i. " table (with subtotal) line number + + help = datac. + + data: rowmax type i value 1. " header row number + data: columnmax type i value 0. " header columns number + + loop at lt_hkey into hkeyitem. + if hkeyitem-col_no > columnmax. + columnmax = hkeyitem-col_no. + endif. + + if hkeyitem-row_no > rowmax. + rowmax = hkeyitem-row_no. + endif. + endloop. + + data: hkeycolumns type i. " header columns no + + hkeycolumns = columnmax. + + if hkeycolumns < l_n_att_cols. + hkeycolumns = l_n_att_cols. + endif. + + columnmax = 0. + + loop at lt_vkey into vkeyitem. + if vkeyitem-col_no > columnmax. + columnmax = vkeyitem-col_no. + endif. + endloop. + + data overflow type i value 1. + data testname(10) type c. + data temp2 type i. " 1st item row position in excel + data realmit type i value 1. + data realoverflow type i value 1. " row index in content + + call method lo_spreadsheet->screen_update + EXPORTING + updating = ''. + + call method lo_spreadsheet->load_lib. + + data: str(40) type c. " range names of columns range (w/o col header) + data: rows type i. " row postion of 1st item line in ecxel + +* calculate row position of data table + + describe table iT_LISTHEADER lines li_commentary_rows. + +* if grid had title, add 1 empy line between title and table + + if li_commentary_rows ne 0. + add 1 to li_commentary_rows. + endif. + +* add top position of block data + + li_commentary_rows = li_commentary_rows + i_top - 1. + +* write header (commentary rows) + + data: li_commentary_row_index type i value 1. + data: li_content_index type i value 1. + data: ls_index(10) type c. + data ls_commentary_range(40) type c value 'TITLE'. + data: li_font_bold type i. + data: li_font_italic type i. + data: li_font_size type i. + + loop at iT_LISTHEADER into wa_listheader. + li_commentary_row_index = i_top + li_content_index - 1. + ls_index = li_content_index. + condense ls_index. + concatenate ls_commentary_range(5) ls_index + into ls_commentary_range. + condense ls_commentary_range. + +* insert title range + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = ls_commentary_range + top = li_commentary_row_index + left = i_left + rows = 1 + columns = 1 + no_flush = no_flush. + +* format range + + case wa_listheader-typ. + when 'H'. "title + li_font_size = 16. + li_font_bold = 1. + li_font_italic = -1. + when 'S'. "subtile + li_font_size = -1. + li_font_bold = 1. + li_font_italic = -1. + when others. "'A' comment + li_font_size = -1. + li_font_bold = -1. + li_font_italic = 1. + endcase. + + call method lo_spreadsheet->set_font + EXPORTING + rangename = ls_commentary_range + family = '' + size = li_font_size + bold = li_font_bold + italic = li_font_italic + align = 0 + no_flush = no_flush. + +* title: range content + + rangeitem-name = ls_commentary_range. + rangeitem-columns = 1. + rangeitem-rows = 1. + append rangeitem to ranges. + + contentsitem-row = li_content_index. + contentsitem-column = 1. + concatenate wa_listheader-key + wa_listheader-info + into contentsitem-value + separated by space. + condense contentsitem-value. + append contentsitem to contents. + + add 1 to li_content_index. + + clear: + rangeitem, + contentsitem, + ls_index. + + endloop. + +* set range data title + + call method lo_spreadsheet->set_ranges_data + EXPORTING + ranges = ranges + contents = contents + no_flush = no_flush. + + refresh: + ranges, + contents. + + rows = rowmax + li_commentary_rows + 1. + + all = wa_usr-datfm. + all = all + 3. + + loop at lt_sema into semaitem. + if semaitem-col_typ = 'DAT' or semaitem-col_typ = 'MON' or + semaitem-col_typ = 'N00' or semaitem-col_typ = 'N01' or + semaitem-col_typ = 'N01' or semaitem-col_typ = 'N02' or + semaitem-col_typ = 'N03' or semaitem-col_typ = 'PCT' or + semaitem-col_typ = 'STR' or semaitem-col_typ = 'NUM'. + clear str. + str = semaitem-col_no. + condense str. + concatenate 'DATA' str into str. + mit = semaitem-col_no. + li_col_pos = semaitem-col_no + i_left - 1. + +* range from data1 to data(n), for each columns of table + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = str + top = rows + left = li_col_pos + rows = help + columns = 1 + no_flush = no_flush. + + data dec type i value -1. + data typeinfo type sydes_typeinfo. + loop at <f_excel_tab> assigning <line>. + assign component semaitem-col_no of structure <line> to <item>. + describe field <item> into td. + read table td-types index 1 into typeinfo. + if typeinfo-type = 'P'. + dec = typeinfo-decimals. + elseif typeinfo-type = 'I'. + dec = 0. + endif. + + describe field <line> type typ components count. + mit = 1. + do count times. + if mit = semaitem-col_src. + assign component sy-index of structure <line> to <item>. + describe field <item> into td. + read table td-types index 1 into typeinfo. + if typeinfo-type = 'P'. + dec = typeinfo-decimals. + endif. + exit. + endif. + mit = mit + 1. + enddo. + exit. + endloop. + +* format for each columns of table (w/o columns headers) + + if semaitem-col_typ = 'DAT'. + if semaitem-col_no > vkeycount. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = all + no_flush = no_flush. + else. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 0 + no_flush = no_flush. + endif. + elseif semaitem-col_typ = 'STR'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 0 + no_flush = no_flush. + elseif semaitem-col_typ = 'MON'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 10 + no_flush = no_flush. + elseif semaitem-col_typ = 'N00'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 0 + no_flush = no_flush. + elseif semaitem-col_typ = 'N01'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 1 + no_flush = no_flush. + elseif semaitem-col_typ = 'N02'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 2 + no_flush = no_flush. + elseif semaitem-col_typ = 'N03'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 3 + no_flush = no_flush. + elseif semaitem-col_typ = 'N04'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 4 + no_flush = no_flush. + elseif semaitem-col_typ = 'NUM'. + if dec eq -1. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 2 + no_flush = no_flush. + else. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = dec + no_flush = no_flush. + endif. + elseif semaitem-col_typ = 'PCT'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 3 + decimals = 0 + no_flush = no_flush. + endif. + + endif. + endloop. + +* get item contents for set_range_data method +* get currency cell also + + mit = 1. + + data: currcells type soi_cell_table. + data: curritem type soi_cell_item. + + curritem-rows = 1. + curritem-columns = 1. + curritem-front = -1. + curritem-back = -1. + curritem-font = ''. + curritem-size = -1. + curritem-bold = -1. + curritem-italic = -1. + curritem-align = -1. + curritem-frametyp = -1. + curritem-framecolor = -1. + curritem-currency = ''. + curritem-number = 1. + curritem-input = -1. + + data: conv_exit(10) type c. + data: const type i. + +* Change for Correction request +* Initial 10000 lines are missing in Excel Export +* if there are only 2 columns in exported List object. + + if datareal gt 2. + const = 20000 / datareal. + else. + const = 20000 / ( datareal + 2 ). + endif. + + data: lines type i. + data: innerlines type i. + data: counter type i. + data: curritem2 like curritem. + data: curritem3 like curritem. + data: length type i. + data: found. + +* append content table (for method set_range_content) + + loop at <f_excel_tab> assigning <line>. + +* save line index to compare with lt_subtot_indexs, +* to discover line is a subtotal / totale line or not +* ex use to set 'dun display zero in subtotal / total line' + + l_save_index = sy-tabix. + + do datareal times. + read table lt_sema into semaitem with key col_no = sy-index. + if semaitem-col_src ne 0. + assign component semaitem-col_src + of structure <line> to <item>. + else. + assign component sy-index + of structure <line> to <item>. + endif. + + contentsitem-row = realoverflow. + + if sy-subrc = 0. + move semaitem-col_ops to search_item(3). + search 'ADD#CNT#MIN#MAX#AVG#NOP#DFT#' + for search_item. + if sy-subrc ne 0. + raise error_in_sema. + endif. + move semaitem-col_typ to search_item(3). + search 'NUM#N00#N01#N02#N03#N04#PCT#DAT#MON#STR#' + for search_item. + if sy-subrc ne 0. + raise error_in_sema. + endif. + contentsitem-column = sy-index. + if semaitem-col_typ eq 'DAT' or semaitem-col_typ eq 'MON'. + if semaitem-col_no > vkeycount. + + " Hinweis 512418 + " EXCEL bezieht Datumsangaben + " auf den 31.12.1899, behandelt + " aber 1900 als ein Schaltjahr + " d.h. ab 1.3.1900 korrekt + " 1.3.1900 als Zahl = 61 + + data: genesis type d value '18991230'. + data: number_of_days type p. +* change for date in char format & sema_type = X + data: temp_date type d. + + if not <item> is initial and not <item> co ' ' and not + <item> co '0'. +* change for date in char format & sema_type = X starts + if sema_type = 'X'. + describe field <item> type typ. + if typ = 'C'. + temp_date = <item>. + number_of_days = temp_date - genesis. + else. + number_of_days = <item> - genesis. + endif. + else. + number_of_days = <item> - genesis. + endif. +* change for date in char format & sema_type = X ends + if number_of_days < 61. + number_of_days = number_of_days - 1. + endif. + + set country 'DE'. + write number_of_days to contentsitem-value + no-grouping + left-justified. + set country space. + translate contentsitem-value using comma_elim. + else. + clear contentsitem-value. + endif. + else. + move <item> to contentsitem-value. + endif. + elseif semaitem-col_typ eq 'NUM' or + semaitem-col_typ eq 'N00' or + semaitem-col_typ eq 'N01' or + semaitem-col_typ eq 'N02' or + semaitem-col_typ eq 'N03' or + semaitem-col_typ eq 'N04' or + semaitem-col_typ eq 'PCT'. + set country 'DE'. + describe field <item> type typ. + + if semaitem-col_cur is initial. + if typ ne 'F'. + write <item> to contentsitem-value no-grouping + no-sign decimals 14. + else. + write <item> to contentsitem-value no-grouping + no-sign. + endif. + else. +* Treat of fixed curreny for column >>Y9CK007319 + if semaitem-col_cur < 0. + semaitem-col_cur = semaitem-col_cur * ( -1 ). + select * from tcurx into table lt_tcurx. + sort lt_tcurx. + read table lt_tcurx into + wa_tcurx index semaitem-col_cur. + if sy-subrc = 0. + if typ ne 'F'. + write <item> to contentsitem-value no-grouping + currency wa_tcurx-currkey no-sign decimals 14. + else. + write <item> to contentsitem-value no-grouping + currency wa_tcurx-currkey no-sign. + endif. + endif. + else. + assign component semaitem-col_cur + of structure <line> to <g>. +* mit = index of recent row + curritem-top = rowmax + mit + li_commentary_rows. + + li_col_pos = sy-index + i_left - 1. + curritem-left = li_col_pos. + +* if filed is quantity field (qfieldname ne space) +* or amount field (cfieldname ne space), then format decimal place +* corresponding with config + + clear: l_def. + read table LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + with key tabname = l_tabname + tech = space + no_out = space + col_pos = semaitem-col_no. + IF sy-subrc = 0. + IF <f_fieldcat_line>-cfieldname is not initial. + l_def = 'C'. + else."if <f_fieldcat_line>-qfieldname is not initial. + l_def = 'Q'. + ENDIF. + ENDIF. + +* if field is amount field +* exporting of amount field base on currency decimal table: TCURX + IF l_def = 'C'. "field is amount field + select single * from tcurx into wa_tcurx + where currkey = <g>. +* if amount ref to un-know currency -> default decimal = 2 + if sy-subrc eq 0. + curritem-decimals = wa_tcurx-currdec. + else. + curritem-decimals = 2. + endif. + + append curritem to currcells. + if typ ne 'F'. + write <item> to contentsitem-value + currency <g> + no-sign no-grouping. + else. + write <item> to contentsitem-value + decimals 14 currency <g> + no-sign no-grouping. + endif. + +* if field is quantity field +* exporting of quantity field base on quantity decimal table: T006 + + else."if l_def = 'Q'. " field is quantity field + clear: wa_t006. + select single * from t006 into wa_t006 + where MSEHI = <g>. +* if quantity ref to un-know unit-> default decimal = 2 + if sy-subrc eq 0. + curritem-decimals = wa_t006-decan. + else. + curritem-decimals = 2. + endif. + append curritem to currcells. + + write <item> to contentsitem-value + unit <g> + no-sign no-grouping. + condense contentsitem-value. + + ENDIF. + + endif. "Y9CK007319 + endif. + condense contentsitem-value. + +* add function fieldcat-no zero display + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname + and tech ne 'X' + and no_out ne 'X'. + if <f_fieldcat_line>-col_pos = semaitem-col_no. + if <f_fieldcat_line>-no_zero = 'X'. + if <item> = '0'. + clear: contentsitem-value. + endif. + +* dun display zero in total/subtotal line too + + else. + clear: wa_subtot_indexs. + read table lt_subtot_indexs into wa_subtot_indexs + with key index = l_save_index. + IF sy-subrc = 0. + if <item> = '0'. + clear: contentsitem-value. + endif. + ENDIF. + endif. + endif. + endloop. + unassign: <f_fieldcat_line>. + + if <item> lt 0. + search contentsitem-value for 'E'. + if sy-fdpos eq 0. + +* bring negative sign to front of amount + + translate contentsitem-value using '- '. + condense contentsitem-value no-gaps. + concatenate '-' contentsitem-value + into contentsitem-value. + else. + concatenate '-' contentsitem-value + into contentsitem-value. + endif. + endif. + set country space. +* Hier wird nur die korrekte Kommaseparatierung gemacht, wenn die +* Zeichen einer +* Zahl enthalten sind. Das ist f#ƒÂ#r Timestamps, die auch ":" enthalten. +* F#ƒÂ#r die +* darf keine Kommaseparierung stattfinden. +* Changing for correction request - Y6BK041073 + if contentsitem-value co '0123456789.,-+E '. + translate contentsitem-value using comma_elim. + endif. + else. + clear contentsitem-value. + +* if type is not numeric -> dun display with zero + + write <item> to contentsitem-value no-zero. + + shift contentsitem-value left deleting leading space. + + endif. + append contentsitem to contents. + endif. + enddo. + + realmit = realmit + 1. + realoverflow = realoverflow + 1. + + mit = mit + 1. +* overflow = current row index in content table + overflow = overflow + 1. + endloop. + + unassign: <f_fieldcat_line>. + +* set item range for set_range_data method + + testname = mit / const. + condense testname. + + concatenate 'TEST' testname into testname. + + realoverflow = realoverflow - 1. + realmit = realmit - 1. + help = realoverflow. + + rangeitem-name = testname. + rangeitem-columns = datareal. + rangeitem-rows = help. + append rangeitem to ranges. + +* insert item range dim + + temp2 = rowmax + 1 + li_commentary_rows + realmit - realoverflow. + +* items data + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = testname + top = temp2 + left = i_left + rows = help + columns = datareal + no_flush = no_flush. + +* get columns header contents for set_range_data method +* export columns header only if no columns header option = space + + data: rowcount type i. + data: columncount type i. + + if i_columns_header = 'X'. + +* append columns header to contents: hkey + + rowcount = 1. + do rowmax times. + columncount = 1. + do hkeycolumns times. + loop at lt_hkey into hkeyitem where col_no = columncount + and row_no = rowcount. + endloop. + if sy-subrc = 0. + str = hkeyitem-col_name. + contentsitem-value = hkeyitem-col_name. + else. + contentsitem-value = str. + endif. + contentsitem-column = columncount. + contentsitem-row = rowcount. + append contentsitem to contents. + columncount = columncount + 1. + enddo. + rowcount = rowcount + 1. + enddo. + +* incase columns header in multiline + + data: rowmaxtemp type i. + if rowmax > 1. + rowmaxtemp = rowmax - 1. + rowcount = 1. + do rowmaxtemp times. + columncount = 1. + do columnmax times. + contentsitem-column = columncount. + contentsitem-row = rowcount. + contentsitem-value = ''. + append contentsitem to contents. + columncount = columncount + 1. + enddo. + rowcount = rowcount + 1. + enddo. + endif. + +* append columns header to contents: vkey + + columncount = 1. + do columnmax times. + loop at lt_vkey into vkeyitem where col_no = columncount. + endloop. + contentsitem-value = vkeyitem-col_name. + contentsitem-row = rowmax. + contentsitem-column = columncount. + append contentsitem to contents. + columncount = columncount + 1. + enddo. +*--------------------------------------------------------------------* +* set header range for method set_range_data +* insert header keys range dim + + li_head_top = li_commentary_rows + 1. + li_col_pos = i_left. + +* insert range headers + + if hkeycolumns ne 0. + rangeitem-name = 'TESTHKEY'. + rangeitem-rows = rowmax. + rangeitem-columns = hkeycolumns. + append rangeitem to ranges. + clear: rangeitem. + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = 'TESTHKEY' + top = li_head_top + left = li_col_pos + rows = rowmax + columns = hkeycolumns + no_flush = no_flush. + endif. + endif. + +* format for columns header + total + subtotal +* ------------------------------------------ + + help = rowmax + realmit. " table + header lines + + data: item type colxxl_t. + data: lt_format type soi_format_table. + data: wa_format like line of lt_format. + data: wa_format_temp like line of lt_format. + + field-symbols: <f_source> type any. + field-symbols: <f_des> type any. + +* columns header format + + wa_format-front = -1. + wa_format-back = 15. "grey + wa_format-font = space. + wa_format-size = -1. + wa_format-bold = 1. + wa_format-align = 0. + wa_format-frametyp = -1. + wa_format-framecolor = -1. + +* get column header format from input record +* -> map input format + + if i_columns_header = 'X'. + wa_format-name = 'TESTHKEY'. + if i_format_col_header is not initial. + describe field i_format_col_header type l_typ components + li_col_num. + do li_col_num times. + if sy-index ne 1. " dun map range name + assign component sy-index of structure i_format_col_header + to <f_source>. + if <f_source> is not initial. + assign component sy-index of structure wa_format to <f_des>. + <f_des> = <f_source>. + unassign: <f_des>. + endif. + unassign: <f_source>. + endif. + enddo. + + clear: li_col_num. + endif. + + append wa_format to lt_format. + endif. + +* Zusammenfassen der Spalten mit gleicher Nachkommastellenzahl +* collect vertical cells (col) with the same number of decimal places +* to increase perfomance in currency cell format + + describe table currcells lines lines. + lines = lines - 1. + do lines times. + describe table currcells lines innerlines. + innerlines = innerlines - 1. + sort currcells by left top. + clear found. + do innerlines times. + read table currcells index sy-index into curritem. + counter = sy-index + 1. + read table currcells index counter into curritem2. + if curritem-left eq curritem2-left. + length = curritem-top + curritem-rows. + if length eq curritem2-top. + if curritem-decimals eq curritem2-decimals. + move curritem to curritem3. + curritem3-rows = curritem3-rows + curritem2-rows. + curritem-left = -1. + modify currcells index sy-index from curritem. + curritem2-left = -1. + modify currcells index counter from curritem2. + append curritem3 to currcells. + found = 'X'. + endif. + endif. + endif. + enddo. + if found is initial. + exit. + endif. + delete currcells where left = -1. + enddo. + +* Zusammenfassen der Zeilen mit gleicher Nachkommastellenzahl +* collect horizontal cells (row) with the same number of decimal places +* to increase perfomance in currency cell format + + describe table currcells lines lines. + lines = lines - 1. + do lines times. + describe table currcells lines innerlines. + innerlines = innerlines - 1. + sort currcells by top left. + clear found. + do innerlines times. + read table currcells index sy-index into curritem. + counter = sy-index + 1. + read table currcells index counter into curritem2. + if curritem-top eq curritem2-top and curritem-rows eq + curritem2-rows. + length = curritem-left + curritem-columns. + if length eq curritem2-left. + if curritem-decimals eq curritem2-decimals. + move curritem to curritem3. + curritem3-columns = curritem3-columns + curritem2-columns. + curritem-left = -1. + modify currcells index sy-index from curritem. + curritem2-left = -1. + modify currcells index counter from curritem2. + append curritem3 to currcells. + found = 'X'. + endif. + endif. + endif. + enddo. + if found is initial. + exit. + endif. + delete currcells where left = -1. + enddo. +* Ende der Zusammenfassung + + +* item data: format for currency cell, corresponding with currency + + call method lo_spreadsheet->cell_format + EXPORTING + cells = currcells + no_flush = no_flush. + +* item data: write item table content + + call method lo_spreadsheet->set_ranges_data + EXPORTING + ranges = ranges + contents = contents + no_flush = no_flush. + +* whole table range to format all table + + if i_columns_header = 'X'. + li_head_top = li_commentary_rows + 1. + else. + li_head_top = li_commentary_rows + 2. + help = help - 1. + endif. + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = 'WHOLE_TABLE' + top = li_head_top + left = i_left + rows = help + columns = datareal + no_flush = no_flush. + +* columns width auto fix +* this parameter = space in case use with exist template + + IF i_columns_autofit = 'X'. + call method lo_spreadsheet->fit_widest + EXPORTING + name = 'WHOLE_TABLE' + no_flush = no_flush. + ENDIF. + +* frame +* The parameter has 8 bits +*0 Left margin +*1 Top marginT +*2 Bottom margin +*3 Right margin +*4 Horizontal line +*5 Vertical line +*6 Thinness +*7 Thickness +* here 127 = 1111111 6-5-4-3-2-1 mean Thin-ver-hor-right-bot-top-left + +* ( final DOI method call, set no_flush = space +* equal to call method CL_GUI_CFW=>FLUSH ) + + call method lo_spreadsheet->set_frame + EXPORTING + rangename = 'WHOLE_TABLE' + typ = 127 + color = 1 + no_flush = space + IMPORTING + error = lo_error + retcode = lc_retcode. + + error_doi. + +* reformat subtotal / total line after format wholw table + + loop at subranges into subrangeitem. + l_sub_index = subrangeitem-rows + li_commentary_rows + rowmax. + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = subrangeitem-name + left = i_left + top = l_sub_index + rows = 1 + columns = datareal + no_flush = no_flush. + + wa_format-name = subrangeitem-name. + +* default format: +* - clolor: subtotal = light yellow, subtotal = yellow +* - frame: box + + IF subrangeitem-name(3) = 'SUB'. + wa_format-back = 36. "subtotal line + wa_format_temp = i_format_subtotal. + else. + wa_format-back = 27. "total line + wa_format_temp = i_format_total. + endif. + wa_format-FRAMETYP = 79. + wa_format-FRAMEcolor = 1. + wa_format-number = -1. + wa_format-align = -1. + +* get subtoal + total format from intput parameter +* overwrite default format + + if wa_format_temp is not initial. + describe field wa_format_temp type l_typ components li_col_num. + do li_col_num times. + if sy-index ne 1. " dun map range name + assign component sy-index of structure wa_format_temp + to <f_source>. + if <f_source> is not initial. + assign component sy-index of structure wa_format to <f_des>. + <f_des> = <f_source>. + unassign: <f_des>. + endif. + unassign: <f_source>. + endif. + enddo. + + clear: li_col_num. + endif. + + append wa_format to lt_format. + clear: wa_format-name. + clear: l_sub_index. + clear: wa_format_temp. + + endloop. + + if lt_format[] is not initial. + call method lo_spreadsheet->set_ranges_format + EXPORTING + formattable = lt_format + no_flush = no_flush. + refresh: lt_format. + endif. +*--------------------------------------------------------------------* + call method lo_spreadsheet->screen_update + EXPORTING + updating = 'X'. + + call method c_oi_errors=>flush_errors. + + lo_error_w = l_error. + lc_retcode = lo_error_w->error_code. + +** catch no_flush -> led to dump ( optional ) +* go_error = l_error. +* gc_retcode = go_error->error_code. +* error_doi. + + clear: + lt_sema, + wa_sema, + lt_hkey, + wa_hkey, + lt_vkey, + wa_vkey, + l_n_hrz_keys, + l_n_att_cols, + l_n_vrt_keys, + count, + datac, + datareal, + vkeycount, + all, + mit, + li_col_pos, + li_col_num, + ranges, + rangeitem, + contents, + contentsitem, + semaitem, + hkeyitem, + vkeyitem, + li_commentary_rows, + l_retcode, + li_head_top, + <f_excel_tab>. + + clear: + lo_error_w. + + unassign: + <line>, + <item>, + <f_excel_tab>. + +*--------------------------------------------------------------------* +* SESSION 5: SAVE AND CLOSE FILE +*--------------------------------------------------------------------* + +* ex of save path: 'FILE://C:\temp\test.xlsx' + concatenate 'FILE://' I_save_path + into ls_path. + + call method lo_proxy->save_document_to_url + EXPORTING + no_flush = 'X' + url = ls_path + IMPORTING + error = lo_error + retcode = lc_retcode + CHANGING + document_size = li_document_size. + + error_doi. + +* if save successfully -> raise successful message +* message i499(sy) with 'Document is Exported to ' p_path. + message i499(sy) with 'Data has been exported successfully'. + + clear: + ls_path, + li_document_size. + + close_document. + endmethod. + + + + + + + + method BIND_TABLE. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (wi p) 2012-12-01 +* - ... +* aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue #237 - Check if overlapping areas exist +* - Alessandro Iannacci 2012-12-01 +* changes: - Added raise if overlaps are detected +*--------------------------------------------------------------------* + + CONSTANTS: + lc_top_left_column TYPE zexcel_cell_column_alpha VALUE 'B', + lc_top_left_row TYPE zexcel_cell_row VALUE '3'. + + DATA: + lv_row_int TYPE zexcel_cell_row, + lv_first_row TYPE zexcel_cell_row, + lv_last_row TYPE zexcel_cell_row, + lv_column_int TYPE zexcel_cell_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lt_field_catalog TYPE zexcel_t_fieldcatalog, + lv_id TYPE i, + lv_rows TYPE i, + lv_formula TYPE string, + ls_settings TYPE zexcel_s_table_settings, + lo_table TYPE REF TO zcl_excel_table, + lt_column_name_buffer TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line, + lv_value TYPE string, + lv_syindex TYPE char3, + lv_errormessage TYPE string, "ins issue #237 + + lv_columns TYPE i, + lt_columns TYPE zexcel_t_fieldcatalog, + lv_maxcol TYPE i, + lv_maxrow TYPE i, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_curtable TYPE REF TO zcl_excel_table. + + FIELD-SYMBOLS: + <ls_field_catalog> TYPE zexcel_s_fieldcatalog, + <ls_field_catalog_custom> TYPE zexcel_s_fieldcatalog, + <fs_table_line> TYPE ANY, + <fs_fldval> TYPE ANY. + + ls_settings = is_table_settings. + + IF ls_settings-top_left_column IS INITIAL. + ls_settings-top_left_column = lc_top_left_column. + ENDIF. + + IF ls_settings-table_style IS INITIAL. + ls_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ENDIF. + + IF ls_settings-top_left_row IS INITIAL. + ls_settings-top_left_row = lc_top_left_row. + ENDIF. + + IF it_field_catalog IS NOT SUPPLIED. + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = ip_table ). + ELSE. + lt_field_catalog = it_field_catalog. + ENDIF. + + SORT lt_field_catalog BY position. + +*--------------------------------------------------------------------* +* issue #237 Check if overlapping areas exist Start +*--------------------------------------------------------------------* + "Get the number of columns for the current table + lt_columns = lt_field_catalog. + DELETE lt_columns WHERE dynpfld NE abap_true. + DESCRIBE TABLE lt_columns LINES lv_columns. + + "Calculate the top left row of the current table + lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). + lv_row_int = ls_settings-top_left_row. + + "Get number of row for the current table + DESCRIBE TABLE ip_table LINES lv_rows. + + "Calculate the bottom right row for the current table + lv_maxcol = lv_column_int + lv_columns - 1. + lv_maxrow = lv_row_int + lv_rows - 1. + ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( lv_maxcol ). + ls_settings-bottom_right_row = lv_maxrow. + + lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). + + lo_iterator = me->tables->if_object_collection~get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + + lo_curtable ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF ( ( ls_settings-top_left_row GE lo_curtable->settings-top_left_row AND ls_settings-top_left_row LE lo_curtable->settings-bottom_right_row ) + OR + ( ls_settings-bottom_right_row GE lo_curtable->settings-top_left_row AND ls_settings-bottom_right_row LE lo_curtable->settings-bottom_right_row ) + ) + AND + ( ( lv_column_int GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_column_int LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) + OR + ( lv_maxcol GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_maxcol LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) + ). + lv_errormessage = 'Table overlaps with previously bound table and will not be added to worksheet.'(400). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDWHILE. +*--------------------------------------------------------------------* +* issue #237 Check if overlapping areas exist End +*--------------------------------------------------------------------* + + CREATE OBJECT lo_table. + lo_table->settings = ls_settings. + lo_table->set_data( ir_data = ip_table ). + lv_id = me->excel->get_next_table_id( ). + lo_table->set_id( iv_id = lv_id ). +* lo_table->fieldcat = lt_field_catalog[]. + + me->tables->add( lo_table ). + +* It is better to loop column by column (only visible column) + LOOP AT lt_field_catalog ASSIGNING <ls_field_catalog> WHERE dynpfld EQ abap_true. + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + + " Due restrinction of new table object we cannot have two column with the same name + " Check if a column with the same name exists, if exists add a counter + " If no medium description is provided we try to use small or long +* lv_value = <ls_field_catalog>-scrtext_m. + IF <ls_field_catalog>-scrtext_m IS NOT INITIAL. + lv_value = <ls_field_catalog>-scrtext_m. + <ls_field_catalog>-scrtext_l = lv_value. + ELSEIF <ls_field_catalog>-scrtext_s IS NOT INITIAL. + lv_value = <ls_field_catalog>-scrtext_s. + <ls_field_catalog>-scrtext_l = lv_value. + ELSEIF <ls_field_catalog>-scrtext_l IS NOT INITIAL. + lv_value = <ls_field_catalog>-scrtext_l. + ELSE. + lv_value = 'Column'. " default value as Excel does + <ls_field_catalog>-scrtext_l = lv_value. + ENDIF. + WHILE 1 = 1. + + READ TABLE lt_column_name_buffer TRANSPORTING NO FIELDS WITH KEY table_line = lv_value BINARY SEARCH. + IF sy-subrc <> 0. + <ls_field_catalog>-scrtext_l = lv_value. + INSERT lv_value INTO TABLE lt_column_name_buffer. + EXIT. + ELSE. + lv_syindex = sy-index. + CONCATENATE <ls_field_catalog>-scrtext_l lv_syindex INTO lv_value. + ENDIF. + + ENDWHILE. + " First of all write column header + IF <ls_field_catalog>-style_header IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_value + ip_style = <ls_field_catalog>-style_header ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_value ). + ENDIF. + + ADD 1 TO lv_row_int. + LOOP AT ip_table ASSIGNING <fs_table_line>. + + ASSIGN COMPONENT <ls_field_catalog>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. + " issue #290 Add formula support in table + IF <ls_field_catalog>-formula EQ abap_true. + IF <ls_field_catalog>-style IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> ). + ENDIF. + ELSE. + IF <ls_field_catalog>-style IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> ). + ENDIF. + ENDIF. + ADD 1 TO lv_row_int. + + ENDLOOP. + IF sy-subrc <> 0. "create empty row if table has no data + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = space ). + ADD 1 TO lv_row_int. + ENDIF. + +*--------------------------------------------------------------------* + " totals +*--------------------------------------------------------------------* + IF <ls_field_catalog>-totals_function IS NOT INITIAL. + lv_formula = lo_table->get_totals_formula( ip_column = <ls_field_catalog>-scrtext_l ip_function = <ls_field_catalog>-totals_function ). + IF <ls_field_catalog>-style_total IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = lv_formula + ip_style = <ls_field_catalog>-style_total ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = lv_formula ). + ENDIF. + ENDIF. + + lv_row_int = ls_settings-top_left_row. + ADD 1 TO lv_column_int. + +*--------------------------------------------------------------------* + " conditional formatting +*--------------------------------------------------------------------* + IF <ls_field_catalog>-cond_style IS NOT INITIAL. + lv_first_row = ls_settings-top_left_row + 1. " +1 to exclude header + lv_last_row = ls_settings-top_left_row + lv_rows. + <ls_field_catalog>-cond_style->set_range( ip_start_column = lv_column_alpha + ip_start_row = lv_first_row + ip_stop_column = lv_column_alpha + ip_stop_row = lv_last_row ). + ENDIF. + + ENDLOOP. + +*--------------------------------------------------------------------* + " Set field catalog +*--------------------------------------------------------------------* + lo_table->fieldcat = lt_field_catalog[]. + + es_table_settings = ls_settings. + es_table_settings-bottom_right_column = lv_column_alpha. + " >> Issue #291 + IF ip_table IS INITIAL. + es_table_settings-bottom_right_row = ls_settings-top_left_row + 2. "Last rows + ELSE. + es_table_settings-bottom_right_row = ls_settings-top_left_row + lv_rows + 1. "Last rows + ENDIF. + " << Issue #291 + + endmethod. + + + + + + + method CALCULATE_CELL_WIDTH. + DATA: cell_value TYPE zexcel_cell_value, + guid TYPE zexcel_cell_style, + stylemapping TYPE zexcel_s_stylemapping. + + me->get_cell( EXPORTING ip_column = ip_column " Cell Column + ip_row = ip_row " Cell Row + IMPORTING ep_value = cell_value + ep_guid = guid )." Cell Value ). + + + ep_width = STRLEN( cell_value ). + TRY. + stylemapping = me->excel->get_style_to_guid( guid ). + CATCH zcx_excel. + EXIT. " Do nothing if no style was found + ENDTRY. + + IF stylemapping-complete_stylex-font-size = 'X'. + ep_width = ep_width * stylemapping-complete_style-font-size / 11. + ENDIF. + + endmethod. + + + + method CALCULATE_COLUMN_WIDTHS. + TYPES: + BEGIN OF t_auto_size, + col_index TYPE int4, + width TYPE float, + END OF t_auto_size. + TYPES: tt_auto_size TYPE TABLE OF t_auto_size. + + DATA: column_dimensions TYPE zexcel_t_worksheet_columndime. + DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + DATA: auto_size TYPE flag. + DATA: auto_sizes TYPE tt_auto_size. +* DATA: col_alpha TYPE zexcel_cell_column_alpha." issue #155 - less restrictive typing for ip_column + DATA: cell_value TYPE zexcel_cell_value. + DATA: cell_style TYPE REF TO zcl_excel_style. + DATA: count TYPE int4. + DATA: highest_row TYPE int4. + DATA: width TYPE i. + + FIELD-SYMBOLS: <column_dimension> LIKE LINE OF column_dimensions. + FIELD-SYMBOLS: <auto_size> LIKE LINE OF auto_sizes. + + column_dimensions[] = me->get_column_dimensions( ). + LOOP AT column_dimensions ASSIGNING <column_dimension>. + auto_size = <column_dimension>-column_dimension->get_auto_size( ). + IF auto_size = abap_true. + APPEND INITIAL LINE TO auto_sizes ASSIGNING <auto_size>. + <auto_size>-col_index = <column_dimension>-column_dimension->get_column_index( ). + <auto_size>-width = -1. + ENDIF. + ENDLOOP. + + " There is only something to do if there are some auto-size columns + IF NOT auto_sizes IS INITIAL. + highest_row = me->get_highest_row( ). + LOOP AT auto_sizes ASSIGNING <auto_size>. +* col_alpha = zcl_excel_common=>convert_column2alpha( <auto_size>-col_index )." issue #155 - less restrictive typing for ip_column + count = 1. + WHILE count <= highest_row. +* Start of change # issue 139 - Dateretention of cellstyles +* IF cell_style IS BOUND. +* CREATE OBJECT cell_style. +* ENDIF. +* me->get_cell( +* EXPORTING +* ip_column = col_alpha " Cell Column +* ip_row = count " Cell Row +* IMPORTING +* ep_value = cell_value " Cell Value +* ep_style = cell_style " Request Cell Style as well +* ). +* " For an easy start we just take the number of characters as the width +* width = strlen( cell_value ). +* " Addition to solve issue #120, contribution by Stefan Schm#ƒÂ#cker +* " Calculate width using Font Size and Font Type +* IF cell_style IS BOUND +* AND cell_style->font IS BOUND. +* width = cell_style->font->calculate_text_width( cell_value ). +* ENDIF. +* width = calculate_cell_width( ip_column = col_alpha " issue #155 - less restrictive typing for ip_column + width = calculate_cell_width( ip_column = <auto_size>-col_index " issue #155 - less restrictive typing for ip_column + ip_row = count ). +* End of change # issue 139 - Dateretention of cellstyles + IF width > <auto_size>-width. + <auto_size>-width = width. + ENDIF. + count = count + 1. + ENDWHILE. +* column_dimension = me->get_column_dimension( col_alpha ). " issue #155 - less restrictive typing for ip_column + column_dimension = me->get_column_dimension( <auto_size>-col_index ). " issue #155 - less restrictive typing for ip_column + column_dimension->set_width( <auto_size>-width ). + ENDLOOP. + ENDIF. + + endmethod. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CHANGE_CELL_STYLE. + " issue # 139 + DATA: stylemapping TYPE zexcel_s_stylemapping, + + complete_style TYPE zexcel_s_cstyle_complete, + complete_stylex TYPE zexcel_s_cstylex_complete, + + borderx TYPE zexcel_s_cstylex_border, + l_guid TYPE zexcel_cell_style. "issue # 177 + +* We have a lot of parameters. Use some macros to make the coding more structured + + DEFINE clear_initial_colorxfields. + if &1-rgb is initial. + clear &2-rgb. + endif. + if &1-indexed is initial. + clear &2-indexed. + endif. + if &1-theme is initial. + clear &2-theme. + endif. + if &1-tint is initial. + clear &2-tint. + endif. + END-OF-DEFINITION. + + DEFINE move_supplied_borders. + if ip_&1 is supplied. " only act if parameter was supplied + if ip_x&1 is supplied. " + borderx = ip_x&1. " use supplied x-parameter + else. + clear borderx with 'X'. +* clear in a way that would be expected to work easily + if ip_&1-border_style is initial. + clear borderx-border_style. + endif. + clear_initial_colorxfields ip_&1-border_color borderx-border_color. + endif. + move-corresponding ip_&1 to complete_style-&2. + move-corresponding borderx to complete_stylex-&2. + endif. + END-OF-DEFINITION. + +* First get current stylsettings + TRY. + me->get_cell( EXPORTING ip_column = ip_column " Cell Column + ip_row = ip_row " Cell Row + IMPORTING ep_guid = l_guid )." Cell Value ). "issue # 177 + + + stylemapping = me->excel->get_style_to_guid( l_guid ). "issue # 177 + complete_style = stylemapping-complete_style. + complete_stylex = stylemapping-complete_stylex. + CATCH zcx_excel. +* Error --> use submitted style + ENDTRY. + +* move_supplied_multistyles: complete. + IF ip_complete IS SUPPLIED. + IF ip_xcomplete IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Complete styleinfo has to be supplied with corresponding X-field'. + ENDIF. + MOVE-CORRESPONDING ip_complete TO complete_style. + MOVE-CORRESPONDING ip_xcomplete TO complete_stylex. + ENDIF. + + + + IF ip_font IS SUPPLIED. + DATA: fontx LIKE ip_xfont. + IF ip_xfont IS SUPPLIED. + fontx = ip_xfont. + ELSE. +* Only supplied values should be used - exception: Flags bold and italic strikethrough underline + MOVE 'X' TO: fontx-bold, + fontx-italic, + fontx-strikethrough, + fontx-underline_mode. + CLEAR fontx-color WITH 'X'. + clear_initial_colorxfields ip_font-color fontx-color. + IF ip_font-family IS NOT INITIAL. + fontx-family = 'X'. + ENDIF. + IF ip_font-name IS NOT INITIAL. + fontx-name = 'X'. + ENDIF. + IF ip_font-scheme IS NOT INITIAL. + fontx-scheme = 'X'. + ENDIF. + IF ip_font-size IS NOT INITIAL. + fontx-size = 'X'. + ENDIF. + IF ip_font-underline_mode IS NOT INITIAL. + fontx-underline_mode = 'X'. + ENDIF. + ENDIF. + MOVE-CORRESPONDING ip_font TO complete_style-font. + MOVE-CORRESPONDING fontx TO complete_stylex-font. +* Correction for undeline mode + ENDIF. + + IF ip_fill IS SUPPLIED. + DATA: fillx LIKE ip_xfill. + IF ip_xfill IS SUPPLIED. + fillx = ip_xfill. + ELSE. + CLEAR fillx WITH 'X'. + IF ip_fill-filltype IS INITIAL. + CLEAR fillx-filltype. + ENDIF. + clear_initial_colorxfields ip_fill-fgcolor fillx-fgcolor. + clear_initial_colorxfields ip_fill-bgcolor fillx-bgcolor. + + ENDIF. + MOVE-CORRESPONDING ip_fill TO complete_style-fill. + MOVE-CORRESPONDING fillx TO complete_stylex-fill. + ENDIF. + + + IF ip_borders IS SUPPLIED. + DATA: bordersx LIKE ip_xborders. + IF ip_xborders IS SUPPLIED. + bordersx = ip_xborders. + ELSE. + CLEAR bordersx WITH 'X'. + IF ip_borders-allborders-border_style IS INITIAL. + CLEAR bordersx-allborders-border_style. + ENDIF. + IF ip_borders-diagonal-border_style IS INITIAL. + CLEAR bordersx-diagonal-border_style. + ENDIF. + IF ip_borders-down-border_style IS INITIAL. + CLEAR bordersx-down-border_style. + ENDIF. + IF ip_borders-left-border_style IS INITIAL. + CLEAR bordersx-left-border_style. + ENDIF. + IF ip_borders-right-border_style IS INITIAL. + CLEAR bordersx-right-border_style. + ENDIF. + IF ip_borders-top-border_style IS INITIAL. + CLEAR bordersx-top-border_style. + ENDIF. + clear_initial_colorxfields ip_borders-allborders-border_color bordersx-allborders-border_color. + clear_initial_colorxfields ip_borders-diagonal-border_color bordersx-diagonal-border_color. + clear_initial_colorxfields ip_borders-down-border_color bordersx-down-border_color. + clear_initial_colorxfields ip_borders-left-border_color bordersx-left-border_color. + clear_initial_colorxfields ip_borders-right-border_color bordersx-right-border_color. + clear_initial_colorxfields ip_borders-top-border_color bordersx-top-border_color. + + ENDIF. + MOVE-CORRESPONDING ip_borders TO complete_style-borders. + MOVE-CORRESPONDING bordersx TO complete_stylex-borders. + ENDIF. + + IF ip_alignment IS SUPPLIED. + DATA: alignmentx LIKE ip_xalignment. + IF ip_xalignment IS SUPPLIED. + alignmentx = ip_xalignment. + ELSE. + CLEAR alignmentx WITH 'X'. + IF ip_alignment-horizontal IS INITIAL. + CLEAR alignmentx-horizontal. + ENDIF. + IF ip_alignment-vertical IS INITIAL. + CLEAR alignmentx-vertical. + ENDIF. + ENDIF. + MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. + MOVE-CORRESPONDING alignmentx TO complete_stylex-alignment. + ENDIF. + + IF ip_protection IS SUPPLIED. + MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. + IF ip_xprotection IS SUPPLIED. + MOVE-CORRESPONDING ip_xprotection TO complete_stylex-protection. + ELSE. + IF ip_protection-hidden IS NOT INITIAL. + complete_style-protection-hidden = 'X'. + ENDIF. + IF ip_protection-locked IS NOT INITIAL. + complete_style-protection-locked = 'X'. + ENDIF. + ENDIF. + ENDIF. + + + move_supplied_borders : borders_allborders borders-allborders, + borders_diagonal borders-diagonal , + borders_down borders-down , + borders_left borders-left , + borders_right borders-right , + borders_top borders-top . + + DEFINE move_supplied_singlestyles. + if ip_&1 is supplied. + complete_style-&2 = ip_&1. + complete_stylex-&2 = 'X'. + endif. + END-OF-DEFINITION. + + move_supplied_singlestyles: number_format_format_code number_format-format_code, + font_bold font-bold, + font_color font-color, + font_color_rgb font-color-rgb, + font_color_indexed font-color-indexed, + font_color_theme font-color-theme, + font_color_tint font-color-tint, + + font_family font-family, + font_italic font-italic, + font_name font-name, + font_scheme font-scheme, + font_size font-size, + font_strikethrough font-strikethrough, + font_underline font-underline, + font_underline_mode font-underline_mode, + fill_filltype fill-filltype, + fill_rotation fill-rotation, + fill_fgcolor fill-fgcolor, + fill_fgcolor_rgb fill-fgcolor-rgb, + fill_fgcolor_indexed fill-fgcolor-indexed, + fill_fgcolor_theme fill-fgcolor-theme, + fill_fgcolor_tint fill-fgcolor-tint, + + fill_bgcolor fill-bgcolor, + fill_bgcolor_rgb fill-bgcolor-rgb, + fill_bgcolor_indexed fill-bgcolor-indexed, + fill_bgcolor_theme fill-bgcolor-theme, + fill_bgcolor_tint fill-bgcolor-tint, + + borders_diagonal_mode borders-diagonal_mode, + alignment_horizontal alignment-horizontal, + alignment_vertical alignment-vertical, + alignment_textrotation alignment-textrotation, + alignment_wraptext alignment-wraptext, + alignment_shrinktofit alignment-shrinktofit, + alignment_indent alignment-indent, + protection_hidden protection-hidden, + protection_locked protection-locked, + + borders_allborders_style borders-allborders-border_style, + borders_allborders_color borders-allborders-border_color, + borders_allbo_color_rgb borders-allborders-border_color-rgb, + borders_allbo_color_indexed borders-allborders-border_color-indexed, + borders_allbo_color_theme borders-allborders-border_color-theme, + borders_allbo_color_tint borders-allborders-border_color-tint, + + borders_diagonal_style borders-diagonal-border_style, + borders_diagonal_color borders-diagonal-border_color, + borders_diagonal_color_rgb borders-diagonal-border_color-rgb, + borders_diagonal_color_inde borders-diagonal-border_color-indexed, + borders_diagonal_color_them borders-diagonal-border_color-theme, + borders_diagonal_color_tint borders-diagonal-border_color-tint, + + borders_down_style borders-down-border_style, + borders_down_color borders-down-border_color, + borders_down_color_rgb borders-down-border_color-rgb, + borders_down_color_indexed borders-down-border_color-indexed, + borders_down_color_theme borders-down-border_color-theme, + borders_down_color_tint borders-down-border_color-tint, + + borders_left_style borders-left-border_style, + borders_left_color borders-left-border_color, + borders_left_color_rgb borders-left-border_color-rgb, + borders_left_color_indexed borders-left-border_color-indexed, + borders_left_color_theme borders-left-border_color-theme, + borders_left_color_tint borders-left-border_color-tint, + + borders_right_style borders-right-border_style, + borders_right_color borders-right-border_color, + borders_right_color_rgb borders-right-border_color-rgb, + borders_right_color_indexed borders-right-border_color-indexed, + borders_right_color_theme borders-right-border_color-theme, + borders_right_color_tint borders-right-border_color-tint, + + borders_top_style borders-top-border_style, + borders_top_color borders-top-border_color, + borders_top_color_rgb borders-top-border_color-rgb, + borders_top_color_indexed borders-top-border_color-indexed, + borders_top_color_theme borders-top-border_color-theme, + borders_top_color_tint borders-top-border_color-tint. + + +* Now we have a completly filled styles. +* This can be used to get the guid +* Return guid if requested. Might be used if copy&paste of styles is requested + ep_guid = me->excel->get_static_cellstyle_guid( ip_cstyle_complete = complete_style + ip_cstylex_complete = complete_stylex ). + me->set_cell_style( ip_column = ip_column + ip_row = ip_row + ip_style = ep_guid ). + + endmethod. + + + + + + method CONSTRUCTOR. + DATA: lv_title TYPE zexcel_sheet_title. + + me->excel = ip_excel. + + CALL FUNCTION 'GUID_CREATE' + IMPORTING + ev_guid_16 = me->guid. + + IF ip_title IS NOT INITIAL. + lv_title = ip_title. + ELSE. +* lv_title = me->guid. " del issue #154 - Names of worksheets + lv_title = me->generate_title( ). " ins issue #154 - Names of worksheets + ENDIF. + + me->set_title( ip_title = lv_title ). + + CREATE OBJECT sheet_setup. + CREATE OBJECT conditional_styles. + CREATE OBJECT data_validations. + CREATE OBJECT tables. + CREATE OBJECT ranges. " issue #163 + CREATE OBJECT drawings + EXPORTING + ip_type = zcl_excel_drawing=>type_image. + CREATE OBJECT charts + EXPORTING + ip_type = zcl_excel_drawing=>type_chart. + me->zif_excel_sheet_protection~initialize( ). + me->zif_excel_sheet_properties~initialize( ). + CREATE OBJECT hyperlinks. + +* initialize active cell coordinates + active_cell-cell_row = 1. + active_cell-cell_column = 1. + +* inizialize dimension range + lower_cell-cell_row = 1. + lower_cell-cell_column = 1. + upper_cell-cell_row = 1. + upper_cell-cell_column = 1. + + endmethod. + + + method DELETE_MERGE. + + DELETE sheet_content_merge INDEX 1. + DELETE sheet_content_merge INDEX 1. + + endmethod. + + + + + + method FREEZE_PANES. + data: lv_xsplit type i, + lv_ysplit type i. + + IF ip_num_columns IS NOT SUPPLIED AND ip_num_rows IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Pleas provide number of rows and/or columns to freeze'. + ENDIF. + + IF ip_num_columns IS SUPPLIED AND ip_num_columns <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Number of columns to freeze should be positive'. + ENDIF. + + IF ip_num_rows IS SUPPLIED AND ip_num_rows <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Number of rows to freeze should be positive'. + ENDIF. + + freeze_pane_cell_column = ip_num_columns + 1. + freeze_pane_cell_row = ip_num_rows + 1. + endmethod. + + + + method GENERATE_TITLE. + DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + errormessage TYPE string. + + DATA: t_titles TYPE HASHED TABLE OF zexcel_sheet_title WITH UNIQUE KEY table_line, + title TYPE zexcel_sheet_title, + sheetnumber TYPE i. + +* Get list of currently used titles + lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_worksheets_iterator->has_next( ) = abap_true. + lo_worksheet ?= lo_worksheets_iterator->get_next( ). + title = lo_worksheet->get_title( ). + INSERT title INTO TABLE t_titles. + ADD 1 TO sheetnumber. + ENDWHILE. + +* Now build sheetnumber. Increase counter until we hit a number that is not used so far + ADD 1 TO sheetnumber. " Start counting with next number + DO. + title = sheetnumber. + SHIFT title LEFT DELETING LEADING space. + CONCATENATE 'Sheet'(001) title INTO ep_title. + INSERT ep_title INTO TABLE t_titles. + IF sy-subrc = 0. " Title not used so far --> take it + EXIT. + ENDIF. + + ADD 1 TO sheetnumber. + ENDDO. + endmethod. + + + + + method GET_ACTIVE_CELL. + + DATA: lv_active_column TYPE zexcel_cell_column_alpha, + lv_active_row TYPE string. + + lv_active_column = zcl_excel_common=>convert_column2alpha( active_cell-cell_column ). + lv_active_row = active_cell-cell_row. + SHIFT lv_active_row RIGHT DELETING TRAILING space. + SHIFT lv_active_row LEFT DELETING LEADING space. + CONCATENATE lv_active_column lv_active_row INTO ep_active_cell. + + endmethod. + + + + + + + + + + method GET_CELL. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + READ TABLE sheet_content INTO ls_sheet_content WITH TABLE KEY cell_row = ip_row + cell_column = lv_column. + + ep_rc = sy-subrc. + ep_value = ls_sheet_content-cell_value. + ep_guid = ls_sheet_content-cell_style. " issue 139 - added this to be used for columnwidth calculation + + " Addition to solve issue #120, contribution by Stefan Schm#ƒÂ#cker + DATA: style_iterator TYPE REF TO cl_object_collection_iterator, + style TYPE REF TO zcl_excel_style. + IF ep_style IS REQUESTED. + style_iterator = me->excel->get_styles_iterator( ). + WHILE style_iterator->has_next( ) = 'X'. + style ?= style_iterator->get_next( ). + IF style->get_guid( ) = ls_sheet_content-cell_style. + ep_style = style. + EXIT. + ENDIF. + ENDWHILE. + ENDIF. + endmethod. + + + + + + method GET_COLUMN_DIMENSION. + FIELD-SYMBOLS: <fs_column_dimension> LIKE LINE OF column_dimensions. + DATA: lv_column_alpha TYPE zexcel_cell_column_alpha. " issue #155 - less restrictive typing for ip_column + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column )." issue #155 - less restrictive typing for ip_column + READ TABLE me->column_dimensions ASSIGNING <fs_column_dimension> + WITH KEY column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column + + IF NOT <fs_column_dimension> IS ASSIGNED. + CREATE OBJECT r_column_dimension + EXPORTING + ip_index = lv_column_alpha " issue #155 - less restrictive typing for ip_column + ip_excel = me->excel " issue #157 - Allow style for columns + ip_worksheet = me. " issue #157 - Allow style for columns + APPEND INITIAL LINE TO me->column_dimensions ASSIGNING <fs_column_dimension>. + <fs_column_dimension>-column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column + <fs_column_dimension>-column_dimension = r_column_dimension. + ELSE. + r_column_dimension = <fs_column_dimension>-column_dimension. + ENDIF. + + endmethod. + + + + method GET_COLUMN_DIMENSIONS. + r_column_dimension[] = me->column_dimensions[]. + endmethod. + + + + method GET_COND_STYLES_ITERATOR. + + eo_iterator = me->conditional_styles->get_iterator( ). + endmethod. + + + + method GET_DATA_VALIDATIONS_ITERATOR. + + eo_iterator = me->data_validations->get_iterator( ). + endmethod. + + + + method GET_DATA_VALIDATIONS_SIZE. + ep_size = me->data_validations->size( ). + endmethod. + + + + method GET_DEFAULT_COLUMN_DIMENSION. + IF me->default_column_dimension IS NOT BOUND. + CREATE OBJECT me->default_column_dimension + EXPORTING + ip_index = 'A' " ???? + ip_worksheet = me + ip_excel = me->excel. + ENDIF. + + r_column_dimension = me->default_column_dimension. + endmethod. + + + + method GET_DEFAULT_EXCEL_DATE_FORMAT. + CONSTANTS: c_lang_e TYPE lang VALUE 'E'. + + IF default_excel_date_format IS NOT INITIAL. + ep_default_excel_date_format = default_excel_date_format. + RETURN. + ENDIF. + + "try to get defaults + TRY. + cl_abap_datfm=>get_date_format_des( EXPORTING im_langu = c_lang_e + IMPORTING ex_dateformat = default_excel_date_format ). + CATCH cx_abap_datfm_format_unknown. + + ENDTRY. + + " and fallback to fixed format + IF default_excel_date_format IS INITIAL. + default_excel_date_format = zcl_excel_style_number_format=>c_format_date_ddmmyyyydot. + ENDIF. + + ep_default_excel_date_format = default_excel_date_format. + endmethod. + + + + method GET_DEFAULT_EXCEL_TIME_FORMAT. + DATA: l_timefm TYPE xutimefm. + + IF default_excel_time_format IS NOT INITIAL. + ep_default_excel_time_format = default_excel_time_format. + RETURN. + ENDIF. + +* Let's get default + l_timefm = cl_abap_timefm=>get_environment_timefm( ). + CASE l_timefm. + WHEN 0. +*0 24 Hour Format (Example: 12:05:10) + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. + WHEN 1. +*1 12 Hour Format (Example: 12:05:10 PM) + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 2. +*2 12 Hour Format (Example: 12:05:10 pm) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 3. +*3 Hours from 0 to 11 (Example: 00:05:10 PM) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 4. +*4 Hours from 0 to 11 (Example: 00:05:10 pm) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN OTHERS. + " and fallback to fixed format + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. + ENDCASE. + + ep_default_excel_time_format = default_excel_time_format. + endmethod. + + + + method GET_DEFAULT_ROW_DIMENSION. + IF me->default_row_dimension IS NOT BOUND. + CREATE OBJECT me->default_row_dimension. + ENDIF. + + r_row_dimension = me->default_row_dimension. + endmethod. + + + + + method GET_DIMENSION_RANGE. + + me->update_dimension_range( ). + IF upper_cell EQ lower_cell. "only one cell + " Worksheet not filled +* IF upper_cell-cell_coords = '0'. + IF upper_cell-cell_coords IS INITIAL. + ep_dimension_range = 'A1'. + ELSE. + ep_dimension_range = upper_cell-cell_coords. + ENDIF. + ELSE. + CONCATENATE upper_cell-cell_coords ':' lower_cell-cell_coords INTO ep_dimension_range. + ENDIF. + + endmethod. + + + + + method GET_DRAWINGS. + + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + lo_iterator TYPE REF TO cl_object_collection_iterator. + + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + r_drawings = drawings. + WHEN zcl_excel_drawing=>type_chart. + r_drawings = charts. + WHEN space. + CREATE OBJECT r_drawings + EXPORTING + ip_type = ''. + + lo_iterator = drawings->get_iterator( ). + WHILE lo_iterator->has_next( ) = abap_true. + lo_drawing ?= lo_iterator->get_next( ). + r_drawings->include( lo_drawing ). + ENDWHILE. + lo_iterator = charts->get_iterator( ). + WHILE lo_iterator->has_next( ) = abap_true. + lo_drawing ?= lo_iterator->get_next( ). + r_drawings->include( lo_drawing ). + ENDWHILE. + WHEN OTHERS. + ENDCASE. + endmethod. + + + + + method GET_DRAWINGS_ITERATOR. + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + eo_iterator = drawings->get_iterator( ). + WHEN zcl_excel_drawing=>type_chart. + eo_iterator = charts->get_iterator( ). + ENDCASE. + endmethod. + + + + + method GET_FREEZE_CELL. + ep_row = me->freeze_pane_cell_row. + ep_column = me->freeze_pane_cell_column. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + + method GET_HIGHEST_COLUMN. + me->update_dimension_range( ). + r_highest_column = me->lower_cell-cell_column. + endmethod. + + + + + method GET_HIGHEST_ROW. + me->update_dimension_range( ). + r_highest_row = me->lower_cell-cell_row. + endmethod. + + + + method GET_HYPERLINKS_ITERATOR. + eo_iterator = hyperlinks->get_iterator( ). + endmethod. + + + + method GET_HYPERLINKS_SIZE. + ep_size = hyperlinks->size( ). + endmethod. + + + + + method GET_MERGE. + + DATA: lv_column_start TYPE string, + lv_column_end TYPE string, + lv_row TYPE string, + lv_index TYPE sy-tabix, + ls_sheet_content TYPE zexcel_s_cell_data, + range_from TYPE string, + range_to TYPE string, + lv_merge_range TYPE string, + lv_count TYPE string. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + DESCRIBE TABLE sheet_content_merge LINES lv_count. + + WHILE lv_count GT lv_index. +* LOOP AT sheet_content_merge ASSIGNING <fs_sheet_content>. + lv_index = lv_index + 1. + READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX lv_index. + lv_column_start = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). + lv_row = <fs_sheet_content>-cell_row. + SHIFT lv_column_start RIGHT DELETING TRAILING space. + SHIFT lv_column_start LEFT DELETING LEADING space. + SHIFT lv_row RIGHT DELETING TRAILING space. + SHIFT lv_row LEFT DELETING LEADING space. + CONCATENATE lv_column_start lv_row + INTO range_from. + + lv_index = lv_index + 1. + READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX lv_index. + lv_column_end = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). + lv_row = <fs_sheet_content>-cell_row. + SHIFT lv_column_end RIGHT DELETING TRAILING space. + SHIFT lv_column_end LEFT DELETING LEADING space. + SHIFT lv_row RIGHT DELETING TRAILING space. + SHIFT lv_row LEFT DELETING LEADING space. + CONCATENATE lv_column_end lv_row + INTO range_to. + + CONCATENATE range_from range_to INTO lv_merge_range + SEPARATED BY ':'. + APPEND lv_merge_range TO merge_range. + ENDWHILE. +* ENDLOOP. + +* READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX 1. +* IF sy-subrc EQ 0 AND <fs_sheet_content> IS ASSIGNED. +* lv_column_start = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). +* lv_row = <fs_sheet_content>-cell_row. +* SHIFT lv_column_start RIGHT DELETING TRAILING space. +* SHIFT lv_column_start LEFT DELETING LEADING space. +* SHIFT lv_row RIGHT DELETING TRAILING space. +* SHIFT lv_row LEFT DELETING LEADING space. +* CONCATENATE lv_column_start lv_row +* INTO range_from. +* ENDIF. +* READ TABLE sheet_content_merge ASSIGNING <fs_sheet_content> INDEX 2. +* IF sy-subrc EQ 0 AND <fs_sheet_content> IS ASSIGNED. +* lv_column_end = zcl_excel_common=>convert_column2alpha( <fs_sheet_content>-cell_column ). +* SHIFT lv_column_end RIGHT DELETING TRAILING space. +* SHIFT lv_column_end LEFT DELETING LEADING space. +* CONCATENATE lv_column_end lv_row +* INTO range_to. +* ENDIF. + +* IF range_from NE space AND range_to NE space. +* CONCATENATE range_from range_to INTO ep_merge_range +* SEPARATED BY ':'. +* ENDIF. + + endmethod. + + + + method GET_RANGES_ITERATOR. + + eo_iterator = me->ranges->get_iterator( ). + + endmethod. + + + + + method GET_ROW_DIMENSION. + FIELD-SYMBOLS: <fs_row_dimension> LIKE LINE OF row_dimensions. + + READ TABLE me->row_dimensions ASSIGNING <fs_row_dimension> + WITH KEY row = ip_row. + + IF NOT <fs_row_dimension> IS ASSIGNED. + CREATE OBJECT r_row_dimension + EXPORTING + ip_index = ip_row. + APPEND INITIAL LINE TO me->row_dimensions ASSIGNING <fs_row_dimension>. + <fs_row_dimension>-row = ip_row. + <fs_row_dimension>-row_dimension = r_row_dimension. + ELSE. + r_row_dimension = <fs_row_dimension>-row_dimension. + ENDIF. + + endmethod. + + + + method GET_ROW_DIMENSIONS. + r_row_dimension[] = me->row_dimensions[]. + endmethod. + + + + method GET_TABCOLOR. + ev_tabcolor = me->tabcolor. + endmethod. + + + + method GET_TABLES_ITERATOR. + eo_iterator = tables->if_object_collection~get_iterator( ). + endmethod. + + + + method GET_TABLES_SIZE. + ep_size = tables->if_object_collection~size( ). + endmethod. + + + + + method GET_TITLE. + DATA lv_value TYPE string. + IF ip_escaped EQ abap_true. + lv_value = me->title. + ep_title = zcl_excel_common=>escape_string( lv_value ). + ELSE. + ep_title = me->title. + ENDIF. + endmethod. + + + + + + method GET_VALUE_TYPE. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + ls_dfies TYPE dfies, + l_function TYPE funcname, + l_value(50) TYPE c. + + ep_value = ip_value. + ep_value_type = cl_abap_typedescr=>typekind_string. " Thats our default if something goes wrong. + + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ip_value ). + CATCH cx_sy_move_cast_error. + CLEAR lo_addit. + ENDTRY. + IF lo_addit IS BOUND. + lo_addit->get_ddic_field( RECEIVING p_flddescr = ls_dfies + EXCEPTIONS not_found = 1 + no_ddic_type = 2 + OTHERS = 3 ) . + IF sy-subrc = 0. + ep_value_type = ls_dfies-inttype. + + IF ls_dfies-convexit IS NOT INITIAL. +* We need to convert with output conversion function + CONCATENATE 'CONVERSION_EXIT_' ls_dfies-convexit '_OUTPUT' INTO l_function. + SELECT SINGLE funcname INTO l_function + FROM tfdir + WHERE funcname = l_function. + IF sy-subrc = 0. + CALL FUNCTION l_function + EXPORTING + input = ip_value + IMPORTING +* LONG_TEXT = + output = l_value +* SHORT_TEXT = + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ELSE. + ep_value = l_value. + ENDIF. + ENDIF. + ENDIF. + ELSE. + ep_value_type = lo_addit->get_data_type_kind( ip_value ). + ENDIF. + ENDIF. + + endmethod. + + + method PRINT_TITLE_SET_RANGE. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range, + lv_repeat_range_sheetname TYPE string, + lv_repeat_range_col TYPE string, + lv_row_char_from TYPE char10, + lv_row_char_to TYPE char10, + lv_repeat_range_row TYPE string, + lv_repeat_range TYPE string. + + +*--------------------------------------------------------------------* +* Get range that represents printarea +* if non-existant, create it +*--------------------------------------------------------------------* + lo_range_iterator = me->get_ranges_iterator( ). + WHILE lo_range_iterator->has_next( ) = abap_true. + + lo_range ?= lo_range_iterator->get_next( ). + IF lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. + EXIT. " Found it + ENDIF. + CLEAR lo_range. + + ENDWHILE. + + + IF me->print_title_col_from IS INITIAL AND + me->print_title_row_from IS INITIAL. +*--------------------------------------------------------------------* +* No print titles are present, +*--------------------------------------------------------------------* + IF lo_range IS BOUND. + me->ranges->remove( lo_range ). + ENDIF. + ELSE. +*--------------------------------------------------------------------* +* Print titles are present, +*--------------------------------------------------------------------* + IF lo_range IS NOT BOUND. + lo_range = me->add_new_range( ). + lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. + ENDIF. + + lv_repeat_range_sheetname = me->get_title( ). + lv_repeat_range_sheetname = zcl_excel_common=>escape_string( lv_repeat_range_sheetname ). + +*--------------------------------------------------------------------* +* Repeat-columns +*--------------------------------------------------------------------* + IF me->print_title_col_from IS NOT INITIAL. + CONCATENATE lv_repeat_range_sheetname + '!$' me->print_title_col_from + ':$' me->print_title_col_to + INTO lv_repeat_range_col. + ENDIF. + +*--------------------------------------------------------------------* +* Repeat-rows +*--------------------------------------------------------------------* + IF me->print_title_row_from IS NOT INITIAL. + lv_row_char_from = me->print_title_row_from. + lv_row_char_to = me->print_title_row_to. + CONCATENATE '!$' lv_row_char_from + ':$' lv_row_char_to + INTO lv_repeat_range_row. + CONDENSE lv_repeat_range_row NO-GAPS. + CONCATENATE lv_repeat_range_sheetname + lv_repeat_range_row + INTO lv_repeat_range_row. + ENDIF. + +*--------------------------------------------------------------------* +* Concatenate repeat-rows and columns +*--------------------------------------------------------------------* + IF lv_repeat_range_col IS INITIAL. + lv_repeat_range = lv_repeat_range_row. + ELSEIF lv_repeat_range_row IS INITIAL. + lv_repeat_range = lv_repeat_range_col. + ELSE. + CONCATENATE lv_repeat_range_col lv_repeat_range_row + INTO lv_repeat_range SEPARATED BY ','. + ENDIF. + + + lo_range->set_range_value( lv_repeat_range ). + ENDIF. + + + + endmethod. + + + + + + + + + + + + method SET_CELL. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string, + lv_col_alpha TYPE zexcel_cell_column_alpha, + lv_value TYPE zexcel_cell_value, + lv_data_type TYPE zexcel_cell_data_type, + lv_value_type TYPE abap_typekind, + lo_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style, + lo_addit TYPE REF TO cl_abap_elemdescr, + lo_value TYPE REF TO data, + lo_value_new TYPE REF TO data. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data, + <fs_numeric> TYPE numeric, + <fs_date> TYPE d, + <fs_time> TYPE t, + <fs_value> TYPE simple. + + IF ip_value IS NOT SUPPLIED AND ip_formula IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please provide the value or formula'. + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* lv_style_guid = ip_style. + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH TABLE KEY cell_row = ip_row " Changed to access via table key , Stefan Schmöcker, 2013-08-03 + cell_column = lv_column. + IF sy-subrc = 0. + IF ip_style IS INITIAL. + " If no style is provided as method-parameter and cell is found use cell's current style + lv_style_guid = <fs_sheet_content>-cell_style. + ELSE. + " Style provided as method-parameter --> use this + lv_style_guid = ip_style. + ENDIF. + ELSE. + " No cell found --> use supplied style even if empty + lv_style_guid = ip_style. + ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + IF ip_value IS SUPPLIED. + "if data type is passed just write the value. Otherwise map abap type to excel and perform conversion + "IP_DATA_TYPE is passed by excel reader so source types are preserved +*First we get reference into local var. + CREATE DATA lo_value LIKE ip_value. + ASSIGN lo_value->* TO <fs_value>. + <fs_value> = ip_value. + IF ip_data_type IS SUPPLIED. + IF ip_abap_type IS NOT SUPPLIED. + get_value_type( EXPORTING ip_value = ip_value + IMPORTING ep_value = <fs_value> ) . + ENDIF. + lv_value = <fs_value>. + lv_data_type = ip_data_type. + ELSE. + IF ip_abap_type IS SUPPLIED. + lv_value_type = ip_abap_type. + ELSE. + get_value_type( EXPORTING ip_value = ip_value + IMPORTING ep_value = <fs_value> + ep_value_type = lv_value_type ). + ENDIF. + CASE lv_value_type. + WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. + lo_addit = cl_abap_elemdescr=>get_i( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_numeric>. + IF sy-subrc = 0. + <fs_numeric> = <fs_value>. + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). + ENDIF. + + WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. + lo_addit = cl_abap_elemdescr=>get_f( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_numeric>. + IF sy-subrc = 0. + <fs_numeric> = <fs_value>. + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). + ENDIF. + + WHEN cl_abap_typedescr=>typekind_char OR cl_abap_typedescr=>typekind_string OR cl_abap_typedescr=>typekind_num OR + cl_abap_typedescr=>typekind_hex. + lv_value = <fs_value>. + lv_data_type = 's'. + + WHEN cl_abap_typedescr=>typekind_date. + lo_addit = cl_abap_elemdescr=>get_d( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_date>. + IF sy-subrc = 0. + <fs_date> = <fs_value>. + lv_value = zcl_excel_common=>date_to_excel_string( ip_value = <fs_date> ) . + ENDIF. +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Moved to end of routine - apply date-format even if other styleinformation is passed +* IF ip_style IS NOT SUPPLIED. "get default date format in case parameter is initial +* lo_style = excel->add_new_style( ). +* lo_style->number_format->format_code = get_default_excel_date_format( ). +* lv_style_guid = lo_style->get_guid( ). +* ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + WHEN cl_abap_typedescr=>typekind_time. + lo_addit = cl_abap_elemdescr=>get_t( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_time>. + IF sy-subrc = 0. + <fs_time> = <fs_value>. + lv_value = zcl_excel_common=>time_to_excel_string( ip_value = <fs_time> ). + ENDIF. +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Moved to end of routine - apply time-format even if other styleinformation is passed +* IF ip_style IS NOT SUPPLIED. "get default time format for user in case parameter is initial +* lo_style = excel->add_new_style( ). +* lo_style->number_format->format_code = zcl_excel_style_number_format=>c_format_date_time6. +* lv_style_guid = lo_style->get_guid( ). +* ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid data type of input value'. + ENDCASE. + ENDIF. + + ENDIF. + + IF ip_hyperlink IS BOUND. + ip_hyperlink->set_cell_reference( ip_column = ip_column + ip_row = ip_row ). + me->hyperlinks->add( ip_hyperlink ). + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Read table moved up, so that current style may be evaluated +* lv_column = zcl_excel_common=>convert_column2int( ip_column ). + +* READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row +* cell_column = lv_column. +* +* IF sy-subrc EQ 0. + IF <fs_sheet_content> IS ASSIGNED. +* End of change issue #152 - don't touch exisiting style if only value is passed + <fs_sheet_content>-cell_value = lv_value. + <fs_sheet_content>-cell_formula = ip_formula. + <fs_sheet_content>-cell_style = lv_style_guid. + <fs_sheet_content>-data_type = lv_data_type. + ELSE. + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column. + ls_sheet_content-cell_value = lv_value. + ls_sheet_content-cell_formula = ip_formula. + ls_sheet_content-cell_style = lv_style_guid. + ls_sheet_content-data_type = lv_data_type. + lv_row_alpha = ip_row. +* SHIFT lv_row_alpha RIGHT DELETING TRAILING space."del #152 - replaced with condense - should be faster +* SHIFT lv_row_alpha LEFT DELETING LEADING space. "del #152 - replaced with condense - should be faster + CONDENSE lv_row_alpha NO-GAPS. "ins #152 - replaced 2 shifts - should be faster + lv_col_alpha = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column + CONCATENATE lv_col_alpha lv_row_alpha INTO ls_sheet_content-cell_coords. " issue #155 - less restrictive typing for ip_column + INSERT ls_sheet_content INTO TABLE sheet_content ASSIGNING <fs_sheet_content>. "ins #152 - Now <fs_sheet_content> always holds the data +* APPEND ls_sheet_content TO sheet_content. +* SORT sheet_content BY cell_row cell_column. + " me->update_dimension_range( ). + + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* For Date- or Timefields change the formatcode if nothing is set yet +* Enhancement option: Check if existing formatcode is a date/ or timeformat +* If not, use default + DATA: lo_format_code_datetime TYPE zexcel_number_format. + DATA: stylemapping TYPE zexcel_s_stylemapping. + CASE lv_value_type. + WHEN cl_abap_typedescr=>typekind_date. + TRY. + stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). + CATCH zcx_excel . + ENDTRY. + IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR + stylemapping-complete_style-number_format-format_code IS INITIAL. + lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_std. + ELSE. + lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. + ENDIF. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_number_format_format_code = lo_format_code_datetime ). + + WHEN cl_abap_typedescr=>typekind_time. + TRY. + stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). + CATCH zcx_excel . + ENDTRY. + IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR + stylemapping-complete_style-number_format-format_code IS INITIAL. + lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_time6. + ELSE. + lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. + ENDIF. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_number_format_format_code = lo_format_code_datetime ). + + ENDCASE. +* End of change issue #152 - don't touch exisiting style if only value is passed + +* Fix issue #162 + lv_value = ip_value. + IF lv_value CS cl_abap_char_utilities=>cr_lf. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_alignment_wraptext = abap_true ). + ENDIF. +* End of Fix issue #162 + + endmethod. + + + + + + + method SET_CELL_FORMULA. + DATA: + lv_column TYPE zexcel_cell_column, + ls_sheet_content LIKE LINE OF me->sheet_content. + + FIELD-SYMBOLS: + <sheet_content> LIKE LINE OF me->sheet_content. + +*--------------------------------------------------------------------* +* Get cell to set formula into +*--------------------------------------------------------------------* + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + READ TABLE me->sheet_content ASSIGNING <sheet_content> WITH TABLE KEY cell_row = ip_row + cell_column = lv_column. + IF sy-subrc <> 0. " Create new entry in sheet_content if necessary + CHECK ip_formula IS INITIAL. " no need to create new entry in sheet_content when no formula is passed + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column. + INSERT ls_sheet_content INTO TABLE me->sheet_content ASSIGNING <sheet_content>. + ENDIF. + +*--------------------------------------------------------------------* +* Fieldsymbol now holds the relevant cell +*--------------------------------------------------------------------* + <sheet_content>-cell_formula = ip_formula. + + + endmethod. + + + + + + + method SET_CELL_STYLE. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string, + lo_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_style_guid = ip_style. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row + cell_column = lv_column. + + IF sy-subrc EQ 0. + <fs_sheet_content>-cell_style = lv_style_guid. + ELSE. + set_cell( ip_column = ip_column ip_row = ip_row ip_value = '' ip_style = ip_style ). + ENDIF. + + endmethod. + + + + + + + method SET_COLUMN_WIDTH. + DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + DATA: width TYPE float. + + column_dimension = me->get_column_dimension( ip_column ). + +* if a fix size is supplied use this + IF ip_width_fix IS SUPPLIED. + TRY. + width = ip_width_fix. + IF width <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please supply a positive number as column-width'. + ENDIF. + column_dimension->set_width( width ). + EXIT. + CATCH cx_sy_conversion_no_number. +* Strange stuff passed --> raise error + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret supplied input as number'. + ENDTRY. + ENDIF. + +* If we get down to here, we have to use whatever is found in autosize. + column_dimension->set_auto_size( ip_width_autosize ). + + + endmethod. + + + + + method SET_DEFAULT_EXCEL_DATE_FORMAT. + + IF ip_default_excel_date_format IS INITIAL. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Default date format cannot be blank'. + ENDIF. + + default_excel_date_format = ip_default_excel_date_format. + endmethod. + + + + + + + + method SET_MERGE. + + DATA: lv_column_start TYPE zexcel_cell_column, + lv_column_end TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_column_start = zcl_excel_common=>convert_column2int( ip_column_start ). + lv_column_end = zcl_excel_common=>convert_column2int( ip_column_end ). + + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column_start. + lv_row_alpha = ip_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_column_start lv_row_alpha INTO ls_sheet_content-cell_coords. + INSERT ls_sheet_content INTO TABLE sheet_content_merge. + + ls_sheet_content-cell_column = lv_column_end. + IF ip_row_to IS SUPPLIED. + ls_sheet_content-cell_row = ip_row_to. + lv_row_alpha = ip_row_to. + ELSE. + lv_row_alpha = ip_row. + ls_sheet_content-cell_row = ip_row. + ENDIF. + + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE ip_column_end lv_row_alpha INTO ls_sheet_content-cell_coords. + INSERT ls_sheet_content INTO TABLE sheet_content_merge. + + endmethod. + + + + method SET_PRINT_GRIDLINES. + me->print_gridlines = i_print_gridlines. + endmethod. + + + + + + method SET_ROW_HEIGHT. + DATA: row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + DATA: height TYPE float. + + row_dimension = me->get_row_dimension( ip_row ). + +* if a fix size is supplied use this + TRY. + height = ip_height_fix. + IF height <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please supply a positive number as row-height'. + ENDIF. + row_dimension->set_row_height( height ). + EXIT. + CATCH cx_sy_conversion_no_number. +* Strange stuff passed --> raise error + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret supplied input as number'. + ENDTRY. + + + + endmethod. + + + + method SET_SHOW_GRIDLINES. + me->show_gridlines = i_show_gridlines. + endmethod. + + + + method SET_SHOW_ROWCOLHEADERS. + me->show_rowcolheaders = i_show_rowcolheaders. + endmethod. + + + + method SET_TABCOLOR. + me->tabcolor = iv_tabcolor. + endmethod. + + + + + + + + + + + + method SET_TABLE. + + DATA: lo_tabdescr TYPE REF TO cl_abap_structdescr, + lr_data TYPE REF TO data, + ls_newline TYPE REF TO data, + ls_header TYPE x030l, + lt_dfies TYPE ddfields, + lv_row_header TYPE zexcel_cell_row VALUE '2', + lv_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + lv_row_int TYPE zexcel_cell_row, + lv_column_int TYPE zexcel_cell_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lv_cell_value TYPE zexcel_cell_value. + + + FIELD-SYMBOLS: <fs_table_line> TYPE ANY, + <fs_fldval> TYPE ANY, + <fs_dfies> TYPE dfies, + <fs_cell_value> TYPE zexcel_cell_value. + + lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). + lv_row_int = ip_top_left_row. + + CREATE DATA lr_data LIKE LINE OF ip_table. + + lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + ls_header = lo_tabdescr->get_ddic_header( ). + + lt_dfies = lo_tabdescr->get_ddic_field_list( ). + +* It is better to loop column by column + LOOP AT lt_dfies ASSIGNING <fs_dfies>. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + + IF ip_no_header = abap_false. + " First of all write column header + lv_cell_value = <fs_dfies>-scrtext_m. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_cell_value + ip_style = ip_hdr_style ). + IF ip_transpose = abap_true. + ADD 1 TO lv_column_int. + ELSE. + ADD 1 TO lv_row_int. + ENDIF. + ENDIF. + + LOOP AT ip_table ASSIGNING <fs_table_line>. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + ASSIGN COMPONENT <fs_dfies>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. + MOVE <fs_fldval> TO lv_cell_value. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> "lv_cell_value + ip_style = ip_body_style ). + IF ip_transpose = abap_true. + ADD 1 TO lv_column_int. + ELSE. + ADD 1 TO lv_row_int. + ENDIF. + ENDLOOP. + IF ip_transpose = abap_true. + lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). + ADD 1 TO lv_row_int. + ELSE. + lv_row_int = ip_top_left_row. + ADD 1 TO lv_column_int. + ENDIF. + ENDLOOP. + + endmethod. + + + + + method SET_TITLE. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 The current coding for replacing a named ranges name +* after renaming a sheet should be checked if it is +* really working if sheetname should be escaped +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (wip ) 2012-12-08 +* - ... +* changes: aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue#243 - ' is not allowed as first character in sheet title +* - Stefan Schmöcker, 2012-12-02 +* changes: added additional check for ' as first character +*--------------------------------------------------------------------* + DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + errormessage TYPE string, + lv_rangesheetname_old TYPE string, + lv_rangesheetname_new TYPE string, + lo_ranges_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range, + lv_range_value TYPE zexcel_range_value, + lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + + +*--------------------------------------------------------------------* +* Check whether title consists only of allowed characters +* Illegal characters are: / \ [ ] * ? : --> http://msdn.microsoft.com/en-us/library/ff837411.aspx +* Illegal characters not in documentation: ' as first character +*--------------------------------------------------------------------* + IF ip_title CA '/\[]*?:'. + lv_errormessage = 'Found illegal character in sheetname. List of forbidden characters: /\[]*?:'(402). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF ip_title IS NOT INITIAL AND ip_title(1) = `'`. + lv_errormessage = 'Sheetname may not start with &'(403). " & used instead of ' to allow fallbacklanguage + REPLACE '&' IN lv_errormessage WITH `'`. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + +*--------------------------------------------------------------------* +* Check whether title is unique in workbook +*--------------------------------------------------------------------* + lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_worksheets_iterator->has_next( ) = 'X'. + + lo_worksheet ?= lo_worksheets_iterator->get_next( ). + CHECK me->guid <> lo_worksheet->get_guid( ). " Don't check against itself + IF ip_title = lo_worksheet->get_title( ). " Not unique --> raise exception + errormessage = 'Duplicate sheetname &'. + REPLACE '&' IN errormessage WITH ip_title. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = errormessage. + ENDIF. + + ENDWHILE. + +*--------------------------------------------------------------------* +* Remember old sheetname and rename sheet to desired name +*--------------------------------------------------------------------* + CONCATENATE me->title '!' INTO lv_rangesheetname_old. + me->title = ip_title. + +*--------------------------------------------------------------------* +* After changing this worksheet's title we have to adjust +* all ranges that are referring to this worksheet. +*--------------------------------------------------------------------* +* 2do§1 - Check if the following quickfix is solid +* I fear it isn't - but this implementation is better then +* nothing at all since it handles a supposed majority of cases +*--------------------------------------------------------------------* + CONCATENATE me->title '!' INTO lv_rangesheetname_new. + + lo_ranges_iterator = me->excel->get_ranges_iterator( ). + WHILE lo_ranges_iterator->has_next( ) = 'X'. + + lo_range ?= lo_ranges_iterator->get_next( ). + lv_range_value = lo_range->get_value( ). + REPLACE ALL OCCURRENCES OF lv_rangesheetname_old IN lv_range_value WITH lv_rangesheetname_new. + IF sy-subrc = 0. + lo_range->set_range_value( lv_range_value ). + ENDIF. + + ENDWHILE. + + + endmethod. + + + + method UPDATE_DIMENSION_RANGE. + + DATA: ls_sheet_content TYPE zexcel_s_cell_data, + lt_sheet_content TYPE zexcel_t_cell_data_unsorted, + lv_row_alpha TYPE string, + lv_column_alpha TYPE zexcel_cell_column_alpha. + + CHECK sheet_content IS NOT INITIAL. + +* update dimension range + lt_sheet_content = sheet_content. + "upper left corner + SORT lt_sheet_content BY cell_row. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + upper_cell-cell_row = ls_sheet_content-cell_row. + SORT lt_sheet_content BY cell_column. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + upper_cell-cell_column = ls_sheet_content-cell_column. + + lv_row_alpha = upper_cell-cell_row. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( upper_cell-cell_column ). + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_column_alpha lv_row_alpha INTO upper_cell-cell_coords. + + "bottom right corner + SORT lt_sheet_content BY cell_row DESCENDING. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + lower_cell-cell_row = ls_sheet_content-cell_row. + SORT lt_sheet_content BY cell_column DESCENDING. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + lower_cell-cell_column = ls_sheet_content-cell_column. + + lv_row_alpha = lower_cell-cell_row. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lower_cell-cell_column ). + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_column_alpha lv_row_alpha INTO lower_cell-cell_coords. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method ADD. + + worksheets->add( ip_worksheet ). + + endmethod. + + + method CLEAR. + + worksheets->clear( ). + + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT worksheets. + + endmethod. + + + + + method GET. + + DATA lv_index TYPE i. + lv_index = ip_index. + eo_worksheet ?= worksheets->if_object_collection~get( lv_index ). + + endmethod. + + + + method GET_ITERATOR. + + eo_iterator ?= worksheets->if_object_collection~get_iterator( ). + + endmethod. + + + + method IS_EMPTY. + + is_empty = worksheets->if_object_collection~is_empty( ). + + endmethod. + + + + method REMOVE. + + worksheets->remove( ip_worksheet ). + + endmethod. + + + + method SIZE. + + ep_size = worksheets->if_object_collection~size( ). + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + method CONSTRUCTOR. + me->column_index = zcl_excel_common=>convert_column2int( ip_index ). + me->width = -1. + me->auto_size = abap_false. + me->visible = abap_true. + me->outline_level = 0. + me->collapsed = abap_false. + me->excel = ip_excel. "ins issue #157 - Allow Style for columns + me->worksheet = ip_worksheet. "ins issue #157 - Allow Style for columns + + " set default index to cellXf + me->xf_index = 0. + + endmethod. + + + + method GET_AUTO_SIZE. + r_auto_size = me->auto_size. + endmethod. + + + + method GET_COLLAPSED. + r_Collapsed = me->Collapsed. + endmethod. + + + + method GET_COLUMN_INDEX. + r_column_index = me->column_index. + endmethod. + + + + + method GET_COLUMN_STYLE_GUID. + IF me->style_guid IS NOT INITIAL. + ep_style_guid = me->style_guid. + ELSE. + ep_style_guid = me->worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. + endmethod. + + + + method GET_OUTLINE_LEVEL. + r_outline_level = me->outline_level. + endmethod. + + + + method GET_VISIBLE. + r_Visible = me->Visible. + endmethod. + + + + method GET_WIDTH. + r_WIDTH = me->WIDTH. + endmethod. + + + + method GET_XF_INDEX. + r_xf_index = me->xf_index. + endmethod. + + + + + method SET_AUTO_SIZE. + me->auto_size = ip_auto_size. + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLLAPSED. + me->Collapsed = ip_Collapsed. + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLUMN_INDEX. + me->column_index = zcl_excel_common=>convert_column2int( ip_index ). + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLUMN_STYLE_BY_GUID. + DATA: stylemapping TYPE zexcel_s_stylemapping. + + IF me->excel IS NOT BOUND. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Internal error - reference to ZCL_EXCEL not bound'. + ENDIF. + TRY. + stylemapping = me->excel->get_style_to_guid( ip_style_guid ). + me->style_guid = stylemapping-guid. + + CATCH zcx_excel . + EXIT. " leave as is in case of error + ENDTRY. + + endmethod. + + + + method SET_OUTLINE_LEVEL. + me->outline_level = ip_outline_level. + endmethod. + + + + + method SET_VISIBLE. + me->Visible = ip_Visible. + r_worksheet_columndime = me. + endmethod. + + + + + + method SET_WIDTH. + TRY. + me->width = ip_width. + r_worksheet_columndime = me. + CATCH cx_sy_conversion_no_number. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret width as number'. + ENDTRY. + endmethod. + + + + + method SET_XF_INDEX. + me->XF_INDEX = ip_XF_INDEX. + r_worksheet_columndime = me. + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + method CONSTRUCTOR. + " Initialise values + me->row_index = ip_index. + me->row_height = -1. + me->visible = abap_true. + me->outline_level = 0. + me->collapsed = abap_false. + + " set row dimension as unformatted by default + me->xf_index = 0. + endmethod. + + + + method GET_COLLAPSED. + r_collapsed = me->collapsed. + endmethod. + + + + method GET_OUTLINE_LEVEL. + r_outline_level = me->outline_level. + endmethod. + + + + method GET_ROW_HEIGHT. + r_row_height = me->row_height. + endmethod. + + + + method GET_ROW_INDEX. + r_row_index = me->row_index. + endmethod. + + + + method GET_VISIBLE. + r_visible = me->visible. + endmethod. + + + + method GET_XF_INDEX. + r_xf_index = me->xf_index. + endmethod. + + + + method SET_COLLAPSED. + me->collapsed = ip_collapsed. + endmethod. + + + + + method SET_OUTLINE_LEVEL. + IF ip_outline_level < 0 + OR ip_outline_level > 7. + + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Outline level must range between 0 and 7.'. + + ENDIF. + me->outline_level = ip_outline_level. + endmethod. + + + + + method SET_ROW_HEIGHT. + TRY. + me->row_height = ip_row_height. + CATCH cx_sy_conversion_no_number. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret ip_row_height as number'. + ENDTRY. + endmethod. + + + + method SET_ROW_INDEX. + me->row_index = ip_index. + endmethod. + + + + method SET_VISIBLE. + me->visible = ip_visible. + endmethod. + + + + method SET_XF_INDEX. + me->XF_INDEX = ip_XF_INDEX. + endmethod. + + + + + *"* 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. + +* 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. + +********************************************************************** +* STEP 12: 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_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 ). + + " 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_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. + 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 ). + 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 #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 +*--------------------------------------------------------------------* + + +** 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_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, + 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_iconset TYPE zexcel_conditional_iconset, + ls_cellis TYPE zexcel_conditional_cellis, + ls_expression TYPE zexcel_conditional_expression, + lt_cfvo TYPE TABLE OF cfvo, + ls_cfvo TYPE cfvo, + 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, + 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. + +*--------------------------------------------------------------------* +* 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 + 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 + lv_style_index = me->excel->get_style_index_in_styles( lv_style_guid ). "ins issue #237 + IF lv_style_index > 0. "ins issue #237 + lv_value = lv_style_index - 1. "ins issue #237 + 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. + 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 = lv_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 +*--------------------------------------------------------------------* + + LOOP AT io_worksheet->sheet_content ASSIGNING <ls_sheet_content>. + 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. + CLEAR ls_style_mapping. + 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( ) = 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( ) = abap_true OR + row_dimension->get_outline_level( ) > 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( ) = abap_true. + lo_element_2->set_attribute_ns( name = 'collapsed' value = 'true'). + ENDIF. + " Outline level + IF row_dimension->get_outline_level( ) > 0. + lv_value = row_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 = '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. + l_autofilter_hidden = abap_true. " First default is not showing + ENDIF. + + 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 + IF <ls_sheet_content>-data_type IS NOT INITIAL. + lo_element_3->set_attribute_ns( name = lc_xml_attr_t + value = <ls_sheet_content>-data_type ). + 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'. + 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. + + 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_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 + 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 + 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. + +* 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_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( ). + 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. + + +** 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'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element_fonts TYPE REF TO if_ixml_element, + lo_element_font TYPE REF TO if_ixml_element, + lo_element_fills TYPE REF TO if_ixml_element, + lo_element_fill TYPE REF TO if_ixml_element, + lo_element_borders TYPE REF TO if_ixml_element, + lo_element_border TYPE REF TO if_ixml_element, + lo_element_numfmts TYPE REF TO if_ixml_element, + lo_element_numfmt TYPE REF TO if_ixml_element, + lo_element_cellxfs TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_sub_element TYPE REF TO if_ixml_element, + lo_sub_element_2 TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_iterator2 TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_style TYPE REF TO zcl_excel_style. + + + DATA: lt_fonts TYPE zexcel_t_style_font, + ls_font TYPE zexcel_s_style_font, + lt_fills TYPE zexcel_t_style_fill, + ls_fill TYPE zexcel_s_style_fill, + lt_borders TYPE zexcel_t_style_border, + ls_border TYPE zexcel_s_style_border, + lt_numfmts TYPE zexcel_t_style_numfmt, + ls_numfmt TYPE zexcel_s_style_numfmt, + lt_protections TYPE zexcel_t_style_protection, + ls_protection TYPE zexcel_s_style_protection, + lt_alignments TYPE zexcel_t_style_alignment, + ls_alignment TYPE zexcel_s_style_alignment, + lt_cellxfs TYPE zexcel_t_cellxfs, + ls_cellxfs TYPE zexcel_s_cellxfs, + ls_styles_mapping TYPE zexcel_s_styles_mapping, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + ls_cellis TYPE zexcel_conditional_cellis, + ls_expression TYPE zexcel_conditional_expression, + lt_colors TYPE zexcel_t_style_color_argb, + ls_color LIKE LINE OF lt_colors. + + DATA: 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 ). + "pattern + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + lo_element_fill->append_child( new_child = lo_sub_element )."pattern + lo_element_fills->append_child( new_child = lo_element_fill ). + ENDLOOP. + + " create border elements + LOOP AT lt_borders INTO ls_border. + lo_element_border = lo_document->create_simple_element( name = lc_xml_node_border + parent = lo_document ). + + IF ls_border-diagonalup IS NOT INITIAL. + lv_value = ls_border-diagonalup. + CONDENSE lv_value. + lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonalup + value = lv_value ). + ENDIF. + + IF ls_border-diagonaldown IS NOT INITIAL. + lv_value = ls_border-diagonaldown. + CONDENSE lv_value. + lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonaldown + value = lv_value ). + ENDIF. + + "left + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_left + parent = lo_document ). + IF ls_border-left_style IS NOT INITIAL. + lv_value = ls_border-left_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-left_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "right + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_right + parent = lo_document ). + IF ls_border-right_style IS NOT INITIAL. + lv_value = ls_border-right_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-right_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "top + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_top + parent = lo_document ). + IF ls_border-top_style IS NOT INITIAL. + lv_value = ls_border-top_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-top_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "bottom + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_bottom + parent = lo_document ). + IF ls_border-bottom_style IS NOT INITIAL. + lv_value = ls_border-bottom_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-bottom_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "diagonal + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_diagonal + parent = lo_document ). + IF ls_border-diagonal_style IS NOT INITIAL. + lv_value = ls_border-diagonal_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-diagonal_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + lo_element_borders->append_child( new_child = lo_element_border ). + ENDLOOP. + + " update attribute "count" + DESCRIBE TABLE lt_fonts LINES lv_fonts_count. + MOVE lv_fonts_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_fonts->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_fills LINES lv_fills_count. + MOVE lv_fills_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_fills->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_borders LINES lv_borders_count. + MOVE lv_borders_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_borders->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_cellxfs LINES lv_cellxfs_count. + MOVE lv_cellxfs_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_cellxfs->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + + " Append to root node + lo_element_root->append_child( new_child = lo_element_numfmts ). + lo_element_root->append_child( new_child = lo_element_fonts ). + lo_element_root->append_child( new_child = lo_element_fills ). + lo_element_root->append_child( new_child = lo_element_borders ). + + " cellstylexfs node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstylexfs + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '1' ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_xf + parent = lo_document ). + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_numfmtid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_fontid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_fillid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_borderid + value = c_off ). + + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + + LOOP AT lt_cellxfs INTO ls_cellxfs. + lo_element = lo_document->create_simple_element( name = lc_xml_node_xf + parent = lo_document ). + MOVE ls_cellxfs-numfmtid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_numfmtid + value = lv_value ). + MOVE ls_cellxfs-fontid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_fontid + value = lv_value ). + MOVE ls_cellxfs-fillid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_fillid + value = lv_value ). + MOVE ls_cellxfs-borderid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_borderid + value = lv_value ). + MOVE ls_cellxfs-xfid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_xfid + value = lv_value ). + IF ls_cellxfs-applynumberformat EQ 1. + MOVE ls_cellxfs-applynumberformat TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applynumberformat + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyfont EQ 1. + MOVE ls_cellxfs-applyfont TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyfont + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyfill EQ 1. + MOVE ls_cellxfs-applyfill TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyfill + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyborder EQ 1. + MOVE ls_cellxfs-applyborder TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyborder + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyalignment EQ 1. " depends on each style not for all the sheet + MOVE ls_cellxfs-applyalignment TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyalignment + value = lv_value ). + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_alignment + parent = lo_document ). + ADD 1 TO ls_cellxfs-alignmentid. "Table index starts from 1 + READ TABLE lt_alignments INTO ls_alignment INDEX ls_cellxfs-alignmentid. + SUBTRACT 1 FROM ls_cellxfs-alignmentid. + IF ls_alignment-horizontal IS NOT INITIAL. + MOVE ls_alignment-horizontal TO lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_horizontal + value = lv_value ). + ENDIF. + IF ls_alignment-vertical IS NOT INITIAL. + MOVE ls_alignment-vertical TO lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_vertical + value = lv_value ). + ENDIF. + IF ls_alignment-wraptext EQ abap_true. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_wraptext + value = c_on ). + ENDIF. + IF ls_alignment-textrotation IS NOT INITIAL. + MOVE ls_alignment-textrotation TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_textrotation + value = lv_value ). + ENDIF. + IF ls_alignment-shrinktofit EQ abap_true. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_shrinktofit + value = c_on ). + ENDIF. + IF ls_alignment-indent IS NOT INITIAL. + MOVE ls_alignment-indent TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_indent + value = lv_value ). + ENDIF. + + lo_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_cellxfs-applyprotection EQ 1. + MOVE ls_cellxfs-applyprotection TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_applyprotection + value = lv_value ). + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_protection + parent = lo_document ). + ADD 1 TO ls_cellxfs-protectionid. "Table index starts from 1 + READ TABLE lt_protections INTO ls_protection INDEX ls_cellxfs-protectionid. + SUBTRACT 1 FROM ls_cellxfs-protectionid. + IF ls_protection-locked IS NOT INITIAL. + MOVE ls_protection-locked TO lv_value. + CONDENSE lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_locked + value = lv_value ). + ENDIF. + IF ls_protection-hidden IS NOT INITIAL. + MOVE ls_protection-hidden TO lv_value. + CONDENSE lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = lv_value ). + ENDIF. + lo_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + lo_element_cellxfs->append_child( new_child = lo_element ). + ENDLOOP. + + lo_element_root->append_child( new_child = lo_element_cellxfs ). + + " cellStyles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstyles + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '1' ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_cellstyle + parent = lo_document ). + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = 'Normal' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_xfid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_builtinid + value = c_off ). + + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + + " dxfs node + lo_element = lo_document->create_simple_element( name = lc_xml_node_dxfs + parent = lo_document ). + + lo_iterator = me->excel->get_worksheets_iterator( ). + " get sheets + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + " Conditional formatting styles into exch sheet + lo_iterator2 = lo_worksheet->get_cond_styles_iterator( ). + WHILE lo_iterator2->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style_conditional ?= lo_iterator2->if_object_collection_iterator~get_next( ). + CASE lo_style_conditional->rule. + WHEN zcl_excel_style_conditional=>c_rule_cellis. + "if style defined + ls_cellis = lo_style_conditional->mode_cellis. + IF ls_cellis-cell_style IS INITIAL. + CONTINUE. + ENDIF. + READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = ls_cellis-cell_style. + ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 + READ TABLE lt_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. + ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 + + " Style already mapped? + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. + IF sy-subrc EQ 0. + ls_style_cond_mapping-guid = ls_cellis-cell_style. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ELSE. + ls_style_cond_mapping-guid = ls_cellis-cell_style. + ls_style_cond_mapping-style = ls_styles_mapping-style. + ls_style_cond_mapping-dxf = lv_dfx_count. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ADD 1 TO lv_dfx_count. + + " dxf node + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_dxf + parent = lo_document ). + + "Conditional formatting font style correction by Alessandro Iannacci START + lv_index = ls_cellxfs-fontid + 1. + READ TABLE lt_fonts INTO ls_font INDEX lv_index. + IF ls_font IS NOT INITIAL. + lo_element_font = lo_document->create_simple_element( name = lc_xml_node_font + parent = lo_document ). + IF ls_font-bold EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_b + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-italic EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_i + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-underline EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_u + parent = lo_document ). + lv_value = ls_font-underline_mode. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-strikethrough EQ abap_true. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_strike + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + "color + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_element_font + is_color = ls_font-color ). + lo_sub_element->append_child( new_child = lo_element_font ). + ENDIF. + "---Conditional formatting font style correction by Alessandro Iannacci END + + + READ TABLE lt_fills INTO ls_fill INDEX ls_cellxfs-fillid. + IF ls_fill IS NOT INITIAL. + " fill properties + lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill + parent = lo_document ). + "pattern + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern + + lo_sub_element->append_child( new_child = lo_element_fill ). + ENDIF. + ENDIF. + + lo_element->append_child( new_child = lo_sub_element ). + WHEN zcl_excel_style_conditional=>c_rule_expression. + "if style defined + ls_expression = lo_style_conditional->mode_expression. + IF ls_expression-cell_style IS INITIAL. + CONTINUE. + ENDIF. + READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = ls_expression-cell_style. + ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 + READ TABLE lt_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. + ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 + + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. + IF sy-subrc EQ 0. + ls_style_cond_mapping-guid = ls_expression-cell_style. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ELSE. + ls_style_cond_mapping-guid = ls_expression-cell_style. + ls_style_cond_mapping-style = ls_styles_mapping-style. + ls_style_cond_mapping-dxf = lv_dfx_count. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ADD 1 TO lv_dfx_count. + + " dxf node + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_dxf + parent = lo_document ). + + READ TABLE lt_fills INTO ls_fill INDEX ls_cellxfs-fillid. + IF ls_fill IS NOT INITIAL. + " fill properties + lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill + parent = lo_document ). + "pattern + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern + + lo_sub_element->append_child( new_child = lo_element_fill ). + ENDIF. + ENDIF. + + lo_element->append_child( new_child = lo_sub_element ). + WHEN OTHERS. + CONTINUE. + ENDCASE. + ENDWHILE. + ENDWHILE. + + lv_value = lv_dfx_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " tableStyles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_tablestyles + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '0' ). + lo_element->set_attribute_ns( name = lc_xml_attr_defaulttablestyle + value = zcl_excel_table=>builtinstyle_medium9 ). + lo_element->set_attribute_ns( name = lc_xml_attr_defaultpivotstyle + value = zcl_excel_table=>builtinstyle_pivot_light16 ). + lo_element_root->append_child( new_child = lo_element ). + + "write legacy color palette in case any indexed color was changed + IF excel->legacy_palette->is_modified( ) = abap_true. + lo_element = lo_document->create_simple_element( name = lc_xml_node_colors + parent = lo_document ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_indexedcolors + parent = lo_document ). + lo_element->append_child( new_child = lo_sub_element ). + + lt_colors = excel->legacy_palette->get_colors( ). + LOOP AT lt_colors INTO ls_color. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_rgbcolor + parent = lo_document ). + lv_value = ls_color. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_rgb + value = lv_value ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + ENDLOOP. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +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 + 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 ). + + "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( ). + 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 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 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. + + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + +* Signal "not found" +class lcx_not_found implementation. + method constructor. + super->constructor( textid = textid previous = previous ). + me->error = error. + endmethod. + method if_message~get_text. + result = error. + endmethod. +endclass. + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + +* Signal for "Not found" +class lcx_not_found definition inheriting from cx_static_check. + public section. + data error type string. + methods constructor + importing error type string + textid type sotr_conc optional + previous type ref to cx_root optional. + methods if_message~get_text redefinition. +endclass. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes +CLASS lcl_test DEFINITION DEFERRED. +CLASS zcl_excel_reader_huge_file DEFINITION LOCAL FRIENDS lcl_test. + +* +CLASS lcl_test DEFINITION FOR TESTING " #AU Risk_Level Harmless + INHERITING FROM cl_aunit_assert. " #AU Duration Short + + PRIVATE SECTION. + DATA: + out TYPE REF TO zcl_excel_reader_huge_file, " object under test + excel TYPE REF TO zcl_excel, + worksheet TYPE REF TO zcl_excel_worksheet. + METHODS: + setup, + test_number FOR TESTING, + test_shared_string FOR TESTING, + test_shared_string_missing FOR TESTING, + test_inline_string FOR TESTING, + test_boolean FOR TESTING, + test_style FOR TESTING, + test_style_missing FOR TESTING, + test_formula FOR TESTING, + test_read_shared_strings FOR TESTING, + test_skip_to_inexistent FOR TESTING, + get_reader IMPORTING iv_xml TYPE string RETURNING VALUE(eo_reader) TYPE REF TO if_sxml_reader, + assert_value_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_value TYPE string, + assert_formula_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_formula TYPE string, + assert_style_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_style TYPE zexcel_cell_style, + assert_datatype_equals IMPORTING iv_row TYPE i DEFAULT 1 iv_col TYPE i DEFAULT 1 iv_datatype TYPE string. + +ENDCLASS. "lcl_test DEFINITION + +* +CLASS lcl_test IMPLEMENTATION. + +* + METHOD test_number. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="n"><v>17</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `17` ). + assert_datatype_equals( `n` ). + ENDMETHOD. "test_shared_string + +* + METHOD test_shared_string. + DATA lo_reader TYPE REF TO if_sxml_reader. + APPEND `Test` TO out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>0</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Test` ). + assert_datatype_equals( `s` ). + ENDMETHOD. "test_shared_string +* + METHOD test_shared_string_missing. + + DATA: lo_reader TYPE REF TO if_sxml_reader, + lo_ex TYPE REF TO lcx_not_found, + lv_text TYPE string. + lo_reader = get_reader( + `<c r="A1" t="s"><v>0</v></c>` + ). + + TRY. + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + fail(`Index to non-existent shared string should give an error`). + CATCH lcx_not_found INTO lo_ex. + lv_text = lo_ex->get_text( ). " >>> May inspect the message in the debugger + ENDTRY. + + ENDMETHOD. +* + METHOD test_inline_string. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="inlineStr"><is><t>Alpha</t></is></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Alpha` ). + assert_datatype_equals( `inlineStr` ). + ENDMETHOD. "test_inline_string + +* + METHOD test_boolean. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="b"><v>1</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `1` ). + assert_datatype_equals( `b` ). + ENDMETHOD. "test_boolean + +* + METHOD test_formula. + DATA lo_reader TYPE REF TO if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="n"><f>A2*A2</f></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_formula_equals( `A2*A2` ). + assert_datatype_equals( `n` ). + ENDMETHOD. "test_formula + +* + METHOD test_style. + DATA: + lo_reader TYPE REF TO if_sxml_reader, + lo_style TYPE REF TO zcl_excel_style, + lv_guid TYPE zexcel_cell_style. + CREATE OBJECT lo_style. + APPEND lo_style TO out->styles. + lv_guid = lo_style->get_guid( ). + + lo_reader = get_reader( + `<c r="A1" s="0"><v>18</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + + assert_style_equals( lv_guid ). + + ENDMETHOD. "test_style + +* + METHOD test_style_missing. + + DATA: + lo_reader TYPE REF TO if_sxml_reader, + lo_ex TYPE REF TO lcx_not_found, + lv_text TYPE string. + + lo_reader = get_reader( + `<c r="A1" s="0"><v>18</v></c>` + ). + + TRY. + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + fail(`Reference to non-existent style should throw an lcx_not_found exception`). + CATCH lcx_not_found INTO lo_ex. + lv_text = lo_ex->get_text( ). " >>> May inspect the message in the debugger + ENDTRY. + + ENDMETHOD. "test_style + +* + METHOD test_read_shared_strings. + DATA: lo_reader TYPE REF TO if_sxml_reader, + lt_act TYPE stringtab, + lt_exp TYPE stringtab. + lo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( + `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + ) ). + APPEND : + `` TO lt_exp, + `Alpha` TO lt_exp, + `Bravo` TO lt_exp. + + lt_act = out->read_shared_strings( lo_reader ). + + assert_equals( act = lt_act + exp = lt_exp ). + + ENDMETHOD. + +* + METHOD test_skip_to_inexistent. + DATA: lo_reader TYPE REF TO if_sxml_reader, + lo_ex TYPE REF TO lcx_not_found, + lv_text TYPE string. + + lo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( + `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + ) ). + TRY. + out->skip_to( iv_element_name = `nonExistingElement` io_reader = lo_reader ). + fail(`Skipping to non-existing element must raise lcx_not_found exception`). + CATCH lcx_not_found INTO lo_ex. + lv_text = lo_ex->get_text( ). " May inspect exception text in debugger + ENDTRY. + ENDMETHOD. + +* + METHOD get_reader. + DATA: lv_full TYPE string. + CONCATENATE `<root><sheetData><row>` iv_xml `</row></sheetData></root>` INTO lv_full. + eo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( lv_full ) ). + ENDMETHOD. "get_reader +* + METHOD assert_value_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_value + exp = iv_value ). + + ENDMETHOD. "assert_value_equals +** + METHOD assert_formula_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_formula + exp = iv_formula ). + + ENDMETHOD. "assert_formula_equals +* + METHOD assert_style_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_style + exp = iv_style ). + + ENDMETHOD. +* + METHOD assert_datatype_equals. + + FIELD-SYMBOLS: <ls_cell_data> TYPE zexcel_s_cell_data. + + READ TABLE worksheet->sheet_content ASSIGNING <ls_cell_data> + WITH TABLE KEY cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-data_type + exp = iv_datatype ). + + ENDMETHOD. "assert_datatype_equals + METHOD setup. + CREATE OBJECT out. + CREATE OBJECT excel. + CREATE OBJECT worksheet + EXPORTING + ip_excel = excel. + ENDMETHOD. "setup +ENDCLASS. "lcl_test IMPLEMENTATION + + + + + + + + + + + + + + + method FILL_CELL_FROM_ATTRIBUTES. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_attribute( ). + if io_reader->node_type ne c_attribute. + exit. + endif. + case io_reader->name. + when `t`. + es_cell-datatype = io_reader->value. + when `s`. + if io_reader->value is not initial. + es_cell-style = get_style( io_reader->value ). + endif. + when `r`. + es_cell-coord = get_cell_coord( io_reader->value ). + endcase. + endwhile. + + io_reader->current_node( ). + +endmethod. + + + + + method GET_CELL_COORD. + + zcl_excel_common=>convert_columnrow2column_a_row( + exporting + i_columnrow = iv_coord + importing + e_column = es_coord-column + e_row = es_coord-row + ). + +endmethod. + + + + + + method GET_SHARED_STRING. + data: lv_tabix type i. + lv_tabix = iv_index + 1. + read table shared_strings into ev_value index lv_tabix. + if sy-subrc ne 0. + raise exception type lcx_not_found + exporting + error = |Entry { iv_index } not found in Shared String Table|. + endif. +endmethod. + + + + + + method GET_STYLE. + + data: lv_tabix type i, + lo_style type ref to zcl_excel_style. + + if gs_buffer_style-index ne iv_index. + lv_tabix = iv_index + 1. + read table styles into lo_style index lv_tabix. + if sy-subrc ne 0. + raise exception type lcx_not_found + exporting + error = |Entry { iv_index } not found in Style Table|. + else. + gs_buffer_style-index = iv_index. + gs_buffer_style-guid = lo_style->get_guid( ). + endif. + endif. + + ev_style_guid = gs_buffer_style-guid. + +endmethod. + + + + + + method GET_SXML_READER. + + data: lv_xml type xstring. + + lv_xml = get_from_zip_archive( iv_path ). + eo_reader = cl_sxml_string_reader=>create( lv_xml ). + +endmethod. + + + method LOAD_SHARED_STRINGS. + + data: lo_reader type ref to if_sxml_reader. + + lo_reader = get_sxml_reader( ip_path ). + + shared_strings = read_shared_strings( lo_reader ). + +endmethod. + + + method LOAD_WORKSHEET. + + data: lo_reader type ref to if_sxml_reader. + + lo_reader = get_sxml_reader( ip_path ). + + read_worksheet_data( io_reader = lo_reader + io_worksheet = io_worksheet ). + +endmethod. + + + + + method PUT_CELL_TO_WORKSHEET. + call method io_worksheet->set_cell + exporting + ip_column = is_cell-column + ip_row = is_cell-row + ip_value = is_cell-value + ip_formula = is_cell-formula + ip_data_type = is_cell-datatype + ip_style = is_cell-style. +endmethod. + + + + + method READ_SHARED_STRINGS. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + if io_reader->node_type eq c_element_close and + io_reader->name eq `t`. + append io_reader->value to et_shared_strings. + endif. + endwhile. + +endmethod. + + + + + + method READ_WORKSHEET_DATA. + + data: ls_cell type t_cell. + +* Skip to <sheetData> element + skip_to( iv_element_name = `sheetData` io_reader = io_reader ). + +* Main loop: Evaluate the <c> elements and its children + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + case io_reader->node_type. + when c_element_open. + if io_reader->name eq `c`. + ls_cell = fill_cell_from_attributes( io_reader ). + endif. + when c_element_close. + case io_reader->name. + when `c`. + put_cell_to_worksheet( is_cell = ls_cell io_worksheet = io_worksheet ). + when `f`. + ls_cell-formula = io_reader->value. + when `v`. + if ls_cell-datatype eq `s`. + ls_cell-value = get_shared_string( ls_cell-value ). + else. + ls_cell-value = io_reader->value. + endif. + when `is`. + ls_cell-value = io_reader->value. + when `sheetData`. + exit. + endcase. + endcase. + endwhile. + +endmethod. + + + + + + method SKIP_TO. + +* Skip forward to given element + while io_reader->name ne iv_element_name or + io_reader->node_type ne c_element_open. + io_reader->next_node( ). + if io_reader->node_type = c_end_of_stream. + raise exception type lcx_not_found + exporting + error = |XML error: Didn't find element <{ iv_element_name }>|. + endif. + endwhile. + + +endmethod. + + + + + + + *"* 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~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 = 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 +* sp#ƒÂ¤ter hier noch die Worksheets abklappern, welche Styles #ƒÂ#berhaupt noch ben#ƒÂ#tigt werden +* und nur diese dann auch hier zur Verf#ƒÂ#gung stellen +* Da muss ich noch mal nachfragen, ob die beiden ersten Styles, die scheinbar immer mit dem +* EXCEL-Objekt erzeugt werden evtl. immer ben#ƒÂ#tigt werden, egal ob verwendet oder nicht +* Aber als Start fange ich mal an einfach alle static styles der Reihe nach hinzuzuf#ƒÂ#gen + 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 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. + 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_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. + 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 + *"* use this source file for your ABAP unit test classes + + + + + + + + + + + + + + + + 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 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 DESCRIBE_TABLE. + 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. + + + + + 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_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 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 + 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(132) 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. + + WRITE i_value TO l_string. + + CONCATENATE l_string l_func INTO r_text SEPARATED BY space. + + endmethod. + + + + + + method CREATE_WORKSHEET. + DATA: l_freeze_col TYPE i. + DATA: l_guid TYPE oltpguid16. + + IF wo_data IS BOUND AND wo_worksheet IS BOUND. + + wo_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. " By default is on + + IF wt_fieldcatalog IS INITIAL. + set_fieldcatalog( ) . + ELSE. + clean_fieldcatalog( ) . + ENDIF. + + IF i_table = abap_true. + l_freeze_col = bind_table( i_style_table = i_style_table ) . + ELSE. +* Let's check for filter. + IF wt_filter IS NOT INITIAL. + wo_autofilter = wo_excel->add_new_autofilter( io_sheet = wo_worksheet ). + l_freeze_col = bind_cells( ) . + set_autofilter_area( ) . + ELSE. + l_freeze_col = bind_cells( ) . + ENDIF. + + ENDIF. + +* Check for freeze panes + IF ws_layout-is_fixed = abap_true. + IF l_freeze_col = 0. + l_freeze_col = w_col_int. + ENDIF. + wo_worksheet->freeze_panes( EXPORTING ip_num_columns = l_freeze_col + ip_num_rows = w_row_int ) . + ENDIF. + ENDIF. + + endmethod. + + + + + + method EXECUTE_CONVERTER. + DATA: lt_fieldcatalog TYPE zexcel_t_fieldcatalog, + ls_fieldcatalog TYPE zexcel_s_converter_fcat, + lo_if TYPE REF TO zif_excel_converter, + ls_types TYPE ts_alv_types, + lo_addit TYPE REF TO cl_abap_classdescr. + + IF io_object IS BOUND. + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_object_ref( io_object ). + CATCH cx_sy_move_cast_error. + RAISE EXCEPTION TYPE zcx_excel. + ENDTRY. + ls_types-seoclass = lo_addit->get_relative_name( ). + READ TABLE wt_objects INTO ls_types WITH TABLE KEY seoclass = ls_types-seoclass. + IF sy-subrc = 0. + CREATE OBJECT lo_if TYPE (ls_types-clsname). + + TRY. + lo_if->create_fieldcatalog( + EXPORTING + is_option = ws_option + io_object = io_object + it_table = it_table + IMPORTING + es_layout = ws_layout + et_fieldcatalog = wt_fieldcatalog + eo_table = wo_table + et_colors = wt_colors + et_filter = wt_filter + ). + ENDTRY. +* data lines of highest level. + IF ws_layout-max_subtotal_level > 0. + ADD 1 TO ws_layout-max_subtotal_level. + ENDIF. + ELSE. + RAISE EXCEPTION TYPE zcx_excel. + ENDIF. + ELSE. + REFRESH wt_fieldcatalog. + GET REFERENCE OF it_table INTO wo_table. + ENDIF. + + endmethod. + + + + + + + method GET_COLOR_STYLE. + DATA: ls_colors TYPE zexcel_s_converter_col, + ls_color_styles TYPE ts_color_styles, + lo_style TYPE REF TO zcl_excel_style. + + r_style = i_style. " Default we change nothing + + IF wt_colors IS NOT INITIAL. +* Full line has color + READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row + columnname = space. + IF sy-subrc = 0. + READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style + fontcolor = ls_colors-fontcolor + fillcolor = ls_colors-fillcolor. + IF sy-subrc = 0. + r_style = ls_color_styles-style_new->get_guid( ). + ELSE. + lo_style = create_color_style( i_style = i_style + is_colors = ls_colors ) . + r_style = lo_style->get_guid( ) . + ls_color_styles-guid_old = i_style. + ls_color_styles-fontcolor = ls_colors-fontcolor. + ls_color_styles-fillcolor = ls_colors-fillcolor. + ls_color_styles-style_new = lo_style. + INSERT ls_color_styles INTO TABLE wt_color_styles. + ENDIF. + ELSE. +* Only field has color + READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row + columnname = i_fieldname. + IF sy-subrc = 0. + READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style + fontcolor = ls_colors-fontcolor + fillcolor = ls_colors-fillcolor. + IF sy-subrc = 0. + r_style = ls_color_styles-style_new->get_guid( ). + ELSE. + lo_style = create_color_style( i_style = i_style + is_colors = ls_colors ) . + ls_color_styles-guid_old = i_style. + ls_color_styles-fontcolor = ls_colors-fontcolor. + ls_color_styles-fillcolor = ls_colors-fillcolor. + ls_color_styles-style_new = lo_style. + INSERT ls_color_styles INTO TABLE wt_color_styles. + r_style = ls_color_styles-style_new->get_guid( ). + ENDIF. + ELSE. + r_style = i_style. + ENDIF. + ENDIF. + ELSE. + r_style = i_style. + ENDIF. + + endmethod. + + + + + + method GET_FILE. + data: lo_excel_writer type ref to zif_excel_writer, + lo_excel type ref to zcl_excel. + + data: ls_seoclass type seoclass. + + + if wo_excel is bound. + create object lo_excel_writer type zcl_excel_writer_2007. + e_file = lo_excel_writer->write_file( wo_excel ). + + select single * into ls_seoclass + from seoclass + where clsname = 'CL_BCS_CONVERT'. + + if sy-subrc = 0. + call method (ls_seoclass-clsname)=>xstring_to_solix + exporting + iv_xstring = e_file + receiving + et_solix = et_file. + e_bytecount = xstrlen( e_file ). + else. + " Convert to binary + call function 'SCMS_XSTRING_TO_BINARY' + exporting + buffer = e_file + importing + output_length = e_bytecount + tables + binary_tab = et_file. + endif. + endif. + + endmethod. + + + + + method GET_FUNCTION_NUMBER. +*Number Function +*1 AVERAGE +*2 COUNT +*3 COUNTA +*4 MAX +*5 MIN +*6 PRODUCT +*7 STDEV +*8 STDEVP +*9 SUM +*10 VAR +*11 VARP + + case i_totals_function. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_SUM. " Total + r_function_number = 9. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MIN. " Minimum + r_function_number = 5. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MAX. " Maximum + r_function_number = 4. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_AVERAGE. " Mean Value + r_function_number = 1. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_count. " Count + r_function_number = 2. + when others. + clear r_function_number. + endcase. + endmethod. + + + + method GET_OPTION. + + rs_option = ws_option. + + endmethod. + + + + + + + + method GET_STYLE. + DATA: ls_styles TYPE ts_styles, + lo_style TYPE REF TO zcl_excel_style. + + CLEAR r_style. + + READ TABLE wt_styles INTO ls_styles WITH TABLE KEY type = i_type + alignment = i_alignment + inttype = i_inttype + decimals = i_decimals. + IF sy-subrc = 0. + r_style = ls_styles-guid. + ELSE. + CASE i_type. + WHEN c_type_hdr. " Header + lo_style = create_style_hdr( i_alignment = i_alignment ). + WHEN c_type_str. "Stripped + lo_style = create_style_stripped( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_nor. "Normal + lo_style = create_style_normal( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_sub. "Subtotals + lo_style = create_style_subtotal( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_tot. "Totals + lo_style = create_style_total( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + ENDCASE. + IF lo_style IS NOT INITIAL. + r_style = lo_style->get_guid( ). + ls_styles-type = i_type. + ls_styles-alignment = i_alignment. + ls_styles-inttype = i_inttype. + ls_styles-decimals = i_decimals. + ls_styles-guid = r_style. + ls_styles-style = lo_style. + INSERT ls_styles INTO TABLE wt_styles. + ENDIF. + ENDIF. + endmethod. + + + method INIT_OPTION. + + ws_option-filter = abap_true. + ws_option-hidenc = abap_true. + ws_option-subtot = abap_true. + + endmethod. + + + + + + + method LOOP_NORMAL. + DATA: lo_data TYPE REF TO data, + l_row_header TYPE zexcel_cell_row VALUE '2', + l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + l_row_int_start TYPE zexcel_cell_row, + l_row_int_end TYPE zexcel_cell_row, + l_row_int TYPE zexcel_cell_row, + l_col_int TYPE zexcel_cell_column, + l_col_alpha TYPE zexcel_cell_column_alpha, + l_col_alpha_start TYPE zexcel_cell_column_alpha, + l_cell_value TYPE zexcel_cell_value, + l_s_color TYPE abap_bool, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + l_formula TYPE zexcel_cell_formula, + l_style TYPE zexcel_cell_style, + l_cells TYPE i, + l_count TYPE i, + l_table_row TYPE i. + + FIELD-SYMBOLS: <fs_stab> TYPE ANY, + <fs_tab> TYPE STANDARD TABLE, + <fs_sfcat> TYPE zexcel_s_converter_fcat, + <fs_fldval> TYPE ANY, + <fs_cell_value> TYPE zexcel_cell_value. + + ASSIGN wo_data->* TO <fs_tab> . + + DESCRIBE TABLE wt_fieldcatalog LINES l_cells. + DESCRIBE TABLE <fs_tab> LINES l_count. + l_cells = l_cells * l_count. + +* It is better to loop column by column + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + l_row_int = i_row_int. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + +* Freeze panes + IF <fs_sfcat>-fix_column = abap_true. + ADD 1 TO r_freeze_col. + ENDIF. + l_s_color = abap_true. + + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + +* Only if the Header is required create it. + IF ws_option-hidehd IS INITIAL. + " First of all write column header + l_cell_value = <fs_sfcat>-scrtext_m. + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_style = <fs_sfcat>-style_hdr ). + ADD 1 TO l_row_int. + ENDIF. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_table_row = sy-tabix. +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. +* Now let's write the cell values + IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_stripped ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + CLEAR l_s_color. + ELSE. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_normal ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + l_s_color = abap_true. + ENDIF. + READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row + columnname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + wo_worksheet->get_cell( EXPORTING + ip_column = l_col_alpha + ip_row = l_row_int + IMPORTING + ep_value = l_cell_value ). + wo_autofilter->set_value( i_column = l_col_int + i_value = l_cell_value ). + ENDIF. + ADD 1 TO l_row_int. + ENDLOOP. +* Now let's check for optimized + IF <fs_sfcat>-is_optimized = abap_true . + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + ENDIF. +* Now let's check for visible + IF <fs_sfcat>-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + ENDIF. +* Now let's check for total versus subtotal. + IF <fs_sfcat>-totals_function IS NOT INITIAL. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_total( i_row_int = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_total ). + ENDIF. + ENDLOOP. + endmethod. + + + + + + + method LOOP_SUBTOTAL. + + DATA: lo_data TYPE REF TO data, + l_row_header TYPE zexcel_cell_row VALUE '2', + l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + l_row_int_start TYPE zexcel_cell_row, + l_row_int_end TYPE zexcel_cell_row, + l_row_int TYPE zexcel_cell_row, + l_col_int TYPE zexcel_cell_column, + l_col_alpha TYPE zexcel_cell_column_alpha, + l_col_alpha_start TYPE zexcel_cell_column_alpha, + l_cell_value TYPE zexcel_cell_value, + l_s_color TYPE abap_bool, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + l_formula TYPE zexcel_cell_formula, + l_style TYPE zexcel_cell_style, + l_subtotalled TYPE flag, + l_text TYPE string, + ls_sort_values TYPE ts_sort_values, + ls_subtotal_rows TYPE ts_subtotal_rows, + l_sort_level TYPE int4, + l_hidden TYPE int4, + l_line TYPE i, + l_guid TYPE guid_22, + l_tabix TYPE sy-tabix, + l_cells TYPE i, + l_count TYPE i, + l_table_row TYPE i, + lt_fcat TYPE zexcel_t_converter_fcat. + + FIELD-SYMBOLS: <fs_stab> TYPE ANY, + <fs_tab> TYPE STANDARD TABLE, + <fs_sfcat> TYPE zexcel_s_converter_fcat, + <fs_fldval> TYPE ANY, + <fs_sortval> TYPE ANY, + <fs_sortv> TYPE ts_sort_values, + <fs_cell_value> TYPE zexcel_cell_value. + + ASSIGN wo_data->* TO <fs_tab> . + + REFRESH: wt_sort_values, + wt_subtotal_rows. + + DESCRIBE TABLE wt_fieldcatalog LINES l_cells. + DESCRIBE TABLE <fs_tab> LINES l_count. + l_cells = l_cells * l_count. + + READ TABLE <fs_tab> ASSIGNING <fs_stab> INDEX 1. + IF sy-subrc = 0. + l_row_int = i_row_int + 1. + lt_fcat = wt_fieldcatalog. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. + ls_sort_values-fieldname = <fs_sfcat>-columnname. + ls_sort_values-row_int = l_row_int. + ls_sort_values-sort_level = <fs_sfcat>-sort_level. + ls_sort_values-is_collapsed = <fs_sfcat>-is_collapsed. + CREATE DATA ls_sort_values-value LIKE <fs_fldval>. + ASSIGN ls_sort_values-value->* TO <fs_sortval>. + <fs_sortval> = <fs_fldval>. + INSERT ls_sort_values INTO TABLE wt_sort_values. + ENDLOOP. + ENDIF. + l_row_int = i_row_int. +* Let's check if we need to hide a sort level. + DESCRIBE TABLE wt_sort_values LINES l_line. + IF l_line <= 1. + CLEAR l_hidden. + ELSE. + LOOP AT wt_sort_values INTO ls_sort_values WHERE is_collapsed = abap_false. + IF l_hidden < ls_sort_values-sort_level. + l_hidden = ls_sort_values-sort_level. + ENDIF. + ENDLOOP. + ENDIF. + ADD 1 TO l_hidden. " As this is the first level we show. +* First loop without formular only addtional rows with subtotal text. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + ADD 1 TO l_row_int. " 1 is for header row. + l_row_int_start = l_row_int. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. + IF sy-subrc = 0. + READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + ASSIGN <fs_sortv>-value->* TO <fs_sortval>. + IF <fs_sortval> <> <fs_fldval> OR <fs_sortv>-new = abap_true. +* First let's remmember the subtotal values as it has to appear later. + ls_subtotal_rows-row_int = l_row_int. + ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. + ls_subtotal_rows-columnname = <fs_sfcat>-columnname. + INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. +* Now let's write the subtotal line + l_cell_value = create_text_subtotal( i_value = <fs_sortval> + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = <fs_sfcat>-sort_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. +* Now let's change the key + ADD 1 TO l_row_int. + <fs_sortval> = <fs_fldval>. + <fs_sortv>-new = abap_false. + l_line = <fs_sortv>-sort_level. + LOOP AT wt_sort_values ASSIGNING <fs_sortv> WHERE sort_level >= l_line. + <fs_sortv>-row_int = l_row_int. + ENDLOOP. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + ENDLOOP. + ADD 1 TO l_row_int. + l_row_int_start = l_row_int. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + ASSIGN <fs_sortv>-value->* TO <fs_sortval>. + ls_subtotal_rows-row_int = l_row_int. + ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. + ls_subtotal_rows-columnname = <fs_sfcat>-columnname. + INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. +* First let's write the value as it has to appear. + l_cell_value = create_text_subtotal( i_value = <fs_sortval> + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + + l_sort_level = <fs_sfcat>-sort_level. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. + ADD 1 TO l_row_int. + ENDIF. + ENDLOOP. +* Let's write the Grand total + l_sort_level = 0. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . +* lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . Not on grand total + + l_text = create_text_subtotal( i_value = 'Grand'(002) + i_totals_function = <fs_sfcat>-totals_function ). + + l_col_alpha_start = zcl_excel_common=>convert_column2alpha( i_col_int ). + wo_worksheet->set_cell( ip_column = l_col_alpha_start + ip_row = l_row_int + ip_value = l_text + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + +* It is better to loop column by column second time around +* Second loop with formular and data. + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + l_row_int = i_row_int. + l_col_int = i_col_int + <fs_sfcat>-position - 1. +* Freeze panes + IF <fs_sfcat>-fix_column = abap_true. + ADD 1 TO r_freeze_col. + ENDIF. + l_s_color = abap_true. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + " First of all write column header + l_cell_value = <fs_sfcat>-scrtext_m. + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_hdr ). + ADD 1 TO l_row_int. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_table_row = sy-tabix. +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. +* Let's check for subtotal lines + DO. + READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + DO. + READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + l_row_int_start = ls_subtotal_rows-row_int_start. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + ENDIF. + ADD 1 TO l_row_int. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + ADD 1 TO l_row_int. + ENDIF. + ELSE. + EXIT. + ENDIF. + ENDDO. +* Let's set the row dimension values + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = ws_layout-max_subtotal_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim->set_visible( ip_visible = abap_false ) . + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. +* Now let's write the cell values + IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_stripped ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + CLEAR l_s_color. + ELSE. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_normal ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + l_s_color = abap_true. + ENDIF. + READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row + columnname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + wo_worksheet->get_cell( EXPORTING + ip_column = l_col_alpha + ip_row = l_row_int + IMPORTING + ep_value = l_cell_value ). + wo_autofilter->set_value( i_column = l_col_int + i_value = l_cell_value ). + ENDIF. + ADD 1 TO l_row_int. + ENDLOOP. +* Let's check for subtotal lines + DO. + READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + DO. + READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + l_row_int_start = ls_subtotal_rows-row_int_start. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). + ENDIF. + ADD 1 TO l_row_int. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + ADD 1 TO l_row_int. + ENDIF. + ELSE. + EXIT. + ENDIF. + ENDDO. +* Now let's check for Grand total + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + l_row_int_start = i_row_int + 1. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + ENDIF. +* Now let's check for optimized + IF <fs_sfcat>-is_optimized = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + ENDIF. +* Now let's check for visible + IF <fs_sfcat>-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + ENDLOOP. + + endmethod. + + + method OPEN_FILE. + data: l_bytecount type i, + lt_file type solix_tab, + l_dir type string, + l_sep type c. + + field-symbols: <fs_data> type any table. + + assign wo_data->* to <fs_data>. + +* catch zcx_excel . +*endtry. + if wo_excel is bound. + get_file( importing e_bytecount = l_bytecount + et_file = lt_file ) . + + l_dir = create_path( ) . + + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_dir + filetype = 'BIN' + changing data_tab = lt_file ). + cl_gui_frontend_services=>execute( + exporting + document = l_dir +* application = +* parameter = +* default_directory = +* maximized = +* minimized = +* synchronous = +* operation = 'OPEN' + exceptions + cntl_error = 1 + error_no_gui = 2 + bad_parameter = 3 + file_not_found = 4 + path_not_found = 5 + file_extension_unknown = 6 + error_execute_failed = 7 + synchronous_failed = 8 + not_supported_by_gui = 9 + ). + if sy-subrc <> 0. + message id sy-msgid type sy-msgty number sy-msgno + with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + endif. + + endif. + + + endmethod. + + + method SET_AUTOFILTER_AREA. + DATA: ls_area TYPE zexcel_s_autofilter_area, + l_lines TYPE i, + lt_values TYPE zexcel_t_autofilter_values, + ls_values TYPE zexcel_s_autofilter_values. + +* Let's check for filter. + IF wo_autofilter IS BOUND. + ls_area-row_start = 1. + lt_values = wo_autofilter->get_values( ) . + SORT lt_values BY column ASCENDING. + DESCRIBE TABLE lt_values LINES l_lines. + READ TABLE lt_values INTO ls_values INDEX 1. + IF sy-subrc = 0. + ls_area-col_start = ls_values-column. + ENDIF. + READ TABLE lt_values INTO ls_values INDEX l_lines. + IF sy-subrc = 0. + ls_area-col_end = ls_values-column. + ENDIF. + wo_autofilter->set_filter_area( is_area = ls_area ) . + ENDIF. + + endmethod. + + + + + + method SET_CELL_FORMAT. + DATA: l_format TYPE zexcel_number_format. + + CLEAR r_format. + CASE i_inttype. + WHEN cl_abap_typedescr=>typekind_date. + r_format = wo_worksheet->get_default_excel_date_format( ). + WHEN cl_abap_typedescr=>typekind_time. + r_format = wo_worksheet->get_default_excel_time_format( ). + WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. + IF i_decimals > 0 . + l_format = '#,##0.'. + DO i_decimals TIMES. + CONCATENATE l_format '0' INTO l_format. + ENDDO. + r_format = l_format. + ENDIF. + WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. + r_format = '#,##0'. + ENDCASE. + + endmethod. + + + method SET_FIELDCATALOG. + + DATA: lr_data TYPE REF TO data, + lo_structdescr TYPE REF TO cl_abap_structdescr, + lt_dfies TYPE ddfields, + ls_dfies TYPE dfies, + ls_fieldcatalog TYPE zexcel_s_fieldcatalog. + DATA: ls_fcat TYPE zexcel_s_converter_fcat. + + FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. + + ASSIGN wo_data->* TO <fs_tab> . + + CREATE DATA lr_data LIKE LINE OF <fs_tab>. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + + LOOP AT lt_dfies INTO ls_dfies. + MOVE-CORRESPONDING ls_dfies TO ls_fcat. + ls_fcat-columnname = ls_dfies-fieldname. + INSERT ls_fcat INTO TABLE wt_fieldcatalog. + ENDLOOP. + + clean_fieldcatalog( ). + + endmethod. + + + + method SET_OPTION. + + IF ws_indx-begdt IS INITIAL. + ws_indx-begdt = sy-datum. + ENDIF. + + ws_indx-aedat = sy-datum. + ws_indx-usera = sy-uname. + ws_indx-pgmid = sy-cprog. + + EXPORT p1 = is_option TO DATABASE indx(xl) FROM ws_indx ID ws_indx-srtfd. + + IF sy-subrc = 0. + ws_option = is_option. + ENDIF. + + endmethod. + + + + method WRITE_FILE. + data: l_bytecount type i, + lt_file type solix_tab, + l_dir type string. + + field-symbols: <fs_data> type any table. + + assign wo_data->* to <fs_data>. + +* catch zcx_excel . +*endtry. + if wo_excel is bound. + get_file( importing e_bytecount = l_bytecount + et_file = lt_file ) . + if i_path is initial. + l_dir = create_path( ) . + else. + l_dir = i_path. + endif. + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_dir + filetype = 'BIN' + changing data_tab = lt_file ). + endif. + endmethod. + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature +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. + + break rturnheim. + + IF lo_result IS BOUND. + lo_data = get_table( io_object = lo_result->r_model->r_data ). + IF lo_data IS BOUND. + ASSIGN lo_data->* TO <fs_table> . + + wo_config ?= lo_result->r_model->r_model. + + IF wo_config IS BOUND. + wt_fields = wo_config->if_salv_wd_field_settings~get_fields( ) . + wt_columns = wo_config->if_salv_wd_column_settings~get_columns( ) . + ENDIF. + + create_wt_fcat( io_table = lo_data ). + create_wt_sort( ). + create_wt_filt( ). + + apply_sort( EXPORTING it_table = <fs_table> + IMPORTING eo_table = eo_table ) . + +* get_color( EXPORTING io_table = eo_table +* IMPORTING et_colors = et_colors ) . + + get_filter( IMPORTING et_filter = et_filter + CHANGING xo_table = eo_table ) . + + update_catalog( CHANGING cs_layout = es_layout + ct_fieldcatalog = et_fieldcatalog ). + ELSE. +* We have a problem and should stop here + ENDIF. + ENDIF. +ENDMETHOD. + + + + method CREATE_WT_FCAT. + DATA: lr_data TYPE REF TO data, + lo_structdescr TYPE REF TO cl_abap_structdescr, + lt_dfies TYPE ddfields, + ls_dfies TYPE dfies, + lv_sytabix TYPE sytabix. + + DATA: ls_fcat TYPE lvc_s_fcat. + + FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. + + ASSIGN io_table->* TO <fs_tab> . + CREATE DATA lr_data LIKE LINE OF <fs_tab>. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + + loop at lt_dfies into ls_dfies. + MOVE-CORRESPONDING ls_dfies TO ls_fcat. +* ls_fcat-columnname = ls_dfies-fieldname. + ls_fcat-col_pos = ls_dfies-position. + ls_fcat-key = ls_dfies-keyflag. + get_fields_info( CHANGING xs_fcat = ls_fcat ) . + + ls_fcat-col_opt = abap_true. + + get_columns_info( CHANGING xs_fcat = ls_fcat ) . + + INSERT ls_fcat INTO TABLE wt_fcat. + endloop. + + endmethod. + + + method CREATE_WT_FILT. +* No neeed for superclass. +* Only for WD + DATA: lt_otab TYPE abap_sortorder_tab, + ls_otab TYPE abap_sortorder. + DATA: lt_filters TYPE salv_wd_t_filter_rule_ref, + ls_filt TYPE lvc_s_filt. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref, + <fs_filter> TYPE salv_wd_s_filter_rule_ref. + + LOOP AT wt_fields ASSIGNING <fs_fields>. + REFRESH lt_filters. + lt_filters = <fs_fields>-r_field->if_salv_wd_filter~get_filter_rules( ) . + LOOP AT lt_filters ASSIGNING <fs_filter>. + ls_filt-fieldname = <fs_fields>-fieldname. + IF <fs_filter>-r_filter_rule->get_included( ) = abap_true. + ls_filt-sign = 'I'. + ELSE. + ls_filt-sign = 'E'. + ENDIF. + ls_filt-option = <fs_filter>-r_filter_rule->get_operator( ). + ls_filt-high = <fs_filter>-r_filter_rule->get_high_value( ) . + ls_filt-low = <fs_filter>-r_filter_rule->get_low_value( ) . + INSERT ls_filt INTO TABLE wt_filt. + ENDLOOP. + ENDLOOP. + + endmethod. + + + method CREATE_WT_SORT. + DATA: lo_sort TYPE REF TO cl_salv_wd_sort_rule, + l_sort_order TYPE salv_wd_constant, + ls_sort TYPE lvc_s_sort. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. + + LOOP AT wt_fields ASSIGNING <fs_fields>. + lo_sort = <fs_fields>-r_field->if_salv_wd_sort~get_sort_rule( ) . + IF lo_sort IS BOUND. + l_sort_order = lo_sort->get_sort_order( ). + IF l_sort_order <> if_salv_wd_c_sort=>sort_order. + CLEAR ls_sort. + ls_sort-spos = lo_sort->get_sort_position( ). + ls_sort-fieldname = <fs_fields>-fieldname. +* ls_sort-GROUP + ls_sort-subtot = lo_sort->get_group_aggregation( ). +* ls_sort-COMP +* ls_sort-EXPA +* ls_sort-SELTEXT +* ls_sort-OBLIGATORY +* ls_sort-LEVEL +* ls_sort-NO_OUT + IF l_sort_order = if_salv_wd_c_sort=>sort_order_ascending. + ls_sort-up = abap_true. + ELSE. + ls_sort-down = abap_true. + ENDIF. + INSERT ls_sort INTO TABLE wt_sort. + ENDIF. + ENDIF. + ENDLOOP. + + endmethod. + + + + method GET_COLUMNS_INFO. + DATA: l_numc2 TYPE salv_wd_constant. + + + FIELD-SYMBOLS: <fs_column> TYPE salv_wd_s_column_ref. + + READ TABLE wt_columns ASSIGNING <fs_column> WITH KEY id = xs_fcat-fieldname . + IF sy-subrc = 0. + xs_fcat-col_pos = <fs_column>-r_column->get_position( ) . + l_numc2 = <fs_column>-r_column->get_fixed_position( ). + IF l_numc2 = '02'. + xs_fcat-fix_column = abap_true . + ENDIF. + l_numc2 = <fs_column>-r_column->get_visible( ). + IF l_numc2 = '01'. + xs_fcat-no_out = abap_true . + ENDIF. + ENDIF. + + endmethod. + + + + method GET_FIELDS_INFO. + DATA: lo_aggr TYPE REF TO cl_salv_wd_aggr_rule, + l_aggrtype TYPE salv_wd_constant. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. + + READ TABLE wt_fields ASSIGNING <fs_fields> WITH KEY fieldname = xs_fcat-fieldname. + IF sy-subrc = 0. + lo_aggr = <fs_fields>-r_field->if_salv_wd_aggr~get_aggr_rule( ) . + IF lo_aggr IS BOUND. + l_aggrtype = lo_aggr->get_aggregation_type( ) . + CASE l_aggrtype. + WHEN if_salv_wd_c_aggregation=>aggrtype_total. + xs_fcat-do_sum = abap_true. + WHEN if_salv_wd_c_aggregation=>aggrtype_minimum. + xs_fcat-do_sum = 'A'. + WHEN if_salv_wd_c_aggregation=>aggrtype_maximum . + xs_fcat-do_sum = 'B'. + WHEN if_salv_wd_c_aggregation=>aggrtype_average . + xs_fcat-do_sum = 'C'. + WHEN OTHERS. + CLEAR xs_fcat-do_sum . + ENDCASE. + ENDIF. + ENDIF. + + endmethod. + + + + *"* 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' + IMPORTING + ev_guid_16 = me->guid. + + IF ip_title IS NOT INITIAL. + title = ip_title. + ELSE. + title = me->guid. + ENDIF. + + me->type = ip_type. + +* inizialize dimension range + anchor = anchor_one_cell. + from_loc-col = 1. + from_loc-row = 1. + endmethod. + + + + method CREATE_MEDIA_NAME. + +* if media name is initial, create unique name + CHECK media_name IS INITIAL. + + index = ip_index. + CONCATENATE me->type index INTO media_name. + CONDENSE media_name NO-GAPS. + endmethod. + + + + method GET_FROM_COL. + r_from_col = me->from_loc-col. + endmethod. + + + + method GET_FROM_ROW. + r_from_row = me->from_loc-row. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + method GET_HEIGHT_EMU_STR. + r_height = pixel2emu( size-height ). + CONDENSE r_height NO-GAPS. + endmethod. + + + + method GET_INDEX. + rp_index = me->index. + endmethod. + + + + method GET_MEDIA. + CASE media_source. + WHEN c_media_source_xstring. + r_media = media. + WHEN c_media_source_www. + DATA: lt_mime TYPE tsfmime, + lv_filesize TYPE i, + lv_filesizec(10). + + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = media_key_www + TABLES + mime = lt_mime + EXCEPTIONS + OTHERS = 1. + + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = media_key_www-relid + objid = media_key_www-objid + name = 'filesize' + IMPORTING + value = lv_filesizec. + + lv_filesize = lv_filesizec. + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filesize + IMPORTING + buffer = r_media + TABLES + binary_tab = lt_mime + EXCEPTIONS + failed = 1 + OTHERS = 2. + WHEN c_media_source_mime. + DATA: lt_bin_mime TYPE sdokcntbins. + cl_wb_mime_repository=>load_mime( EXPORTING + io = me->io + IMPORTING + filesize = lv_filesize + bin_data = lt_bin_mime + CHANGING + language = sy-langu ). + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filesize + IMPORTING + buffer = r_media + TABLES + binary_tab = lt_bin_mime + EXCEPTIONS + failed = 1 + OTHERS = 2. + ENDCASE. + endmethod. + + + + method GET_MEDIA_NAME. + CONCATENATE media_name `.` media_type INTO r_name. + endmethod. + + + + method GET_MEDIA_TYPE. + r_type = media_type. + endmethod. + + + + method GET_NAME. + r_name = title. + endmethod. + + + + method GET_POSITION. + rp_position-anchor = anchor. + rp_position-from = from_loc. + rp_position-to = to_loc. + rp_position-size = size. + endmethod. + + + + method GET_TO_COL. + r_to_col = me->to_loc-col. + endmethod. + + + + method GET_TO_ROW. + r_to_row = me->to_loc-row. + endmethod. + + + + method GET_TYPE. + rp_type = me->type. + endmethod. + + + + method GET_WIDTH_EMU_STR. + r_width = pixel2emu( size-width ). + CONDENSE r_width NO-GAPS. + endmethod. + + + + method LOAD_CHART_ATTRIBUTES. + DATA: node TYPE REF TO if_ixml_element. + DATA: node2 TYPE REF TO if_ixml_element. + DATA: node3 TYPE REF TO if_ixml_element. + DATA: node4 TYPE REF TO if_ixml_element. + DATA: iterator TYPE REF TO if_ixml_node_iterator. + + DATA: chartspace TYPE REF TO if_ixml_node_collection. + DATA: coll_length TYPE i. + DATA: chartelem TYPE REF TO if_ixml_element. + + DATA lo_barchart TYPE REF TO zcl_excel_graph_bars. + DATA lo_piechart TYPE REF TO zcl_excel_graph_pie. + DATA lo_linechart TYPE REF TO zcl_excel_graph_line. + + TYPES: BEGIN OF t_prop, + val TYPE string, + rtl TYPE string, + lang TYPE string, + formatcode TYPE string, + sourcelinked TYPE string, + END OF t_prop. + + TYPES: BEGIN OF t_pagemargins, + b TYPE string, + l TYPE string, + r TYPE string, + t TYPE string, + header TYPE string, + footer TYPE string, + END OF t_pagemargins. + + DATA ls_prop TYPE t_prop. + DATA ls_pagemargins TYPE t_pagemargins. + + DATA lo_collection TYPE REF TO if_ixml_node_collection. + DATA lo_node TYPE REF TO if_ixml_node. + DATA lo_iterator TYPE REF TO if_ixml_node_iterator. + DATA lv_idx TYPE i. + DATA lv_order TYPE i. + DATA lv_invertifnegative TYPE string. + DATA lv_symbol TYPE string. + DATA lv_smooth TYPE c. + DATA lv_sername TYPE string. + DATA lv_label TYPE string. + DATA lv_value TYPE string. + DATA lv_axid TYPE string. + DATA lv_orientation TYPE string. + DATA lv_delete TYPE string. + DATA lv_axpos TYPE string. + DATA lv_formatcode TYPE string. + DATA lv_sourcelinked TYPE string. + DATA lv_majortickmark TYPE string. + DATA lv_minortickmark TYPE string. + DATA lv_ticklblpos TYPE string. + DATA lv_crossax TYPE string. + DATA lv_crosses TYPE string. + DATA lv_auto TYPE string. + DATA lv_lblalgn TYPE string. + DATA lv_lbloffset TYPE string. + DATA lv_nomultilvllbl TYPE string. + DATA lv_crossbetween TYPE string. + + node ?= ip_chart->if_ixml_node~get_first_child( ). + CHECK node IS NOT INITIAL. + + CASE me->graph_type. + WHEN c_graph_bars. + CREATE OBJECT lo_barchart. + me->graph = lo_barchart. + WHEN c_graph_pie. + CREATE OBJECT lo_piechart. + me->graph = lo_piechart. + WHEN c_graph_line. + CREATE OBJECT lo_linechart. + me->graph = lo_linechart. + WHEN OTHERS. + ENDCASE. + + "Fill properties + node2 ?= node->find_from_name( name = 'date1904' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_1904val = ls_prop-val. + node2 ?= node->find_from_name( name = 'lang' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_langval = ls_prop-val. + node2 ?= node->find_from_name( name = 'roundedCorners' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_roundedcornersval = ls_prop-val. + + "style + node2 ?= node->find_from_name( name = 'style' namespace = 'c14' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_c14styleval = ls_prop-val. + node2 ?= node->find_from_name( name = 'style' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_styleval = ls_prop-val. + "---------------------------Read graph properties + node2 ?= node->find_from_name( name = 'autoTitleDeleted' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_autotitledeletedval = ls_prop-val. + + "plotArea + CASE me->graph_type. + WHEN c_graph_bars. + node2 ?= node->find_from_name( name = 'barDir' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_bardirval = ls_prop-val. + node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_groupingval = ls_prop-val. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'invertIfNegative' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_invertifnegative = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_barchart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_invertifnegative = lv_invertifnegative + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showbubblesizeval = ls_prop-val. + node2 ?= node->find_from_name( name = 'gapWidth' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_gapwidthval = ls_prop-val. + + "Load axes + node2 ?= node->find_from_name( name = 'barChart' namespace = 'c' ). + CALL METHOD node2->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'axId' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lv_axid = ls_prop-val. + IF sy-index EQ 1. "catAx + node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_auto = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lblalgn = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lbloffset = ls_prop-val. + node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_nomultilvllbl = ls_prop-val. + CALL METHOD lo_barchart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_bars=>c_catax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_auto = lv_auto + ip_lblalgn = lv_lblalgn + ip_lbloffset = lv_lbloffset + ip_nomultilvllbl = lv_nomultilvllbl. + ELSEIF sy-index EQ 2. "valAx + node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossbetween = ls_prop-val. + CALL METHOD lo_barchart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_bars=>c_valax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_crossbetween = lv_crossbetween. + ENDIF. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + + WHEN c_graph_pie. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_piechart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showbubblesizeval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showLeaderLines' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showleaderlinesval = ls_prop-val. + node2 ?= node->find_from_name( name = 'firstSliceAng' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_firstsliceangval = ls_prop-val. + WHEN c_graph_line. + node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_groupingval = ls_prop-val. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'symbol' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_symbol = ls_prop-val. + node3 ?= node2->find_from_name( name = 'smooth' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_smooth = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_linechart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_symbol = lv_symbol + ip_smooth = lv_smooth + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showbubblesizeval = ls_prop-val. + + node ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). + node2 ?= node->find_from_name( name = 'marker' namespace = 'c' DEPTH = '1' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->NS_MARKERVAL = ls_prop-val. + node2 ?= node->find_from_name( name = 'smooth' namespace = 'c' DEPTH = '1' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->NS_SMOOTHVAL = ls_prop-val. + node ?= ip_chart->if_ixml_node~get_first_child( ). + CHECK node IS NOT INITIAL. + + "Load axes + node2 ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). + CALL METHOD node2->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'axId' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lv_axid = ls_prop-val. + IF sy-index EQ 1. "catAx + node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. +* node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). +* zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). +* lv_formatcode = ls_prop-formatcode. +* lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_auto = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lblalgn = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lbloffset = ls_prop-val. + node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_nomultilvllbl = ls_prop-val. + CALL METHOD lo_linechart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_line=>c_catax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_auto = lv_auto + ip_lblalgn = lv_lblalgn + ip_lbloffset = lv_lbloffset + ip_nomultilvllbl = lv_nomultilvllbl. + ELSEIF sy-index EQ 2. "valAx + node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossbetween = ls_prop-val. + CALL METHOD lo_linechart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_line=>c_valax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_crossbetween = lv_crossbetween. + ENDIF. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + WHEN OTHERS. + ENDCASE. + + "legend + CASE me->graph_type. + WHEN c_graph_bars. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_overlayval = ls_prop-val. + WHEN c_graph_line. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_overlayval = ls_prop-val. + WHEN c_graph_pie. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_overlayval = ls_prop-val. + node2 ?= node->find_from_name( name = 'pPr' namespace = 'a' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_pprrtl = ls_prop-rtl. + node2 ?= node->find_from_name( name = 'endParaRPr' namespace = 'a' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_endpararprlang = ls_prop-lang. + + WHEN OTHERS. + ENDCASE. + + node2 ?= node->find_from_name( name = 'plotVisOnly' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_plotvisonlyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'dispBlanksAs' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_dispblanksasval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showDLblsOverMax' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_showdlblsovermaxval = ls_prop-val. + "--------------------- + + node2 ?= node->find_from_name( name = 'pageMargins' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_pagemargins ). + me->graph->pagemargins = ls_pagemargins. + + + endmethod. + + + + + + method PIXEL2EMU. +* suppose 96 DPI + IF ip_dpi IS SUPPLIED. + r_emu = ip_pixel * 914400 / ip_dpi. + ELSE. +* suppose 96 DPI + r_emu = ip_pixel * 914400 / 96. + ENDIF. + endmethod. + + + + + + + method SET_MEDIA. + IF ip_media IS SUPPLIED. + media = ip_media. + ENDIF. + media_type = ip_media_type. + media_source = c_media_source_xstring. + IF ip_width IS SUPPLIED. + size-width = ip_width. + ENDIF. + IF ip_height IS SUPPLIED. + size-height = ip_height. + ENDIF. + endmethod. + + + + + + method SET_MEDIA_MIME. + + io = ip_io. + media_source = c_media_source_mime. + size-width = ip_width. + size-height = ip_height. + + cl_wb_mime_repository=>load_mime( EXPORTING + io = ip_io + IMPORTING + filename = media_name + "mimetype = media_type + CHANGING + language = sy-langu ). + + SPLIT media_name AT '.' INTO media_name media_type. + + + + endmethod. + + + + + + method SET_MEDIA_WWW. + DATA: lv_value(20). + + media_key_www = ip_key. + media_source = c_media_source_www. + + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = media_key_www-relid + objid = media_key_www-objid + name = 'fileextension' + IMPORTING + value = lv_value. + media_type = lv_value. + SHIFT media_type LEFT DELETING LEADING '.'. + + size-width = ip_width. + size-height = ip_height. + endmethod. + + + + + + + method SET_POSITION. + from_loc-col = zcl_excel_common=>convert_column2int( ip_from_col ) - 1. + IF ip_coloff IS SUPPLIED. + from_loc-col_offset = ip_coloff. + ENDIF. + from_loc-row = ip_from_row - 1. + IF ip_rowoff IS SUPPLIED. + from_loc-row_offset = ip_rowoff. + ENDIF. + anchor = anchor_one_cell. + endmethod. + + + + + + method SET_POSITION2. + + data: lv_anchor type zexcel_drawing_anchor. + lv_anchor = ip_anchor. + + IF lv_anchor IS INITIAL. + IF ip_to IS NOT INITIAL. + lv_anchor = anchor_two_cell. + ELSE. + lv_anchor = anchor_one_cell. + ENDIF. + ENDIF. + + CASE lv_anchor. + WHEN anchor_absolute OR anchor_one_cell. + CLEAR: me->to_loc. + WHEN anchor_two_cell. + CLEAR: me->size. + ENDCASE. + + me->from_loc = ip_from. + me->to_loc = ip_to. + me->anchor = lv_anchor. + + endmethod. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + method ADD. + DATA: lv_index TYPE i. + + drawings->add( ip_drawing ). + lv_index = drawings->if_object_collection~size( ). + ip_drawing->create_media_name( + ip_index = lv_index ). + endmethod. + + + method CLEAR. + + drawings->clear( ). + endmethod. + + + + method CONSTRUCTOR. + + CREATE OBJECT drawings. + type = ip_type. + + endmethod. + + + + + method GET. + + DATA lv_index TYPE i. + lv_index = ip_index. + eo_drawing ?= drawings->if_object_collection~get( lv_index ). + endmethod. + + + + method GET_ITERATOR. + + eo_iterator ?= drawings->if_object_collection~get_iterator( ). + endmethod. + + + + method GET_TYPE. + rp_type = me->type. + endmethod. + + + + method INCLUDE. + drawings->add( ip_drawing ). + endmethod. + + + + method IS_EMPTY. + + is_empty = drawings->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + + drawings->remove( ip_drawing ). + endmethod. + + + + method SIZE. + + ep_size = drawings->if_object_collection~size( ). + endmethod. + + + + + + + + *"* 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. + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method CONSTRUCTOR. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + method GET_VALUE. + + ep_value = me->value. + + endmethod. + + + + method SET_RANGE_VALUE. + me->value = ip_value. + endmethod. + + + + + + + + method SET_VALUE. + DATA: lv_start_row_c TYPE char7, + lv_stop_row_c TYPE char7, + lv_value TYPE string. + lv_stop_row_c = ip_stop_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_start_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + lv_value = ip_sheet_name. + me->value = zcl_excel_common=>escape_string( ip_value = lv_value ). + + CONCATENATE me->value '!$' ip_start_column '$' lv_start_row_c ':$' ip_stop_column '$' lv_stop_row_c INTO me->value. + endmethod. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& 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. + + 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. + +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 = '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_c TYPE REF TO zcl_excel_style, + style_column_c_guid TYPE zexcel_cell_style. + +CONSTANTS: gc_save_file_name TYPE string VALUE '31_AutosizeWithDifferentFontSizes.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + + 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 ). + + + + +*** 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' ). + ELSE. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_fill_fgcolor_rgb = 'FFF5DEBF' ). + 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. + +DATA: excel TYPE REF TO zcl_excel, + reader TYPE REF TO zif_excel_reader, + go_error TYPE REF TO cx_root, + gv_message type string. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '37-passthrough.xlsx'. + +SELECTION-SCREEN BEGIN OF BLOCK blx WITH FRAME. +PARAMETERS: p_upfile TYPE string DEFAULT 'c:\temp\whatever.xlsx' LOWER CASE. +SELECTION-SCREEN END OF BLOCK blx. + +INCLUDE zdemo_excel_outputopt_incl. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_upfile. + PERFORM f4_p_upfile CHANGING p_upfile. + + +START-OF-SELECTION. + + TRY. + CREATE OBJECT reader TYPE zcl_excel_reader_2007. +* CREATE OBJECT reader TYPE zcl_excel_reader_xlsm. + excel = reader->load_file( p_upfile ). + + "Use template for charts + excel->use_template = abap_true. +*--------------------------------------------------------------------* +* CL_ABAP_ZIP may have problems reading LibreOffice generated files +* You may have to use alternate ZIP-Class - see comments in issue #234 in abap2xlsx at developers network +* excel = reader->load_file( i_filename = p_upfile +* iv_use_alternate_zip = 'ZCL_EXCEL_ABAP_ZIP' ). +*--------------------------------------------------------------------* + +*** Create output + lcl_output=>output( excel ). + CATCH cx_root INTO go_error. + MESSAGE 'Error reading excelfile' TYPE 'I'. + gv_message = go_error->get_text( ). + IF gv_message IS NOT INITIAL. + MESSAGE gv_message TYPE 'I'. + ENDIF. + ENDTRY. + + +*&---------------------------------------------------------------------* +*& 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_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. + + cl_gui_frontend_services=>file_open_dialog( EXPORTING + default_filename = p_upfile + file_filter = zcl_excel_common=>c_xlsx_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 + + + + + + + + + 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. + +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. + + " 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_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 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'E' ip_value = 'C_ICONSET_5QUARTERS' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'E' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'E' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'E' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'E' ip_value = 50 ). + + +*** 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, + 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 DEFAULT 'X' USER-COMMAND space. + +PARAMETERS: rb_back RADIOBUTTON GROUP rb1. + +PARAMETERS: rb_show RADIOBUTTON GROUP rb1. + +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. +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. + + CREATE OBJECT cl_output. + CREATE OBJECT cl_writer TYPE zcl_excel_writer_2007. + 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 hat Länge 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( ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZABAP2XLSX_DEMO_SHOW +*&---------------------------------------------------------------------* +REPORT zabap2xlsx_demo_like_se83. + + +*----------------------------------------------------------------------* +* CLASS lcl_perform DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_perform DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS: setup_objects, + collect_reports, + + handle_nav FOR EVENT double_click OF cl_gui_alv_grid + IMPORTING e_row. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_reports, + progname TYPE reposrc-progname, + sort TYPE reposrc-progname, + filename TYPE string, + END OF ty_reports. + + CLASS-DATA: + lo_grid TYPE REF TO cl_gui_alv_grid, + lo_text TYPE REF TO cl_gui_textedit, + cl_document TYPE REF TO i_oi_document_proxy, + + t_reports TYPE STANDARD TABLE OF ty_reports WITH NON-UNIQUE DEFAULT KEY. + CLASS-DATA:error TYPE REF TO i_oi_error, + t_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY, + cl_control TYPE REF TO i_oi_container_control. "Office Dokument + +ENDCLASS. "lcl_perform DEFINITION + + +START-OF-SELECTION. + lcl_perform=>collect_reports( ). + lcl_perform=>setup_objects( ). + +END-OF-SELECTION. + + WRITE '.'. " Force output + + +*----------------------------------------------------------------------* +* CLASS lcl_perform IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_perform IMPLEMENTATION. + METHOD setup_objects. + DATA: lo_split TYPE REF TO cl_gui_splitter_container, + lo_container TYPE REF TO cl_gui_container. + + DATA: it_fieldcat TYPE lvc_t_fcat, + is_layout TYPE lvc_s_layo, + is_variant TYPE disvariant. + FIELD-SYMBOLS: <fc> LIKE LINE OF it_fieldcat. + + + CREATE OBJECT lo_split + EXPORTING + parent = cl_gui_container=>screen0 + rows = 1 + columns = 3 + no_autodef_progid_dynnr = 'X'. + lo_split->set_column_width( EXPORTING id = 1 + width = 20 ). + lo_split->set_column_width( EXPORTING id = 2 + width = 40 ). + +* Left: List of reports + lo_container = lo_split->get_container( row = 1 + column = 1 ). + + CREATE OBJECT lo_grid + EXPORTING + i_parent = lo_container. + SET HANDLER lcl_perform=>handle_nav FOR lo_grid. + + is_variant-report = sy-repid. + is_variant-handle = '0001'. + + is_layout-cwidth_opt = 'X'. + + APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. + <fc>-fieldname = 'PROGNAME'. + <fc>-tabname = 'REPOSRC'. + + APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. + <fc>-fieldname = 'SORT'. + <fc>-ref_field = 'PROGNAME'. + <fc>-ref_table = 'REPOSRC'. + + + lo_grid->set_table_for_first_display( EXPORTING + is_variant = is_variant + i_save = 'A' + is_layout = is_layout + CHANGING + it_outtab = t_reports + it_fieldcatalog = it_fieldcat + EXCEPTIONS + invalid_parameter_combination = 1 + program_error = 2 + too_many_lines = 3 + OTHERS = 4 ). + +* Middle: Text with coding + lo_container = lo_split->get_container( row = 1 + column = 2 ). + CREATE OBJECT lo_text + EXPORTING + parent = lo_container. + lo_text->set_readonly_mode( cl_gui_textedit=>true ). + lo_text->set_font_fixed( ). + + + +* right: DemoOutput + lo_container = lo_split->get_container( row = 1 + column = 3 ). + + c_oi_container_control_creator=>get_container_control( IMPORTING control = cl_control + error = error ). + APPEND error TO t_errors. + + cl_control->init_control( EXPORTING inplace_enabled = 'X' + no_flush = 'X' + r3_application_name = 'Demo Document Container' + parent = lo_container + IMPORTING error = error + EXCEPTIONS OTHERS = 2 ). + APPEND error TO t_errors. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + APPEND error TO t_errors. +* Errorhandling should be inserted here + + + ENDMETHOD. "setup_objects + + "collect_reports + METHOD collect_reports. + FIELD-SYMBOLS:<report> LIKE LINE OF t_reports. + DATA: t_source TYPE STANDARD TABLE OF text255 WITH NON-UNIQUE DEFAULT KEY. + +* Get all demoreports + SELECT progname + INTO CORRESPONDING FIELDS OF TABLE t_reports + FROM reposrc + WHERE progname LIKE 'ZDEMO_EXCEL%' + AND progname <> sy-repid + AND subc = '1'. + + LOOP AT t_reports ASSIGNING <report>. + +* Check if already switched to new outputoptions + READ REPORT <report>-progname INTO t_source. + IF sy-subrc = 0. + FIND 'INCLUDE zdemo_excel_outputopt_incl.' IN TABLE t_source IGNORING CASE. + ENDIF. + IF sy-subrc <> 0. + DELETE t_reports. + CONTINUE. + ENDIF. + + +* Build half-numeric sort + <report>-sort = <report>-progname. + REPLACE REGEX '(ZDEMO_EXCEL)(\d\d)\s*$' IN <report>-sort WITH '$1\0$2'. " REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE + + REPLACE REGEX '(ZDEMO_EXCEL)(\d)\s*$' IN <report>-sort WITH '$1\0\0$2'. + ENDLOOP. + SORT t_reports BY sort progname. + + ENDMETHOD. "collect_reports + + METHOD handle_nav. + CONSTANTS: filename TYPE text80 VALUE 'ZABAP2XLSX_DEMO_SHOW.xlsx'. + DATA: wa_report LIKE LINE OF t_reports, + t_source TYPE STANDARD TABLE OF text255, + t_rawdata TYPE solix_tab, + wa_rawdata LIKE LINE OF t_rawdata, + bytecount TYPE i, + length TYPE i, + add_selopt TYPE flag. + + + READ TABLE t_reports INTO wa_report INDEX e_row-index. + CHECK sy-subrc = 0. + +* Set new text into middle frame + READ REPORT wa_report-progname INTO t_source. + lo_text->set_text_as_r3table( EXPORTING table = t_source ). + + +* Unload old xls-file + cl_document->close_document( ). + +* Get the demo +* If additional parameters found on selection screen, start via selection screen , otherwise start w/o + CLEAR add_selopt. + FIND 'PARAMETERS' IN TABLE t_source. + IF sy-subrc = 0. + add_selopt = 'X'. + ELSE. + FIND 'SELECT-OPTIONS' IN TABLE t_source. + IF sy-subrc = 0. + add_selopt = 'X'. + ENDIF. + ENDIF. + IF add_selopt IS INITIAL. + SUBMIT (wa_report-progname) AND RETURN + WITH p_backfn = filename + WITH rb_back = 'X' + WITH rb_down = ' ' + WITH rb_send = ' ' + WITH rb_show = ' '. + ELSE. + SUBMIT (wa_report-progname) VIA SELECTION-SCREEN AND RETURN + WITH p_backfn = filename + WITH rb_back = 'X' + WITH rb_down = ' ' + WITH rb_send = ' ' + WITH rb_show = ' '. + ENDIF. + + OPEN DATASET filename FOR INPUT IN BINARY MODE. + IF sy-subrc = 0. + DO. + CLEAR wa_rawdata. + READ DATASET filename INTO wa_rawdata LENGTH length. + IF sy-subrc <> 0. + APPEND wa_rawdata TO t_rawdata. + ADD length TO bytecount. + EXIT. + ENDIF. + APPEND wa_rawdata TO t_rawdata. + ADD length TO bytecount. + ENDDO. + CLOSE DATASET filename. + ENDIF. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + + cl_document->open_document_from_table( EXPORTING document_size = bytecount + document_table = t_rawdata + open_inplace = 'X' ). + + ENDMETHOD. "handle_nav + +ENDCLASS. "lcl_perform IMPLEMENTATION + + + + + + + + *&---------------------------------------------------------------------* +*& Report Z_ZAKE_SVN +*& +*&---------------------------------------------------------------------* +*& Checkout / Checkin the ZAKE_SVN Project +*& +*&---------------------------------------------------------------------* + +REPORT zake_svn_a2x. + +CONSTANTS cl_svn TYPE seoclsname VALUE 'ZCL_ZAKE_SVN'. +CONSTANTS cl_tortoise_svn TYPE seoclsname VALUE 'ZCL_ZAKE_TORTOISE_SVN'. + +DATA package TYPE devclass. +DATA zake TYPE REF TO zake. + +DATA objects TYPE scts_tadir. +DATA object LIKE LINE OF objects. + +DATA files TYPE string_table. +DATA file LIKE LINE OF files. + +DATA zake_build TYPE string. +DATA zake_nuggetname TYPE string. + +DATA comment_str TYPE string. +DATA loclpath_str TYPE string. +DATA svnpath_str TYPE string. +DATA username_str TYPE string. +DATA password_str TYPE string. +DATA class TYPE seoclsname. + +DATA: ex TYPE REF TO zcx_saplink, + message TYPE string. + +SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME TITLE a. +PARAMETERS: + checkout TYPE flag RADIOBUTTON GROUP act, + update TYPE flag RADIOBUTTON GROUP act DEFAULT 'X', + install TYPE flag RADIOBUTTON GROUP act, + export TYPE flag RADIOBUTTON GROUP act, + build TYPE flag RADIOBUTTON GROUP act, + checkin TYPE flag RADIOBUTTON GROUP act. +SELECTION-SCREEN END OF BLOCK a. + +SELECTION-SCREEN BEGIN OF BLOCK b WITH FRAME TITLE b. +PARAMETERS: + svn TYPE flag RADIOBUTTON GROUP cl, + tortoise TYPE flag RADIOBUTTON GROUP cl. +SELECTION-SCREEN END OF BLOCK b. + +SELECTION-SCREEN BEGIN OF BLOCK c WITH FRAME TITLE c. +PARAMETERS: + loclpath TYPE char512 DEFAULT 'C:\Projects\abap2xlsx\trunk' LOWER CASE OBLIGATORY, + zakenugg TYPE char512 DEFAULT 'C:\Projects\abap2xlsx\nuggs\abap2xlsx_Daily.nugg' LOWER CASE OBLIGATORY, + svnpath TYPE char512 DEFAULT 'https://code.sdn.sap.com/svn/abap2xlsx/trunk' LOWER CASE OBLIGATORY, + comment TYPE char512 DEFAULT '' LOWER CASE, + username TYPE char512 LOWER CASE, + password TYPE char512 LOWER CASE, + testrun TYPE flag DEFAULT 'X'. +SELECTION-SCREEN END OF BLOCK c. + +INITIALIZATION. + a = 'Action'. + b = 'Version Controll Program'. + c = 'Parameters'. + +START-OF-SELECTION. + + svnpath_str = svnpath. + loclpath_str = loclpath. + zake_nuggetname = zakenugg. + comment_str = comment. + + " SELECT * INTO TABLE objects FROM tadir WHERE devclass = 'ZABAP2XLSX'. + " DELETE zake_objects WHERE object = 'DEVC'. + + TRY. + IF svn = 'X'. + class = cl_svn. + ELSE. + class = cl_tortoise_svn. + ENDIF. + + CREATE OBJECT zake + TYPE + (class) + EXPORTING + i_svnpath = svnpath_str + i_localpath = loclpath_str. + zake->set_testrun( testrun ). + zake->set_package( 'ZA2X' ). + + IF checkout = 'X'. + zake->checkout( ). + ELSEIF update = 'X'. + zake->update( ). + ELSEIF install = 'X'. + zake->install_slinkees_from_lm( testrun ). + " zake->install_objects( zake_objects ). + ELSEIF export = 'X'. + " Build Object list for Export + " Programs + object-object = 'PROG'. + object-obj_name = 'ZAKE_SVN_A2X'. + APPEND object TO objects. + zake->set_checkin_objects( objects ). + zake->download_slinkees_to_lm = abap_true. + zake->download_nugget_to_lm = space. + zake->download_zip_to_lm_flag = space. + zake->create_slinkees( zake_nuggetname ). + ELSEIF build = 'X'. + " Build a complete package for download + zake->set_checkin_objects( objects ). + " We don't want that for the complete Package Slinkees are created + " in the ZAKE folder + zake->download_slinkees_to_lm = space. + zake->download_nugget_to_lm = space. + zake->create_slinkees( zake_nuggetname ). + ELSEIF checkin = 'X'. + zake->set_package( 'ZA2X' ). + zake->set_checkin_objects( objects ). + zake->create_slinkees( zake_nuggetname ). + IF testrun IS INITIAL. + zake->checkin( comment_str ). + ENDIF. + ENDIF. + CATCH zcx_saplink INTO ex. + message = ex->msg. + WRITE: / 'An Error occured: ', message. + ENDTRY. + + + + + + + + + *&---------------------------------------------------------------------* +*& 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 chnage 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. + 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 p_path = p_path AND RETURN. " abap2xlsx Demo: Hello world + SUBMIT zdemo_excel2 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Styles + SUBMIT zdemo_excel3 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: iTab binding + SUBMIT zdemo_excel4 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Multi sheets, page setup and sheet properties + SUBMIT zdemo_excel5 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Conditional formatting + SUBMIT zdemo_excel6 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Formulas + SUBMIT zdemo_excel7 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Conditional formatting + SUBMIT zdemo_excel8 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Ranges + SUBMIT zdemo_excel9 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Data validation + SUBMIT zdemo_excel10 WITH p_path = p_path AND RETURN. " 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 p_path = p_path AND RETURN. " abap2xlsx Demo: Column size + SUBMIT zdemo_excel13 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Merge cell + SUBMIT zdemo_excel14 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Alignment + SUBMIT zdemo_excel16 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Drawing + SUBMIT zdemo_excel17 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Lock sheet + SUBMIT zdemo_excel18 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Lock workbook + SUBMIT zdemo_excel19 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Set active sheet + " zdemo_excel20 is not added because it uses ALV and cannot be processed (OLE2) + SUBMIT zdemo_excel21 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Color Picker + SUBMIT zdemo_excel22 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Bind table with field catalog & sheet style + SUBMIT zdemo_excel23 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Multiple sheets with and w/o grid lines, print options + SUBMIT zdemo_excel24 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Multiple sheets with different default date formats + SUBMIT zdemo_excel25 AND RETURN. " 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 p_path = p_path AND RETURN. " abap2xlsx Demo: Conditional Formatting + SUBMIT zdemo_excel28 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: CSV writer + " SUBMIT zdemo_excel29 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Macro enabled workbook + SUBMIT zdemo_excel30 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: ABAP Cell data types + SUBMIT zdemo_excel31 WITH p_path = p_path AND RETURN. " 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 p_path = p_path AND RETURN. " abap2xlsx Demo: Table autofilter + SUBMIT zdemo_excel34 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Static Styles Chess + SUBMIT zdemo_excel35 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Static Styles + SUBMIT zdemo_excel36 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Style applied to sheet, column and single cell + SUBMIT zdemo_excel37 WITH p_upfile = lv_upfile + WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Simplest call of the reader and writer - passthrough data + SUBMIT zdemo_excel38 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Show off integration of drawings ( here using the SAP-Icons ) + SUBMIT ZDEMO_EXCEL39 WITH p_path = p_path AND RETURN. " abap2xlsx Demo: Charts + " + " Reader/Writer Demo must always run at the end + " to make sure all documents where created + " + SUBMIT zdemo_excel15 WITH p_path = p_path AND RETURN. " 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 a. +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 b. +PARAMETERS: reltyp TYPE bu_reltyp DEFAULT 'BUR011', + partner TYPE bu_partner DEFAULT '191'. +SELECTION-SCREEN END OF BLOCK b. + +INITIALIZATION. + a = 'Select by master data'. + b = 'Select by relationship'. + +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 = 6 ip_value = 'Outline row level 0' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Outline row level 1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Outline row level 2' ). + + 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 ). + " 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 ). + +*** 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. + +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 '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 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 ). + +* 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.zip b/build/ABAP2XLSX_V_7_0.zip index d478a558afd5232ebeac32f152c466a59c1a0f29..2812f994ca976ba0477fc60ddef13f850ad2f521 100644 GIT binary patch literal 291459 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 TL;N=d@J}=UK}aXCANzj**apAa literal 288183 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

-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

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