class ZCL_EXCEL_READER_2007 definition public final create public . *"* public components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! public section. interfaces ZIF_EXCEL_READER . *"* protected components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! protected section. *"* private components of class ZCL_EXCEL_READER_2007 *"* do not include other source files here!!! private section. data EXCEL2007 type XSTRING . data ZIP type ref to CL_ABAP_ZIP . 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 . *"* local class implementation for public class *"* use this source file for the implementation part of *"* local helper classes *"* use this source file for any type declarations (class *"* definitions, interfaces or data types) you need for method *"* implementation or private method's signature TYPES: BEGIN OF t_splice_entry, name TYPE string, offset TYPE i, length TYPE i, compressed TYPE i, END OF t_splice_entry. TYPES: t_splice_entries TYPE STANDARD TABLE OF t_splice_entry WITH DEFAULT KEY. *"* use this source file for any macro definitions you need *"* in the implementation part of the class method ZIF_EXCEL_READER~LOAD. TYPES: BEGIN OF t_worksheet, id TYPE string, target TYPE string, END OF t_worksheet. TYPES: t_worksheets TYPE TABLE OF t_worksheet. 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_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_relationships TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'. TYPE-POOLS: ixml. DATA: rels TYPE REF TO if_ixml_document, rels_coll TYPE REF TO if_ixml_node_collection, rels_coll_index TYPE i, workbook_path TYPE string, rels_workbook_path TYPE string, rels_workbook TYPE REF TO if_ixml_document, rels_wb_coll TYPE REF TO if_ixml_node_collection, rels_wb_coll_index TYPE i, shared_strings_path TYPE string, shared_strings TYPE REF TO if_ixml_document, shared_strings_coll TYPE REF TO if_ixml_node_collection, shared_strings_coll_index TYPE i, worksheets TYPE t_worksheets, workbook TYPE REF TO if_ixml_document, workbook_coll TYPE REF TO if_ixml_node_collection, workbook_index TYPE i, worksheet_path TYPE string, worksheet TYPE REF TO if_ixml_document, worksheet_coll TYPE REF TO if_ixml_node_collection, worksheet_index TYPE i. FIELD-SYMBOLS: <worksheet> TYPE t_worksheet. DATA: node TYPE REF TO if_ixml_node, value_elem TYPE REF TO if_ixml_element, formula_elem TYPE REF TO if_ixml_element, si TYPE REF TO if_ixml_node_list, row TYPE REF TO if_ixml_node_list, row_iterator TYPE REF TO if_ixml_node_iterator, cell TYPE REF TO if_ixml_element, attributes TYPE REF TO if_ixml_named_node_map, attribute TYPE REF TO if_ixml_node, col_attributes TYPE REF TO if_ixml_named_node_map, attr_type TYPE string, attr_target TYPE string, attr_id TYPE string, tag_name TYPE string, r TYPE string, cell_data_type TYPE string, cell_column TYPE zexcel_cell_column_alpha, cell_row TYPE zexcel_cell_row, value TYPE string, values TYPE stringtab, value_index TYPE i, cell_value TYPE zexcel_cell_value, cell_formula TYPE zexcel_cell_formula, stripped_name TYPE chkfile, dirname TYPE string. DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, worksheet_title TYPE zexcel_sheet_title, worksheet_id TYPE string. me->excel2007 = i_excel2007. rels = me->get_ixml_from_zip_archive( '_rels/.rels' ). CREATE OBJECT r_excel. rels_coll = rels->get_elements_by_tag_name( name = 'Relationship' ). rels_coll_index = 0. WHILE rels_coll_index < rels_coll->get_length( ). node = rels_coll->get_item( rels_coll_index ). rels_coll_index = rels_coll_index + 1. attributes ?= node->get_attributes( ). attribute ?= attributes->get_named_item_ns( 'Type' ). attr_type = attribute->get_value( ). CASE attr_type. WHEN lc_core_properties. " TODO Map Document Properties to ZCL_EXCEL WHEN lc_office_document. attribute ?= attributes->get_named_item_ns( 'Target' ). workbook_path = attribute->get_value( ). CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' EXPORTING full_name = workbook_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 ). rels_wb_coll = rels_workbook->get_elements_by_tag_name( name = 'Relationship' ). rels_wb_coll_index = 0. WHILE rels_wb_coll_index < rels_wb_coll->get_length( ). node = rels_wb_coll->get_item( rels_wb_coll_index ). rels_wb_coll_index = rels_wb_coll_index + 1. attributes ?= node->get_attributes( ). attribute ?= attributes->get_named_item_ns( 'Type' ). attr_type = attribute->get_value( ). CASE attr_type. WHEN lc_shared_strings. " Read Shared Strings attribute ?= attributes->get_named_item_ns( 'Target' ). attr_target = attribute->get_value( ). CONCATENATE dirname attr_target INTO shared_strings_path. shared_strings = me->get_ixml_from_zip_archive( shared_strings_path ). shared_strings_coll = shared_strings->get_elements_by_tag_name( name = 'si' ). shared_strings_coll_index = 0. WHILE shared_strings_coll_index < shared_strings_coll->get_length( ). node = shared_strings_coll->get_item( shared_strings_coll_index ). shared_strings_coll_index = shared_strings_coll_index + 1. si = node->get_children( ). node = si->get_item( 0 ). tag_name = node->get_name( ). IF tag_name = 't'. value = node->get_value( ). APPEND value TO values. ELSEIF tag_name = 'r'. " TODO pharse Ritch text ENDIF. ENDWHILE. WHEN lc_worksheet. " Read worksheets APPEND INITIAL LINE TO worksheets ASSIGNING <worksheet>. attribute ?= attributes->get_named_item_ns( 'Id' ). <worksheet>-id = attribute->get_value( ). attribute ?= attributes->get_named_item_ns( 'Target' ). <worksheet>-target = attribute->get_value( ). " WRITE: / <worksheet>-id, ':', <worksheet>-target. WHEN OTHERS. ENDCASE. ENDWHILE. " Read Workbook workbook = me->get_ixml_from_zip_archive( workbook_path ). workbook_coll = workbook->get_elements_by_tag_name( name = 'sheet' ). workbook_index = 0. WHILE workbook_index < workbook_coll->get_length( ). node = workbook_coll->get_item( workbook_index ). workbook_index = workbook_index + 1. attributes ?= node->get_attributes( ). attribute ?= attributes->get_named_item_ns( 'name' ). worksheet_title = attribute->get_value( ). IF workbook_index > 1. lo_worksheet = r_excel->add_new_worksheet( worksheet_title ). ELSE. lo_worksheet = r_excel->get_active_worksheet( ). lo_worksheet->set_title( worksheet_title ). ENDIF. attribute ?= attributes->get_named_item_ns( name = 'id' uri = lc_relationships ). worksheet_id = attribute->get_value( ). READ TABLE worksheets ASSIGNING <worksheet> WITH KEY id = worksheet_id. " WRITE: / worksheet_id, worksheet_title, <worksheet>-target. CONCATENATE dirname <worksheet>-target INTO worksheet_path. worksheet = me->get_ixml_from_zip_archive( worksheet_path ). worksheet_coll = worksheet->get_elements_by_tag_name( name = 'row' ). worksheet_index = 0. WHILE worksheet_index < worksheet_coll->get_length( ). node = worksheet_coll->get_item( worksheet_index ). worksheet_index = worksheet_index + 1. row = node->get_children( ). row_iterator = row->create_iterator( ). cell ?= row_iterator->get_next( ). WHILE NOT cell IS INITIAL. col_attributes = cell->get_attributes( ). attribute ?= col_attributes->get_named_item_ns( 'r' ). r = attribute->get_value( ). CLEAR: cell_data_type, cell_value, cell_formula. attribute ?= col_attributes->get_named_item_ns( 't' ). IF attribute IS BOUND. cell_data_type = attribute->get_value( ). ENDIF. value_elem = cell->find_from_name( name = 'v' ). CASE cell_data_type. WHEN 's'. " String values are stored as index in shared string table value_index = value_elem->get_value( ) + 1. READ TABLE values INTO cell_value INDEX value_index. WHEN 'inlineStr'. " inlineStr values are kept in special node value_elem = cell->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. formula_elem = cell->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. zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING i_columnrow = r IMPORTING e_column = cell_column e_row = cell_row ). lo_worksheet->set_cell( EXPORTING ip_column = cell_column " Cell Column ip_row = cell_row " Cell Row ip_value = cell_value " Cell Value ip_formula = cell_formula ip_data_type = cell_data_type ). ENDIF. cell ?= row_iterator->get_next( ). ENDWHILE. ENDWHILE. ENDWHILE. WHEN OTHERS. ENDCASE. 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 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.