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 SECTION. *"* protected components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! 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, 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. 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 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 . METHODS load_worksheet IMPORTING !ip_path TYPE string !io_worksheet TYPE REF TO zcl_excel_worksheet . METHODS load_shared_strings IMPORTING !ip_path TYPE string . METHODS load_styles IMPORTING !ip_path TYPE string !ip_excel TYPE REF TO zcl_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~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_validating( mode = if_ixml_parser=>co_no_validation ). parser->parse( ). endmethod. method LOAD_SHARED_STRINGS. DATA: value 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. shared_strings_xml = me->get_ixml_from_zip_archive( ip_path ). 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'. value = node2->get_value( ). APPEND value TO shared_strings. ELSEIF tag_name = 'r'. " TODO pharse Ritch text 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. 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->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, 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. CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', lc_xml_attr_true_int TYPE string VALUE '1'. DATA: worksheet TYPE REF TO if_ixml_document, rows TYPE REF TO if_ixml_node_collection, 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 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, 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, 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. worksheet = me->get_ixml_from_zip_archive( ip_path ). rows = worksheet->get_elements_by_tag_name( name = 'row' ). iterator = rows->create_iterator( ). row ?= iterator->get_next( ). WHILE row IS BOUND. cells = row->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 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 ?= 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. 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_width( column-width ). 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. endmethod.