diff --git a/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk b/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk index 2cc6b22..bfe1962 100644 --- a/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk +++ b/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk @@ -1,3092 +1,2912 @@ - - - - - - - - - - - - - - - - - - - - - class ZCL_EXCEL_READER_2007 definition - public - create public . - -public section. - type-pools IXML . - - interfaces ZIF_EXCEL_READER . - - class-methods FILL_STRUCT_FROM_ATTRIBUTES - importing - !IP_ELEMENT type ref to IF_IXML_ELEMENT - changing - !CP_STRUCTURE type ANY . - protected section. - - types: - BEGIN OF t_relationship, - id TYPE string, - type TYPE string, - target TYPE string, - worksheet TYPE REF TO zcl_excel_worksheet, - sheetid type string, "ins #235 - repeat rows/cols - needed to identify correct sheet - END OF t_relationship . - types: - BEGIN OF t_fileversion, - appname TYPE string, - lastedited TYPE string, - lowestedited TYPE string, - rupbuild TYPE string, - codename TYPE string, - END OF t_fileversion . - types: - BEGIN OF t_sheet, - name TYPE string, - sheetid TYPE string, - id TYPE string, - state TYPE string, - END OF t_sheet . - types: - BEGIN OF t_workbookpr, - codename TYPE string, - defaultthemeversion TYPE string, - END OF t_workbookpr . - types: - BEGIN OF t_sheetpr, - codename TYPE string, - END OF t_sheetpr . - types: - BEGIN OF t_range, - name TYPE string, - hidden type string, "inserted with issue #235 because Autofilters didn't passthrough - localsheetid TYPE string, " issue #163 - END OF t_range . - types: - t_fills TYPE STANDARD TABLE OF REF TO zcl_excel_style_fill WITH NON-UNIQUE DEFAULT KEY . - types: - t_borders TYPE STANDARD TABLE OF REF TO zcl_excel_style_borders WITH NON-UNIQUE DEFAULT KEY . - types: - t_fonts TYPE STANDARD TABLE OF REF TO zcl_excel_style_font WITH NON-UNIQUE DEFAULT KEY . - types: - t_style_refs TYPE STANDARD TABLE OF REF TO zcl_excel_style WITH NON-UNIQUE DEFAULT KEY . - types: - BEGIN OF t_num_format, - id TYPE string, - format TYPE REF TO zcl_excel_style_number_format, - END OF t_num_format . - types: - t_num_formats TYPE HASHED TABLE OF t_num_format WITH UNIQUE KEY id . - types: - BEGIN OF t_color, - indexed TYPE string, - rgb TYPE string, - theme TYPE string, - tint TYPE string, - END OF t_color . - types: - BEGIN OF t_rel_drawing, - id TYPE string, - content TYPE xstring, - file_ext TYPE string, - content_xml TYPE REF TO IF_IXML_DOCUMENT, - END OF t_rel_drawing . - types: - t_rel_drawings TYPE STANDARD TABLE OF t_rel_drawing WITH NON-UNIQUE DEFAULT KEY . - - data SHARED_STRINGS type STRINGTAB . - data STYLES type T_STYLE_REFS . - - class-methods RESOLVE_PATH - importing - !IP_PATH type STRING - returning - value(RP_RESULT) type STRING . - methods GET_FROM_ZIP_ARCHIVE - importing - !I_FILENAME type STRING - returning - value(R_CONTENT) type XSTRING - raising - ZCX_EXCEL . - methods GET_IXML_FROM_ZIP_ARCHIVE - importing - !I_FILENAME type STRING - !IS_NORMALIZING type BOOLEAN default 'X' - returning - value(R_IXML) type ref to IF_IXML_DOCUMENT - raising - ZCX_EXCEL . - methods LOAD_WORKBOOK - importing - !IV_WORKBOOK_FULL_FILENAME type STRING - !IO_EXCEL type ref to ZCL_EXCEL - raising - ZCX_EXCEL . - methods LOAD_DRAWING_ANCHOR - importing - !IO_ANCHOR_ELEMENT type ref to IF_IXML_ELEMENT - !IO_WORKSHEET type ref to ZCL_EXCEL_WORKSHEET - !IT_RELATED_DRAWINGS type T_REL_DRAWINGS . - methods LOAD_WORKSHEET - importing - !IP_PATH type STRING - !IO_WORKSHEET type ref to ZCL_EXCEL_WORKSHEET - raising - ZCX_EXCEL . - methods LOAD_WORKSHEET_DRAWING - importing - !IP_PATH type STRING - !IO_WORKSHEET type ref to ZCL_EXCEL_WORKSHEET - raising - ZCX_EXCEL . - methods LOAD_SHARED_STRINGS - importing - !IP_PATH type STRING - raising - ZCX_EXCEL . - methods LOAD_STYLES - importing - !IP_PATH type STRING - !IP_EXCEL type ref to ZCL_EXCEL - raising - ZCX_EXCEL . - methods LOAD_STYLE_BORDERS - importing - !IP_XML type ref to IF_IXML_DOCUMENT - returning - value(EP_BORDERS) type T_BORDERS . - methods LOAD_STYLE_FILLS - importing - !IP_XML type ref to IF_IXML_DOCUMENT - returning - value(EP_FILLS) type T_FILLS . - methods LOAD_STYLE_FONTS - importing - !IP_XML type ref to IF_IXML_DOCUMENT - returning - value(EP_FONTS) type T_FONTS . - methods LOAD_STYLE_NUM_FORMATS - importing - !IP_XML type ref to IF_IXML_DOCUMENT - returning - value(EP_NUM_FORMATS) type T_NUM_FORMATS . - methods RESOLVE_REFERENCED_FORMULAE . - private section. - - types: - BEGIN OF ty_ref_formulae, - sheet TYPE REF TO zcl_excel_worksheet, - row TYPE i, - column TYPE i, - si TYPE i, - ref TYPE string, - formula TYPE string, - END OF ty_ref_formulae . - types: - tyt_ref_formulae TYPE HASHED TABLE OF ty_ref_formulae WITH UNIQUE KEY sheet row column . - - data EXCEL2007 type XSTRING . - data ZIP type ref to CL_ABAP_ZIP . - data ALTERNATE_ZIP type ref to OBJECT . - data MT_REF_FORMULAE type TYT_REF_FORMULAE . - *"* 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 = iv_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 -*--------------------------------------------------------------------* - - CONSTANTS: lcv_load_from_frontend TYPE char1 VALUE 'F', - lcv_load_from_backend TYPE char1 VALUE 'B'. - - DATA: lv_load_from_source TYPE char1, - - lv_filelength TYPE i, - lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, - ls_binary_data LIKE LINE OF lt_binary_data, -* Background processing - lv_max_length_line TYPE i, - lv_actual_length_line TYPE i, - - lv_errormessage TYPE string, " Can't pass '...'(abc) to exception-class - lv_excel_data TYPE xstring. " Binary content of .xlsx file - - -*--------------------------------------------------------------------* -* ToDos: 2do§1 Decision whether to load from frontend or backend -*--------------------------------------------------------------------* - -*--------------------------------------------------------------------* -* issue#234 - error reading xlsx written by libre office - me->zif_excel_reader~gv_use_alternate_zip = iv_use_alternate_zip. -*--------------------------------------------------------------------* - - -*--------------------------------------------------------------------* -* Autodecide on frontend or backend reading -* Background-processing --> backend reading -* Online-processing --> frontend reading -*--------------------------------------------------------------------* - IF sy-batch = abap_true. - lv_load_from_source = lcv_load_from_backend. - ELSE. - lv_load_from_source = lcv_load_from_frontend. - ENDIF. - - CASE lv_load_from_source. - -*--------------------------------------------------------------------* -* Read from backend -*--------------------------------------------------------------------* - WHEN lcv_load_from_backend. - DESCRIBE FIELD ls_binary_data LENGTH lv_max_length_line IN BYTE MODE. - OPEN DATASET i_filename FOR INPUT IN BINARY MODE. - IF sy-subrc <> 0. - lv_errormessage = 'A problem occured when reading the file'(001). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - WHILE sy-subrc = 0. - - READ DATASET i_filename INTO ls_binary_data MAXIMUM LENGTH lv_max_length_line ACTUAL LENGTH lv_actual_length_line. - APPEND ls_binary_data TO lt_binary_data. - lv_filelength = lv_filelength + lv_actual_length_line. - - ENDWHILE. - CLOSE DATASET i_filename. - -*--------------------------------------------------------------------* -* Read from frontend -*--------------------------------------------------------------------* - WHEN lcv_load_from_frontend. - cl_gui_frontend_services=>gui_upload( EXPORTING - filename = i_filename - filetype = 'BIN' " We are basically working with zipped directories --> force binary read - IMPORTING - filelength = lv_filelength - CHANGING - data_tab = lt_binary_data - EXCEPTIONS - file_open_error = 1 - file_read_error = 2 - no_batch = 3 - gui_refuse_filetransfer = 4 - invalid_type = 5 - no_authority = 6 - unknown_error = 7 - bad_data_format = 8 - header_not_allowed = 9 - separator_not_allowed = 10 - header_too_long = 11 - unknown_dp_error = 12 - access_denied = 13 - dp_out_of_memory = 14 - disk_full = 15 - dp_timeout = 16 - not_supported_by_gui = 17 - error_no_gui = 18 - OTHERS = 19 ). - IF sy-subrc <> 0. - lv_errormessage = 'A problem occured when reading the file'(001). - RAISE EXCEPTION TYPE zcx_excel - EXPORTING - error = lv_errormessage. - ENDIF. - - ENDCASE. - - -*--------------------------------------------------------------------* -* Binary data needs to be provided as XSTRING for further processing -*--------------------------------------------------------------------* - CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' - EXPORTING - input_length = lv_filelength - IMPORTING - buffer = lv_excel_data - TABLES - binary_tab = lt_binary_data. - -*--------------------------------------------------------------------* -* issue#234 - error reading xlsx written by libre office - r_excel = me->zif_excel_reader~load( i_excel2007 = lv_excel_data - iv_use_alternate_zip = iv_use_alternate_zip ). -*--------------------------------------------------------------------* - - - endmethod. - - - - - 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. - - - 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. - - -*--------------------------------------------------------------------* -* §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 - - 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 ). -* CALL FUNCTION 'CV120_SPLIT_FILE' -* EXPORTING -* pf_file = path2 -* IMPORTING -* pfx_extension = file_ext2. - rel_drawing-file_ext = file_ext2. - - "-------------Added by Alessandro Iannacci - Should load graph xml - 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 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. - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + *"* 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 = iv_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 +*--------------------------------------------------------------------* + + CONSTANTS: lcv_load_from_frontend TYPE char1 VALUE 'F', + lcv_load_from_backend TYPE char1 VALUE 'B'. + + DATA: lv_load_from_source TYPE char1, + + lv_filelength TYPE i, + lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, + ls_binary_data LIKE LINE OF lt_binary_data, +* Background processing + lv_max_length_line TYPE i, + lv_actual_length_line TYPE i, + + lv_errormessage TYPE string, " Can't pass '...'(abc) to exception-class + lv_excel_data TYPE xstring. " Binary content of .xlsx file + +DATA: lv_filename TYPE string. + +*--------------------------------------------------------------------* +* ToDos: 2do§1 Decision whether to load from frontend or backend +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office + me->zif_excel_reader~gv_use_alternate_zip = iv_use_alternate_zip. +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* Autodecide on frontend or backend reading +* Background-processing --> backend reading +* Online-processing --> frontend reading +*--------------------------------------------------------------------* + IF sy-batch = abap_true. + lv_load_from_source = lcv_load_from_backend. + ELSE. + lv_load_from_source = lcv_load_from_frontend. + ENDIF. + + move i_filename TO lv_filename. + + CASE lv_load_from_source. + +*--------------------------------------------------------------------* +* Read from backend +*--------------------------------------------------------------------* + WHEN lcv_load_from_backend. + DESCRIBE FIELD ls_binary_data LENGTH lv_max_length_line IN BYTE MODE. + OPEN DATASET 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. + +*--------------------------------------------------------------------* +* Read from frontend +*--------------------------------------------------------------------* + WHEN lcv_load_from_frontend. + 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. + + ENDCASE. + + +*--------------------------------------------------------------------* +* Binary data needs to be provided as XSTRING for further processing +*--------------------------------------------------------------------* + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filelength + IMPORTING + buffer = lv_excel_data + TABLES + binary_tab = lt_binary_data. + +*--------------------------------------------------------------------* +* issue#234 - error reading xlsx written by libre office + r_excel = me->zif_excel_reader~load( i_excel2007 = lv_excel_data + iv_use_alternate_zip = iv_use_alternate_zip ). +*--------------------------------------------------------------------* + + + endmethod. + + + + + 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. + + + 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. + + +*--------------------------------------------------------------------* +* §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 + + 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 ). +* CALL FUNCTION 'CV120_SPLIT_FILE' +* EXPORTING +* pf_file = path2 +* IMPORTING +* pfx_extension = file_ext2. + rel_drawing-file_ext = file_ext2. + + "-------------Added by Alessandro Iannacci - Should load graph xml + 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 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. + + diff --git a/ZA2X/INTF/ZIF_EXCEL_READER.slnk b/ZA2X/INTF/ZIF_EXCEL_READER.slnk index 4c72c51..09fac77 100644 --- a/ZA2X/INTF/ZIF_EXCEL_READER.slnk +++ b/ZA2X/INTF/ZIF_EXCEL_READER.slnk @@ -1,5 +1,5 @@ - + @@ -12,7 +12,7 @@ - + diff --git a/ZA2X/PROG/ZDEMO_EXCEL15.slnk b/ZA2X/PROG/ZDEMO_EXCEL15.slnk index 321cfb5..80eb157 100644 --- a/ZA2X/PROG/ZDEMO_EXCEL15.slnk +++ b/ZA2X/PROG/ZDEMO_EXCEL15.slnk @@ -1,5 +1,5 @@ - - + +