class ZCL_EXCEL_READER_2007 definition public create public . public section. *"* public components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! type-pools IXML . interfaces ZIF_EXCEL_READER . *"* protected components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! protected section. types: BEGIN OF t_relationship, id TYPE string, type TYPE string, target TYPE string, 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, 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, localsheetid TYPE string, " issue #163 END OF t_range . types: t_fills TYPE STANDARD TABLE OF REF TO zcl_excel_style_fill WITH DEFAULT KEY . types: t_borders TYPE STANDARD TABLE OF REF TO zcl_excel_style_borders WITH DEFAULT KEY . types: t_fonts TYPE STANDARD TABLE OF REF TO zcl_excel_style_font WITH DEFAULT KEY . types: t_style_refs TYPE TABLE OF REF TO zcl_excel_style . 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, end of t_rel_drawing . types: t_rel_drawings type TABLE OF t_rel_drawing . class-methods RESOLVE_PATH importing !IP_PATH type STRING returning value(RP_RESULT) type STRING . methods FILL_STRUCT_FROM_ATTRIBUTES importing !IP_ELEMENT type ref to IF_IXML_ELEMENT changing !CP_STRUCTURE type ANY . 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 !IP_PATH type STRING !IP_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 . private section. *"* private components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! data EXCEL2007 type XSTRING . data ZIP type ref to CL_ABAP_ZIP . data SHARED_STRINGS type STRINGTAB . data STYLES type T_STYLE_REFS . *"* 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. * For now always Unknown r_readable = abap_undefined. endmethod. method ZIF_EXCEL_READER~LOAD. CONSTANTS: lc_core_properties TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', lc_office_document TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', lc_relationships TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'. DATA: rels TYPE REF TO if_ixml_document, node TYPE REF TO if_ixml_element, relationship TYPE t_relationship. me->excel2007 = i_excel2007. rels = me->get_ixml_from_zip_archive( '_rels/.rels' ). CREATE OBJECT r_excel. node ?= rels->find_from_name( 'Relationship' ). WHILE node IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). CASE relationship-type. WHEN lc_core_properties. " TODO Map Document Properties to ZCL_EXCEL WHEN lc_office_document. load_workbook( ip_path = relationship-target ip_excel = r_excel ). WHEN OTHERS. ENDCASE. node ?= node->get_next( ). ENDWHILE. endmethod. method ZIF_EXCEL_READER~LOAD_FILE. DATA: excel_data TYPE xstring. DATA filelength TYPE i. DATA bin_tab TYPE TABLE OF x255. " Background processing DATA bin_data LIKE LINE OF bin_tab. DATA len TYPE i. DATA alen TYPE i. IF sy-batch = abap_true. DESCRIBE FIELD bin_data LENGTH len IN BYTE MODE. OPEN DATASET i_filename FOR INPUT IN BINARY MODE. WHILE sy-subrc = 0. READ DATASET i_filename INTO bin_data MAXIMUM LENGTH len ACTUAL LENGTH alen. APPEND bin_data TO bin_tab. filelength = filelength + alen. ENDWHILE. CLOSE DATASET i_filename. ELSE. cl_gui_frontend_services=>gui_upload( EXPORTING filename = i_filename " Name of file filetype = 'BIN' " File Type (ASCII, Binary) IMPORTING filelength = filelength CHANGING data_tab = bin_tab 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. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'A problem occured when reading the file'. ENDIF. ENDIF. CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' EXPORTING input_length = filelength IMPORTING buffer = excel_data TABLES binary_tab = bin_tab. r_excel = me->zif_excel_reader~load( excel_data ). endmethod. method FILL_STRUCT_FROM_ATTRIBUTES. DATA: name TYPE string, attributes TYPE REF TO if_ixml_named_node_map, attribute TYPE REF TO if_ixml_attribute, iterator TYPE REF TO if_ixml_node_iterator. FIELD-SYMBOLS: <component> TYPE any. CLEAR cp_structure. attributes = ip_element->get_attributes( ). iterator = attributes->create_iterator( ). attribute ?= iterator->get_next( ). WHILE attribute IS BOUND. name = attribute->get_name( ). TRANSLATE name TO UPPER CASE. ASSIGN COMPONENT name OF STRUCTURE cp_structure TO <component>. IF sy-subrc = 0. <component> = attribute->get_value( ). ENDIF. attribute ?= iterator->get_next( ). ENDWHILE. endmethod. method GET_FROM_ZIP_ARCHIVE. 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. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'ZIP parse error'. ENDIF. ENDIF. 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. RAISE EXCEPTION TYPE zcx_excel EXPORTING error = 'ZIP index or decompression error'. ENDIF. endmethod. method GET_IXML_FROM_ZIP_ARCHIVE. TYPE-POOLS: ixml. DATA: content TYPE xstring. DATA: ixml TYPE REF TO if_ixml, streamfactory TYPE REF TO if_ixml_stream_factory, istream TYPE REF TO if_ixml_istream, parser TYPE REF TO if_ixml_parser. content = me->get_from_zip_archive( i_filename ). ixml = cl_ixml=>create( ). streamfactory = ixml->create_stream_factory( ). istream = streamfactory->create_istream_xstring( content ). r_ixml = ixml->create_document( ). parser = ixml->create_parser( stream_factory = streamfactory istream = istream document = r_ixml ). * parser->set_normalizing( ). parser->set_normalizing( is_normalizing ). parser->set_validating( mode = if_ixml_parser=>co_no_validation ). 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 ). endmethod. method LOAD_SHARED_STRINGS. DATA: value TYPE string, value2 TYPE string, shared_strings_xml TYPE REF TO if_ixml_document, tag_name TYPE string, node TYPE REF TO if_ixml_element, node2 TYPE REF TO if_ixml_element, node3 TYPE REF TO if_ixml_element. *** Basic structure of Shared strings *** Some lines insignificant for us to read *** <si>(Stringinfo)</si> *** So far I have seen 2 versions how (Stringinfo) can be displayed *** a) "simple" strings: <t>string</t> *** b) rich text string: (<r>richtextstring</r>)+ " String split up into parts that are of equal formatting *** richtextstring: can be *** b1) <t xml:space="preserve">string</t> *** or b2) <rPr>someformattinginfo</rPr><t xml:space="preserve">string</t> 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 node ?= shared_strings_xml->find_from_name( 'si' ). WHILE node IS BOUND. node2 ?= node->get_first_child( ). tag_name = node2->get_name( ). IF tag_name = 't'. " a - "simple" string value = node2->get_value( ). APPEND value TO shared_strings. ELSEIF tag_name = 'r'. " b - rich text string " TODO parse rich text * Still no support for rich text strings - but at least we should try to extract the stringinfo from this passage * and !!! APPEND it to shared strings - otherwise the stringtable might get jumbled CLEAR value. WHILE node2 IS BOUND. " Walk through b) node3 ?= node2->get_first_child( ). WHILE node3 IS BOUND. tag_name = node3->get_name( ). IF tag_name = 't'. " this is sufficient to get hold of b1 and b2 value2 = node3->get_value( ). CONCATENATE value value2 INTO value RESPECTING BLANKS. " Build resulting string from all partial (formatted) strings ENDIF. node3 ?= node3->get_next( ). ENDWHILE. node2 ?= node2->get_next( ). ENDWHILE. APPEND value TO shared_strings. ENDIF. node ?= node->get_next( ). ENDWHILE. endmethod. method LOAD_STYLES. TYPES: BEGIN OF t_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 t_xf. TYPES: BEGIN OF t_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 t_alignment. TYPES: BEGIN OF t_protection, hidden TYPE string, locked TYPE string, END OF t_protection. DATA: styles_xml TYPE REF TO if_ixml_document, iterator TYPE REF TO if_ixml_node_iterator, nodes TYPE REF TO if_ixml_node_collection, node TYPE REF TO if_ixml_element, node2 TYPE REF TO if_ixml_element, fills TYPE t_fills, fill TYPE REF TO zcl_excel_style_fill, num_formats TYPE t_num_formats, num_format TYPE t_num_format, cell_border TYPE REF TO zcl_excel_style_borders, borders TYPE t_borders, fonts TYPE t_fonts, font TYPE REF TO zcl_excel_style_font, style TYPE REF TO zcl_excel_style, xf TYPE t_xf, alignment TYPE t_alignment, protection TYPE t_protection, index TYPE i. styles_xml = me->get_ixml_from_zip_archive( ip_path ). num_formats = load_style_num_formats( styles_xml ). fills = load_style_fills( styles_xml ). borders = load_style_borders( styles_xml ). fonts = load_style_fonts( styles_xml ). "we have all the components of style, now build the style objects node = styles_xml->find_from_name( name = 'cellXfs' ). IF node IS BOUND. nodes = node->get_elements_by_tag_name( name = 'xf' ). iterator = nodes->create_iterator( ). node ?= iterator->get_next( ). WHILE node IS BOUND. style = ip_excel->add_new_style( ). fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = xf ). IF xf-applyfill = '1' AND xf-fillid IS NOT INITIAL. index = xf-fillid + 1. READ TABLE fills INTO fill INDEX index. IF sy-subrc = 0. style->fill = fill. ENDIF. ENDIF. IF xf-numfmtid IS NOT INITIAL. READ TABLE num_formats INTO num_format WITH TABLE KEY id = xf-numfmtid. IF sy-subrc = 0. style->number_format = num_format-format. ENDIF. ENDIF. IF xf-applyborder = '1' AND xf-borderid IS NOT INITIAL. index = xf-borderid + 1. READ TABLE borders INTO cell_border INDEX index. IF sy-subrc = 0. style->borders = cell_border. ENDIF. ENDIF. IF xf-applyfont = '1' AND xf-fontid IS NOT INITIAL. index = xf-fontid + 1. READ TABLE fonts INTO font INDEX index. IF sy-subrc = 0. style->font = font. ENDIF. ENDIF. node2 ?= node->find_from_name( 'alignment' ). IF node2 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = alignment ). IF alignment-horizontal IS NOT INITIAL. style->alignment->horizontal = alignment-horizontal. ENDIF. IF alignment-vertical IS NOT INITIAL. style->alignment->vertical = alignment-vertical. ENDIF. IF alignment-textrotation IS NOT INITIAL. style->alignment->textrotation = alignment-textrotation. ENDIF. IF alignment-wraptext = '1' OR alignment-wraptext = 'true'. style->alignment->wraptext = abap_true. ENDIF. IF alignment-shrinktofit = '1' OR alignment-shrinktofit = 'true'. style->alignment->shrinktofit = abap_true. ENDIF. IF alignment-indent IS NOT INITIAL. style->alignment->indent = alignment-indent. ENDIF. ENDIF. node2 ?= node->find_from_name( 'protection' ). IF node2 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = protection ). IF protection-locked = '1' OR protection-locked = 'true'. style->protection->locked = zcl_excel_style_protection=>c_protection_locked. ELSE. style->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. ENDIF. IF protection-hidden = '1' OR protection-hidden = 'true'. style->protection->hidden = zcl_excel_style_protection=>c_protection_hidden. ELSE. style->protection->hidden = zcl_excel_style_protection=>c_protection_unhidden. ENDIF. ENDIF. INSERT style INTO TABLE styles. node ?= iterator->get_next( ). ENDWHILE. ENDIF. endmethod. method LOAD_STYLE_BORDERS. DATA: node TYPE REF TO if_ixml_element, node2 TYPE REF TO if_ixml_element, node3 TYPE REF TO if_ixml_element, cell_border TYPE REF TO zcl_excel_style_borders, border TYPE REF TO zcl_excel_style_border, color TYPE t_color. node ?= ip_xml->find_from_name( 'border' ). WHILE node IS BOUND. CREATE OBJECT cell_border. IF node->get_attribute( 'diagonalDown' ) IS NOT INITIAL. cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_down. ENDIF. IF node->get_attribute( 'diagonalUp' ) IS NOT INITIAL. IF cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_down. cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_both. ELSE. cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_up. ENDIF. ENDIF. node2 ?= node->get_first_child( ). WHILE node2 IS BOUND. CREATE OBJECT border. CASE node2->get_name( ). WHEN 'left'. cell_border->left = border. WHEN 'right'. cell_border->right = border. WHEN 'top'. cell_border->top = border. WHEN 'bottom'. cell_border->down = border. WHEN 'diagonal'. cell_border->diagonal = border. ENDCASE. border->border_style = node2->get_attribute( 'style' ). node3 ?= node2->find_from_name( 'color' ). IF node3 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = color ). border->border_color-rgb = color-rgb. IF color-indexed IS NOT INITIAL. border->border_color-indexed = color-indexed. ENDIF. IF color-theme IS NOT INITIAL. border->border_color-theme = color-theme. ENDIF. border->border_color-tint = color-tint. ENDIF. node2 ?= node2->get_next( ). ENDWHILE. INSERT cell_border INTO TABLE ep_borders. node ?= node->get_next( ). ENDWHILE. endmethod. method LOAD_STYLE_FILLS. DATA: value TYPE string, node TYPE REF TO if_ixml_element, node2 TYPE REF TO if_ixml_element, node3 TYPE REF TO if_ixml_element, fill TYPE REF TO zcl_excel_style_fill, color TYPE t_color. node ?= ip_xml->find_from_name( 'fill' ). WHILE node IS BOUND. CREATE OBJECT fill. node2 ?= node->get_first_child( ). value = node2->get_name( ). CASE value. WHEN 'patternFill'. fill->filltype = node2->get_attribute( 'patternType' ). node3 = node2->find_from_name( 'bgColor' ). IF node3 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = color ). fill->bgcolor-rgb = color-rgb. IF color-indexed IS NOT INITIAL. fill->bgcolor-indexed = color-indexed. ENDIF. IF color-theme IS NOT INITIAL. fill->bgcolor-theme = color-theme. ENDIF. fill->bgcolor-tint = color-tint. ENDIF. node3 = node->find_from_name( 'fgColor' ). IF node3 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = color ). fill->fgcolor-rgb = color-rgb. IF color-indexed IS NOT INITIAL. fill->fgcolor-indexed = color-indexed. ENDIF. IF color-theme IS NOT INITIAL. fill->fgcolor-theme = color-theme. ENDIF. fill->fgcolor-tint = color-tint. ENDIF. WHEN 'gradientFill'. "TODO WHEN OTHERS. ENDCASE. INSERT fill INTO TABLE ep_fills. node ?= node->get_next( ). ENDWHILE. endmethod. method LOAD_STYLE_FONTS. DATA: value TYPE string, node TYPE REF TO if_ixml_element, node2 TYPE REF TO if_ixml_element, node3 TYPE REF TO if_ixml_element, font TYPE REF TO zcl_excel_style_font, color TYPE t_color. node ?= ip_xml->find_from_name( 'font' ). WHILE node IS BOUND. CREATE OBJECT font. IF node->find_from_name( 'b' ) IS BOUND. font->bold = abap_true. ENDIF. IF node->find_from_name( 'i' ) IS BOUND. font->italic = abap_true. ENDIF. node2 = node->find_from_name( 'u' ). IF node2 IS BOUND. font->underline = abap_true. font->underline_mode = node2->get_attribute( 'val' ). ENDIF. IF node->find_from_name( 'strike' ) IS BOUND. font->strikethrough = abap_true. ENDIF. node2 = node->find_from_name( 'sz' ). IF node2 IS BOUND. font->size = node2->get_attribute( 'val' ). ENDIF. node2 = node->find_from_name( 'name' ). IF node2 IS BOUND. font->name = node2->get_attribute( 'val' ). ENDIF. node2 = node->find_from_name( 'family' ). IF node2 IS BOUND. font->family = node2->get_attribute( 'val' ). ENDIF. node2 = node->find_from_name( 'scheme' ). IF node2 IS BOUND. font->scheme = node2->get_attribute( 'val' ). ENDIF. node2 = node->find_from_name( 'color' ). IF node2 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = color ). font->color-rgb = color-rgb. IF color-indexed IS NOT INITIAL. font->color-indexed = color-indexed. ENDIF. IF color-theme IS NOT INITIAL. font->color-theme = color-theme. ENDIF. font->color-tint = color-tint. ENDIF. INSERT font INTO TABLE ep_fonts. node ?= node->get_next( ). ENDWHILE. endmethod. method LOAD_STYLE_NUM_FORMATS. DATA: node TYPE REF TO if_ixml_element, num_format TYPE t_num_format. node ?= ip_xml->find_from_name( 'numFmt' ). WHILE node IS BOUND. CLEAR num_format. CREATE OBJECT num_format-format. num_format-format->format_code = node->get_attribute( 'formatCode' ). num_format-id = node->get_attribute( 'numFmtId' ). INSERT num_format INTO TABLE ep_num_formats. node ?= node->get_next( ). ENDWHILE. DEFINE predefined_format. num_format-id = &1. create object num_format-format. num_format-format->format_code = &2. insert num_format into table ep_num_formats. END-OF-DEFINITION. 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'. 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)'. 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' '@'. endmethod. method LOAD_WORKBOOK. CONSTANTS: lc_shared_strings TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', lc_worksheet TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', lc_styles TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles'. DATA: rels TYPE REF TO if_ixml_document, rels_workbook_path TYPE string, rels_workbook TYPE REF TO if_ixml_document, path TYPE string, worksheets TYPE TABLE OF t_relationship, workbook TYPE REF TO if_ixml_document, workbook_index TYPE i, worksheet_path TYPE string, sheet TYPE t_sheet, node TYPE REF TO if_ixml_element, stripped_name TYPE chkfile, dirname TYPE string, relationship TYPE t_relationship, lo_worksheet TYPE REF TO zcl_excel_worksheet, lo_range TYPE REF TO zcl_excel_range, worksheet_title TYPE zexcel_sheet_title, range TYPE t_range, range_value TYPE zexcel_range_value. FIELD-SYMBOLS: <worksheet> TYPE t_relationship. CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' EXPORTING full_name = ip_path IMPORTING stripped_name = stripped_name file_path = dirname. " Read Workbook Relationships CONCATENATE dirname '_rels/' stripped_name '.rels' INTO rels_workbook_path. rels_workbook = me->get_ixml_from_zip_archive( rels_workbook_path ). node ?= rels_workbook->find_from_name( 'Relationship' ). WHILE node IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). CASE relationship-type. WHEN lc_shared_strings. " Read Shared Strings CONCATENATE dirname relationship-target INTO path. load_shared_strings( path ). WHEN lc_worksheet. " Read worksheets APPEND relationship TO worksheets. WHEN lc_styles. CONCATENATE dirname relationship-target INTO path. load_styles( ip_path = path ip_excel = ip_excel ). WHEN OTHERS. ENDCASE. node ?= node->get_next( ). ENDWHILE. " Read Workbook workbook = me->get_ixml_from_zip_archive( ip_path ). node ?= workbook->find_from_name( 'sheet' ). workbook_index = 1. WHILE node IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = sheet ). worksheet_title = sheet-name. IF workbook_index > 1. lo_worksheet = ip_excel->add_new_worksheet( worksheet_title ). ELSE. lo_worksheet = ip_excel->get_active_worksheet( ). lo_worksheet->set_title( worksheet_title ). ENDIF. READ TABLE worksheets ASSIGNING <worksheet> WITH KEY id = sheet-id. " WRITE: / worksheet_id, worksheet_title, <worksheet>-target. CONCATENATE dirname <worksheet>-target INTO worksheet_path. load_worksheet( ip_path = worksheet_path io_worksheet = lo_worksheet ). node ?= node->get_next( ). ADD 1 TO workbook_index. ENDWHILE. "Can I reuse the workbook variable? "workbook = me->get_ixml_from_zip_archive( ip_path ). node ?= workbook->find_from_name( 'definedName' ). WHILE node IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = range ). range_value = node->get_value( ). lo_range = ip_excel->add_new_range( ). lo_range->name = range-name. lo_range->sheetid = range-localsheetid. " issue #163 lo_range->set_range_value( range_value ). node ?= node->get_next( ). ENDWHILE. endmethod. METHOD load_worksheet. TYPES: BEGIN OF t_cell, r TYPE string, t TYPE string, s TYPE string, END OF t_cell. TYPES: BEGIN OF t_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 t_column. TYPES: BEGIN OF t_sheetview, showgridlines TYPE zexcel_show_gridlines, tabselected TYPE string, zoomscalenormal TYPE string, workbookviewid TYPE string, showrowcolheaders TYPE string, END OF t_sheetview. TYPES: BEGIN OF t_mergecell, ref TYPE string, END OF t_mergecell. TYPES: BEGIN OF t_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 t_row. TYPES: BEGIN OF t_page_setup, id TYPE string, orientation TYPE string, scale TYPE string, END OF t_page_setup. TYPES: BEGIN OF t_page_margins, footer TYPE string, header TYPE string, bottom TYPE string, top TYPE string, right TYPE string, left TYPE string, END OF t_page_margins. TYPES: BEGIN OF t_sheetformatpr, customheight TYPE string, defaultrowheight TYPE string, customwidth TYPE string, defaultcolwidth TYPE string, END OF t_sheetformatpr. TYPES: BEGIN OF t_headerfooter, alignwithmargins TYPE string, differentoddeven TYPE string, END OF t_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'. CONSTANTS: 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: worksheet TYPE REF TO if_ixml_document, cells TYPE REF TO if_ixml_node_collection, iterator TYPE REF TO if_ixml_node_iterator, iterator2 TYPE REF TO if_ixml_node_iterator, row_elem TYPE REF TO if_ixml_element, cell_elem TYPE REF TO if_ixml_element, cell TYPE t_cell, index TYPE i, value_elem TYPE REF TO if_ixml_element, formula_elem TYPE REF TO if_ixml_element, cell_value TYPE zexcel_cell_value, cell_formula TYPE zexcel_cell_formula, cell_column TYPE zexcel_cell_column_alpha, cell_row TYPE zexcel_cell_row, style TYPE REF TO zcl_excel_style, style_guid TYPE zexcel_cell_style, sheetview_elem TYPE REF TO if_ixml_element, sheetview TYPE t_sheetview, pane_elem TYPE REF TO if_ixml_element, pane TYPE zexcel_pane, pane_cell_row_a TYPE string, pane_cell_row TYPE zexcel_cell_row, pane_cell_col_a TYPE zexcel_cell_column_alpha, pane_cell_col TYPE zexcel_cell_column, mergecells TYPE REF TO if_ixml_node_collection, mergecell_elem TYPE REF TO if_ixml_element, mergecell TYPE t_mergecell, merge_column_start TYPE zexcel_cell_column_alpha, merge_column_end TYPE zexcel_cell_column_alpha, merge_row_start TYPE zexcel_cell_row, merge_row_end TYPE zexcel_cell_row, sheetformatpr_elem TYPE REF TO if_ixml_element, sheetformatpr TYPE t_sheetformatpr, height TYPE float, width TYPE float, headerfooter_elem TYPE REF TO if_ixml_element, headerfooter TYPE t_headerfooter, odd_header TYPE zexcel_s_worksheet_head_foot, odd_footer TYPE zexcel_s_worksheet_head_foot, even_header TYPE zexcel_s_worksheet_head_foot, even_footer TYPE zexcel_s_worksheet_head_foot, hf_value_elem TYPE REF TO if_ixml_element, pagemargins_elem TYPE REF TO if_ixml_element, pagemargins TYPE t_page_margins, pagesetup_elem TYPE REF TO if_ixml_element, pagesetup TYPE t_page_setup, columns TYPE REF TO if_ixml_node_collection, column_elem TYPE REF TO if_ixml_element, column TYPE t_column, column_alpha TYPE zexcel_cell_column_alpha, column_dimension TYPE REF TO zcl_excel_worksheet_columndime, outline_level TYPE int4, lr_tabcolor TYPE REF TO if_ixml_element, ls_tabcolor type lty_tabcolor, ls_excel_s_tabcolor type zexcel_s_tabcolor, rows TYPE REF TO if_ixml_node_collection, row TYPE t_row, max_col TYPE i, "for use with SPANS element min_col TYPE i, "for use with SPANS element max_col_s TYPE char10, "for use with SPANS element min_col_s TYPE char10, "for use with SPANS element row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, path TYPE string, node TYPE REF TO if_ixml_element, relationship TYPE t_relationship, rels_worksheet TYPE REF TO if_ixml_document, rels_worksheet_path TYPE string, stripped_name TYPE chkfile, dirname TYPE string. " 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_worksheet_path. rels_worksheet = me->get_ixml_from_zip_archive( rels_worksheet_path ). node ?= rels_worksheet->find_from_name( 'Relationship' ). WHILE node IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). CONCATENATE dirname relationship-target INTO path. path = resolve_path( path ). CASE relationship-type. WHEN lc_rel_drawing. " Read Drawings CALL METHOD me->load_worksheet_drawing EXPORTING ip_path = path io_worksheet = io_worksheet. WHEN lc_rel_printer. " Read Printer settings WHEN OTHERS. ENDCASE. node ?= node->get_next( ). ENDWHILE. worksheet = me->get_ixml_from_zip_archive( ip_path ). lr_tabcolor ?= worksheet->find_from_name( 'tabColor' ). IF lr_tabcolor IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = lr_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. rows = worksheet->get_elements_by_tag_name( name = 'row' ). iterator = rows->create_iterator( ). row_elem ?= iterator->get_next( ). WHILE row_elem IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = row_elem CHANGING cp_structure = row ). SPLIT row-spans AT ':' INTO min_col_s max_col_s. index = max_col_s. IF index > max_col. max_col = index. ENDIF. cell_row = row-r. IF row-customheight = '1' OR row-collapsed = lc_xml_attr_true OR row-collapsed = lc_xml_attr_true_int OR row-hidden = lc_xml_attr_true OR row-hidden = lc_xml_attr_true_int OR row-outlinelevel > '0'. row_dimension = io_worksheet->get_row_dimension( cell_row ). IF row-customheight = '1'. row_dimension->set_row_height( row-ht ). ENDIF. IF row-collapsed = lc_xml_attr_true OR row-collapsed = lc_xml_attr_true_int. row_dimension->set_collapsed( abap_true ). ENDIF. IF row-hidden = lc_xml_attr_true OR row-hidden = lc_xml_attr_true_int. row_dimension->set_visible( abap_false ). ENDIF. IF row-outlinelevel > ''. * outline_level = condense( row-outlineLevel ). "For basis 7.02 and higher CONDENSE row-outlinelevel. outline_level = row-outlinelevel. IF outline_level > 0. row_dimension->set_outline_level( outline_level ). ENDIF. ENDIF. ENDIF. cells = row_elem->get_elements_by_tag_name( name = 'c' ). iterator2 = cells->create_iterator( ). cell_elem ?= iterator2->get_next( ). WHILE cell_elem IS BOUND. CLEAR: cell_value, cell_formula, style_guid. fill_struct_from_attributes( EXPORTING ip_element = cell_elem CHANGING cp_structure = cell ). value_elem = cell_elem->find_from_name( name = 'v' ). CASE cell-t. WHEN 's'. " String values are stored as index in shared string table index = value_elem->get_value( ) + 1. READ TABLE shared_strings INTO cell_value INDEX index. WHEN 'inlineStr'. " inlineStr values are kept in special node value_elem = cell_elem->find_from_name( name = 'is' ). IF value_elem IS BOUND. cell_value = value_elem->get_value( ). ENDIF. WHEN OTHERS. "other types are stored directly IF value_elem IS BOUND. cell_value = value_elem->get_value( ). ENDIF. ENDCASE. CLEAR style_guid. "read style based on index IF cell-s IS NOT INITIAL. index = cell-s + 1. READ TABLE styles INTO style INDEX index. IF sy-subrc = 0. style_guid = style->get_guid( ). ENDIF. ENDIF. formula_elem = cell_elem->find_from_name( name = 'f' ). IF formula_elem IS BOUND. cell_formula = formula_elem->get_value( ). ENDIF. IF NOT cell_value IS INITIAL OR NOT cell_formula IS INITIAL OR style_guid IS NOT INITIAL. zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING i_columnrow = cell-r IMPORTING e_column = cell_column e_row = cell_row ). io_worksheet->set_cell( ip_column = cell_column " cell_elem Column ip_row = cell_row " cell_elem row_elem ip_value = cell_value " cell_elem Value ip_formula = cell_formula ip_data_type = cell-t ip_style = style_guid ). ENDIF. cell_elem ?= iterator2->get_next( ). ENDWHILE. row_elem ?= iterator->get_next( ). ENDWHILE. "Get the customized column width columns = worksheet->get_elements_by_tag_name( name = 'col' ). iterator = columns->create_iterator( ). column_elem ?= iterator->get_next( ). WHILE column_elem IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = column_elem CHANGING cp_structure = column ). column_elem ?= iterator->get_next( ). IF column-customwidth = lc_xml_attr_true OR column-customwidth = lc_xml_attr_true_int OR column-bestfit = lc_xml_attr_true OR column-bestfit = lc_xml_attr_true_int OR column-collapsed = lc_xml_attr_true OR column-collapsed = lc_xml_attr_true_int OR column-hidden = lc_xml_attr_true OR column-hidden = lc_xml_attr_true_int OR column-outlinelevel > '' OR column-style > ''. index = column-min. WHILE index <= column-max AND index <= max_col. column_alpha = zcl_excel_common=>convert_column2alpha( index ). column_dimension = io_worksheet->get_column_dimension( column_alpha ). IF column-customwidth = lc_xml_attr_true OR column-customwidth = lc_xml_attr_true_int. column_dimension->set_width( column-width ). ENDIF. IF column-bestfit = lc_xml_attr_true OR column-bestfit = lc_xml_attr_true_int. column_dimension->set_auto_size( abap_true ). ENDIF. IF column-collapsed = lc_xml_attr_true OR column-collapsed = lc_xml_attr_true_int. column_dimension->set_collapsed( abap_true ). ENDIF. IF column-hidden = lc_xml_attr_true OR column-hidden = lc_xml_attr_true_int. column_dimension->set_visible( abap_false ). ENDIF. IF column-outlinelevel > ''. * outline_level = condense( column-outlineLevel ). CONDENSE column-outlinelevel. outline_level = outline_level. IF outline_level > 0. column_dimension->set_outline_level( outline_level ). ENDIF. ENDIF. IF column-style > ''. sy-index = column-style + 1. READ TABLE styles INTO style INDEX sy-index. DATA: dummy_zexcel_cell_style TYPE zexcel_cell_style. dummy_zexcel_cell_style = style->get_guid( ). column_dimension->set_column_style_by_guid( dummy_zexcel_cell_style ). ENDIF. ADD 1 TO 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 sheetview_elem = worksheet->find_from_name( name = 'sheetView' ). fill_struct_from_attributes( EXPORTING ip_element = sheetview_elem CHANGING cp_structure = sheetview ). IF sheetview-showgridlines IS INITIAL OR sheetview-showgridlines = lc_xml_attr_true OR sheetview-showgridlines = lc_xml_attr_true_int. "If the attribute is not specified or set to true, we will show grid lines sheetview-showgridlines = abap_true. ELSE. sheetview-showgridlines = abap_false. ENDIF. io_worksheet->set_show_gridlines( sheetview-showgridlines ). "Add merge cell information mergecells = worksheet->get_elements_by_tag_name( name = 'mergeCell' ). iterator = mergecells->create_iterator( ). mergecell_elem ?= iterator->get_next( ). WHILE mergecell_elem IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = mergecell_elem CHANGING cp_structure = mergecell ). zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = mergecell-ref IMPORTING e_column_start = merge_column_start e_column_end = merge_column_end e_row_start = merge_row_start e_row_end = merge_row_end ). mergecell_elem ?= iterator->get_next( ). io_worksheet->set_merge( EXPORTING ip_column_start = merge_column_start ip_column_end = merge_column_end ip_row = merge_row_start ip_row_to = merge_row_end ). ENDWHILE. " read sheet format properties sheetformatpr_elem = worksheet->find_from_name( 'sheetFormatPr' ). IF sheetformatpr_elem IS NOT INITIAL. fill_struct_from_attributes( EXPORTING ip_element = sheetformatpr_elem CHANGING cp_structure = sheetformatpr ). IF sheetformatpr-customheight = '1'. height = sheetformatpr-defaultrowheight. row_dimension = io_worksheet->get_default_row_dimension( ). row_dimension->set_row_height( height ). ENDIF. " TODO... column ENDIF. " Read in page margins pagemargins_elem = worksheet->find_from_name( 'pageMargins' ). IF pagemargins_elem IS NOT INITIAL. fill_struct_from_attributes( EXPORTING ip_element = pagemargins_elem CHANGING cp_structure = pagemargins ). io_worksheet->sheet_setup->margin_bottom = pagemargins-bottom. io_worksheet->sheet_setup->margin_footer = pagemargins-footer. io_worksheet->sheet_setup->margin_header = pagemargins-header. io_worksheet->sheet_setup->margin_left = pagemargins-left. io_worksheet->sheet_setup->margin_right = pagemargins-right. io_worksheet->sheet_setup->margin_top = pagemargins-top. ENDIF. " Read in page setup pagesetup_elem = worksheet->find_from_name( 'pageSetup' ). IF pagesetup_elem IS NOT INITIAL. fill_struct_from_attributes( EXPORTING ip_element = pagesetup_elem CHANGING cp_structure = pagesetup ). io_worksheet->sheet_setup->orientation = pagesetup-orientation. io_worksheet->sheet_setup->scale = pagesetup-scale. ENDIF. " Read header footer headerfooter_elem = worksheet->find_from_name( 'headerFooter' ). IF headerfooter_elem IS NOT INITIAL. fill_struct_from_attributes( EXPORTING ip_element = headerfooter_elem CHANGING cp_structure = headerfooter ). io_worksheet->sheet_setup->diff_oddeven_headerfooter = headerfooter-differentoddeven. hf_value_elem = headerfooter_elem->find_from_name( 'oddFooter' ). IF hf_value_elem IS NOT INITIAL. odd_footer-left_value = hf_value_elem->get_value( ). ENDIF. " TODO.. get the rest. io_worksheet->sheet_setup->set_header_footer( ip_odd_header = odd_header ip_odd_footer = odd_footer ip_even_header = even_header ip_even_footer = even_footer ). ENDIF. " Start fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 " Read pane pane_elem = sheetview_elem->find_from_name( name = 'pane' ). IF pane_elem IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = pane_elem CHANGING cp_structure = pane ). FIND REGEX '^(\w+)(\d+)$' IN pane-topleftcell SUBMATCHES pane_cell_col_a pane_cell_row_a. pane_cell_row = pane_cell_row_a. pane_cell_col = zcl_excel_common=>convert_column2int( pane_cell_col_a ). SUBTRACT 1 FROM: pane_cell_col, pane_cell_row. IF pane_cell_col > 0 AND pane_cell_row > 0. io_worksheet->freeze_panes( ip_num_rows = pane_cell_row ip_num_columns = pane_cell_col ). ELSEIF pane_cell_row > 0. io_worksheet->freeze_panes( ip_num_rows = pane_cell_row ). ELSE. io_worksheet->freeze_panes( ip_num_columns = 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 ). 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. 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. DATA: lt_segments TYPE TABLE OF string, lv_segment TYPE string, lv_count TYPE i. SPLIT ip_path AT '/' INTO TABLE lt_segments. lv_count = lines( lt_segments ). WHILE lv_count > 0. READ TABLE lt_segments INTO lv_segment INDEX lv_count. IF lv_segment = '..'. SUBTRACT 1 FROM lv_count. ELSE. IF strlen( rp_result ) > 0. CONCATENATE '/' rp_result INTO rp_result. ENDIF. CONCATENATE lv_segment rp_result INTO rp_result. ENDIF. SUBTRACT 1 FROM lv_count. ENDWHILE. endmethod.