From 82c6b78f090fa7e45c73fbc8b675cc893864dcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Schm=C3=B6cker?= Date: Sun, 18 Nov 2012 19:21:01 +0000 Subject: [PATCH] issue #234 : We may not ship patched copy of CL_ABAP_ZIP. Removed from trunk and switched coding to dynamic methodcalls. git-svn-id: https://subversion.assembla.com/svn/abap2xlsx/trunk@365 b7d68dce-7c3c-4a99-8ce0-9ea847f5d049 --- ZA2X/CLAS/ZCL_EXCEL_ABAP_ZIP.slnk | 929 --------------------------- ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk | 145 +++-- ZA2X/CLAS/ZCX_EXCEL.slnk | 43 +- ZA2X/INTF/ZIF_EXCEL_READER.slnk | 6 +- ZA2X/PROG/ZDEMO_EXCEL37.slnk | 19 +- 5 files changed, 129 insertions(+), 1013 deletions(-) delete mode 100644 ZA2X/CLAS/ZCL_EXCEL_ABAP_ZIP.slnk diff --git a/ZA2X/CLAS/ZCL_EXCEL_ABAP_ZIP.slnk b/ZA2X/CLAS/ZCL_EXCEL_ABAP_ZIP.slnk deleted file mode 100644 index 3952dc3..0000000 --- a/ZA2X/CLAS/ZCL_EXCEL_ABAP_ZIP.slnk +++ /dev/null @@ -1,929 +0,0 @@ - - - - - - - - - class ZCL_EXCEL_ABAP_ZIP definition - public - final - create public . - -*"* public components of class ZCL_EXCEL_ABAP_ZIP -*"* do not include other source files here!!! -public section. - type-pools IHTTP . - - types: - BEGIN OF T_FILE, - name TYPE string, - date TYPE d, - time TYPE t, - size TYPE i, - END OF T_FILE . - types: - T_FILES TYPE TABLE OF T_FILE . - 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 . - - data FILES type T_FILES read-only . - type-pools ABAP . - data SUPPORT_UNICODE_NAMES type ABAP_BOOL value ABAP_FALSE. "#EC NOTEXT . - - methods LOAD - importing - !ZIP type XSTRING - exceptions - ZIP_PARSE_ERROR . - methods SAVE - returning - value(ZIP) type XSTRING . - methods GET - importing - !NAME type STRING optional - value(INDEX) type I default 0 - exporting - !CONTENT type XSTRING - exceptions - ZIP_INDEX_ERROR - ZIP_DECOMPRESSION_ERROR . - methods ADD - importing - !NAME type STRING - !CONTENT type XSEQUENCE . - methods DELETE - importing - !NAME type STRING optional - value(INDEX) type I default 0 - exceptions - ZIP_INDEX_ERROR . - class-methods CRC32 - importing - !CONTENT type XSTRING - returning - value(CRC32) type I . - class-methods SPLICE - importing - !ZIP type XSTRING - returning - value(ENTRIES) type T_SPLICE_ENTRIES . - *"* protected components of class CL_ABAP_ZIP -*"* do not include other source files here!!! -protected section. - *"* private components of class CL_ABAP_ZIP -*"* do not include other source files here!!! -private section. - - types: - BEGIN OF T_EXT, - min_extract_version TYPE i, - gen_flags TYPE i, - compressed TYPE i, - compsize TYPE i, - crc32(4) TYPE x, - filename_len TYPE i, - filename TYPE xstring, - extra_len TYPE i, - extra TYPE xstring, - content TYPE xstring, - END OF T_EXT . - types: - T_EXTS TYPE TABLE OF T_EXT . - - data EXTS type T_EXTS . - class-data CRC32_MAP type XSTRING . - CLASS msdos IMPLEMENTATION. - - - METHOD from_date. " IMPORTING msdos_date TYPE i RETURNING value(date) TYPE d - -* MS-DOS format for date: -* Bits 15:9 = year - 1980 -* Bits 8:5 = month of year -* Bits 4:0 = day of month - - CONSTANTS: mFE00(2) TYPE x VALUE 'FE00', - m01E0(2) TYPE x VALUE '01E0', - m001F(2) TYPE x VALUE '001F'. - - DATA: x(2) TYPE x, - year TYPE i, - month TYPE i, - day TYPE i, - c4(4) TYPE c, - str TYPE string. - -* Bits 15:9 = year - 1980 - x = msdos_date. - x = x BIT-AND mFE00. - x = x DIV 512. " >> 9 - x = x BIT-AND m001F. - year = x. - year = year + 1980. - WRITE year TO c4 USING EDIT MASK 'RR____'. - CONCATENATE str c4 INTO str. - -* Bits 8:5 = month of year - x = msdos_date. - x = x BIT-AND m01E0. - x = x DIV 32. " >> 5 - x = x BIT-AND m001F. - month = x. - WRITE month TO c4 USING EDIT MASK 'RR__'. - CONCATENATE str c4 INTO str. - -* Bits 4:0 = day of month - x = msdos_date. - x = x BIT-AND m001F. - day = x. - WRITE day TO c4 USING EDIT MASK 'RR__'. - CONCATENATE str c4 INTO str. - -* Build date - TRANSLATE str USING ' 0'. - date = str. - - ENDMETHOD. - - - METHOD from_time. " IMPORTING msdos_time TYPE i RETURNING value(time) TYPE t. - -* MS-DOS format for time: -* Bits 15:11 = hour (24-hour clock) -* Bits 10:5 = minute -* Bits 4:0 = second/2 - - CONSTANTS: mF100(2) TYPE x VALUE 'F100', - m07E0(2) TYPE x VALUE '07E0', - m003F(2) TYPE x VALUE '003F', - m001F(2) TYPE x VALUE '001F'. - - DATA: x(2) TYPE x, - hour TYPE i, - min TYPE i, - c4(4) TYPE c, - str TYPE string. - -* Bits 15:11 = hour (24-hour clock) - x = msdos_time. - x = x BIT-AND mF100. - x = x DIV 2048. " >> 11 - x = x BIT-AND m001F. - hour = x. - WRITE hour TO c4 USING EDIT MASK 'RR__'. - CONCATENATE str c4 INTO str. - -* Bits 10:5 = minute - x = msdos_time. - x = x BIT-AND m07E0. - x = x DIV 32. " >> 5 - x = x BIT-AND m003F. - min = x. - WRITE min TO c4 USING EDIT MASK 'RR__'. - CONCATENATE str c4 INTO str. - -* Bits 4:0 = second/2 - CONCATENATE str '00' INTO str. - -* Build time - TRANSLATE str USING ' 0'. - time = str. - - ENDMETHOD. - - - METHOD to_date. " IMPORTING date TYPE d RETURNING value(msdos_date) TYPE i. - -* MS-DOS format for date: -* Bits 15:9 = year - 1980 -* Bits 8:5 = month of year -* Bits 4:0 = day of month - - DATA: xdate(2) TYPE x, - x(2) TYPE x, - year TYPE i, - month TYPE i, - day TYPE i. - -* Bits 15:9 = year - 1980 - year = date+0(4). - x = year - 1980. - x = x * 512. " << 9 - xdate = xdate BIT-OR x. - -* Bits 8:5 = month of year - month = date+4(2). - x = month. - x = x * 32. " << 5 - xdate = xdate BIT-OR x. - -* Bits 4:0 = day of month - day = date+6(2). - x = day. - xdate = xdate BIT-OR x. - - msdos_date = xdate. - - ENDMETHOD. - - - METHOD to_time. " IMPORTING time TYPE t RETURNING value(msdos_time) TYPE i. - -* MS-DOS format for time: -* Bits 15:11 = hour (24-hour clock) -* Bits 10:5 = minute -* Bits 4:0 = second/2 - - DATA: xtime(2) TYPE x, - x(2) TYPE x, - hour TYPE i, - min TYPE i, - sec TYPE i. - -* Bits 15:11 = hour (24-hour clock) - hour = time+0(2). - x = hour. - x = x * 2048. " << 11 - xtime = xtime BIT-OR x. - -* Bits 10:5 = minute - min = time+2(2). - x = min. - x = x * 32. " << 5 - xtime = xtime BIT-OR x. - -* Bits 4:0 = seconds - sec = time+4(2). - x = sec / 2. - xtime = xtime BIT-OR x. - - msdos_time = xtime. - - ENDMETHOD. - - -ENDCLASS. - CLASS msdos DEFINITION FINAL. - PUBLIC SECTION. - CLASS-METHODS: to_date IMPORTING date TYPE d RETURNING value(msdos_date) TYPE i. - CLASS-METHODS: to_time IMPORTING time TYPE t RETURNING value(msdos_time) TYPE i. - CLASS-METHODS: from_date IMPORTING msdos_date TYPE i RETURNING value(date) TYPE d. - CLASS-METHODS: from_time IMPORTING msdos_time TYPE i RETURNING value(time) TYPE t. -ENDCLASS. - *"* use this source file for any macro definitions you need -*"* in the implementation part of the class - - - ABAP - IHTTP - - - - - - - - METHOD ADD. - - FIELD-SYMBOLS: <file> TYPE t_file, - <ext> TYPE t_ext. - - APPEND INITIAL LINE TO files ASSIGNING <file>. - APPEND INITIAL LINE TO exts ASSIGNING <ext>. - - <file>-name = name. - <file>-date = sy-datum. - <file>-time = sy-uzeit. - <file>-size = XSTRLEN( content ). - -* general purpose flag bit 11 (Language encoding flag (EFS) - CONSTANTS: gen_flags_unicode(2) TYPE x VALUE '0800'. -* see: http://www.pkware.com/documents/casestudies/APPNOTE.TXT, APPENDIX D -* zip normaly used IBM Code Page 437 mapped to SAP Printer EPESCP IBM 437 - - DATA: conv TYPE REF TO cl_abap_conv_out_ce, - conv_cp437 TYPE REF TO cl_abap_conv_out_ce, - conv_utf8 TYPE REF TO cl_abap_conv_out_ce, - cp437 TYPE abap_encoding value '1142', " IBM 437 - utf8 TYPE abap_encoding value '4110'. " UTF-8 - if support_unicode_names = abap_true. - conv = cl_abap_conv_out_ce=>create( encoding = utf8 - ignore_cerr = abap_true - replacement = '#' ). - else. - conv = cl_abap_conv_out_ce=>create( encoding = cp437 - ignore_cerr = abap_true - replacement = '#' ). - endif. - conv->convert( EXPORTING data = <file>-name IMPORTING buffer = <ext>-filename ). - <ext>-filename_len = XSTRLEN( <ext>-filename ). - <ext>-extra_len = 0. - <ext>-extra = ''. - <ext>-min_extract_version = 20. - if support_unicode_names = abap_true. - <ext>-gen_flags = gen_flags_unicode. - else. - <ext>-gen_flags = 0. - endif. - - IF <file>-size > 0. - <ext>-compressed = 8. " gzip Deflate - <ext>-crc32 = crc32( content ). - cl_abap_gzip=>compress_binary( - EXPORTING raw_in = content - raw_in_len = <file>-size - IMPORTING gzip_out = <ext>-content - gzip_out_len = <ext>-compsize ). - ELSE. " folder - <ext>-compressed = 0. " gzip Stored - <ext>-crc32 = 0. - <ext>-compsize = 0. - ENDIF. - -ENDMETHOD. - - - - - METHOD CRC32. - -* Let us ask our friendly neighbour whether there is a CRC32 in the kernel (thanks guys!) - IF cl_http_utility=>is_ict_system_call_implemented( ihttp_scid_crc32_checksum ) IS INITIAL. - SYSTEM-CALL ict "#EC CI_SYSTEMCALL - DID - ihttp_scid_crc32_checksum - PARAMETERS - content " > xstr - crc32. " < unsigned int - RETURN. - ENDIF. - -* Do the calculations by hand. This is going to be slow. This is going to be a pain. -* What is a man to do? - - CONSTANTS: magic_nr(4) TYPE x VALUE 'EDB88320', - mFFFFFFFF(4) TYPE x VALUE 'FFFFFFFF', - m7FFFFFFF(4) TYPE x VALUE '7FFFFFFF', - m00FFFFFF(4) TYPE x VALUE '00FFFFFF', - m000000FF(4) TYPE x VALUE '000000FF', - m000000(3) TYPE x VALUE '000000'. - - IF XSTRLEN( crc32_map ) = 0. - DO 256 TIMES. - DATA: c(4) TYPE x, low_bit(4) TYPE x. - c = sy-index - 1. - DO 8 TIMES. - low_bit = '00000001'. low_bit = c BIT-AND low_bit. " c & 1 - c = c DIV 2. c = c BIT-AND m7FFFFFFF. " c >> 1 (top is zero, but in ABAP signed!) - IF low_bit IS NOT INITIAL. - c = c BIT-XOR magic_nr. - ENDIF. - ENDDO. - CONCATENATE crc32_map c INTO crc32_map IN BYTE MODE. - ENDDO. - ENDIF. - - DATA: len TYPE i, n TYPE i. "#EC * - DATA: crc(4) TYPE x VALUE mFFFFFFFF, x4(4) TYPE x, idx(4) TYPE x. - - len = XSTRLEN( content ). - DO len TIMES. - n = sy-index - 1. - CONCATENATE m000000 content+n(1) INTO idx IN BYTE MODE. - idx = ( crc BIT-XOR idx ) BIT-AND m000000FF. - idx = idx * 4. - x4 = crc32_map+idx(4). - crc = crc DIV 256. crc = crc BIT-AND m00FFFFFF. " c >> 8 - crc = x4 BIT-XOR crc. - ENDDO. - crc = crc BIT-XOR mFFFFFFFF. - - crc32 = crc. - -ENDMETHOD. - - - - - - METHOD DELETE. - - IF index = 0. - READ TABLE files TRANSPORTING NO FIELDS WITH KEY name = name. - IF sy-subrc IS NOT INITIAL. - RAISE zip_index_error. "#EC RAISE_OK - ENDIF. - index = sy-tabix. - ENDIF. - - IF index < 1 OR index > LINES( files ). - RAISE zip_index_error. "#EC RAISE_OK - ENDIF. - - DELETE files INDEX index. - DELETE exts INDEX index. - -ENDMETHOD. - - - - - - - - METHOD GET. - - FIELD-SYMBOLS: <ext> TYPE t_ext. - - IF index IS INITIAL. - READ TABLE files TRANSPORTING NO FIELDS WITH KEY name = name. - IF sy-subrc IS NOT INITIAL. - RAISE zip_index_error. "#EC RAISE_OK - ENDIF. - index = sy-tabix. - ENDIF. - - IF index < 1 OR index > LINES( files ). - RAISE zip_index_error. "#EC RAISE_OK - ENDIF. - - READ TABLE exts INDEX index ASSIGNING <ext>. - - IF <ext>-compressed IS INITIAL. - content = <ext>-content. - ELSE. - cl_abap_gzip=>decompress_binary( - EXPORTING gzip_in = <ext>-content - gzip_in_len = <ext>-compsize - IMPORTING raw_out = content ). - ENDIF. - - IF crc32( content ) <> <ext>-crc32. - RAISE zip_decompression_error. "#EC RAISE_OK - ENDIF. - -ENDMETHOD. - - - - - METHOD load. - -* Documentation from: http://www.pkware.com/company/standards/appnote/appnote.txt - -* Start to decode new ZIP file - CLEAR: files, exts. - REFRESH: files, exts. - -* Global offset for moving through file - DATA: offset TYPE i. - - DEFINE next. " move offset - offset = offset + &1. - END-OF-DEFINITION. - -* DATA: l1(1) TYPE x, h1(1) TYPE x, l2(1) TYPE x, h2(1) TYPE x, xstr TYPE xstring. - DATA: w2(2) TYPE x, w4(4) TYPE x, xstr TYPE xstring. - DEFINE read2. " read two bytes as integer and move offset -* l1 = zip+offset(1). offset = offset + 1. -* h1 = zip+offset(1). offset = offset + 1. -* CONCATENATE h1 l1 INTO xstr IN BYTE MODE. - w2 = zip+offset(2). - offset = offset + 2. - concatenate w2+1(1) w2+0(1) into xstr in byte mode. - &1 = xstr. - END-OF-DEFINITION. - - DEFINE read4. " read four bytes as integer and move offset -* l1 = zip+offset(1). offset = offset + 1. -* h1 = zip+offset(1). offset = offset + 1. -* l2 = zip+offset(1). offset = offset + 1. -* h2 = zip+offset(1). offset = offset + 1. -* CONCATENATE h2 l2 h1 l1 INTO xstr IN BYTE MODE. - w4 = zip+offset(4). - offset = offset + 4. - concatenate w4+3(1) w4+2(1) w4+1(1) w4+0(1) into xstr in byte mode. - &1 = xstr. - END-OF-DEFINITION. - - CONSTANTS: gen_flags_encrypted(2) TYPE x VALUE '0001', - gen_flags_unicode(2) TYPE x VALUE '0800'. " general purpose flag bit 11 - DATA: gen_flags(2) TYPE x. - -* We convert all names from xstring into string -* see: http://www.pkware.com/documents/casestudies/APPNOTE.TXT, APPENDIX D -* zip normaly used IBM Code Page 437 mapped to SAP Printer EPESCP IBM 437 - DATA: conv TYPE REF TO cl_abap_conv_in_ce, - conv_cp437 TYPE REF TO cl_abap_conv_in_ce, - conv_utf8 TYPE REF TO cl_abap_conv_in_ce, - cp437 TYPE abap_encoding VALUE '1142', " IBM 437 - utf8 TYPE abap_encoding VALUE '4110'. " UTF-8 - - conv_cp437 = cl_abap_conv_in_ce=>create( encoding = cp437 - ignore_cerr = abap_true - replacement = '#' ). - conv_utf8 = cl_abap_conv_in_ce=>create( encoding = utf8 - ignore_cerr = abap_true - replacement = '#' ). - -* The maximum length of the ZIP file for scanning. - DATA: max_length TYPE i. - max_length = XSTRLEN( zip ) - 4. - -* Extract information about all files. - DATA: msdos_date TYPE i, msdos_time TYPE i, file_no TYPE i VALUE 0. - FIELD-SYMBOLS: <file> TYPE t_file, - <ext> TYPE t_ext. -*--------------------------------------------------------------------* -* Insert Begin - Get local file headers by central directory record -* Documentation: http://en.wikipedia.org/wiki/Zip_(file_format) -*--------------------------------------------------------------------* -* ### End of central directory record -* 0 4 End of central directory signature = 0x06054b50 -* 4 2 Number of this disk -* 6 2 Disk where central directory starts -* 8 2 Number of central directory records on this disk -*10 ->2 Total number of central directory records -*12 4 Size of central directory (bytes) -*16 ->4 Offset of start of central directory,relative to start of archive -*20 2 Comment length (n) -*22 n Comment -*--------------------------------------------------------------------* -* ### Central directory file header -* 0 4 Central directory file header signature = 0x02014b50 -* 4 2 Version made by -* 6 2 Version needed to extract (minimum) -* 8 2 General purpose bit flag -*10 2 Compression method -*12 2 File last modification time -*14 2 File last modification date -*16 4 CRC-32 -*20 4 Compressed size -*24 4 Uncompressed size -*28 2 File name length (n) -*30 2 Extra field length (m) -*32 2 File comment length (k) -*34 2 Disk number where file starts -*36 2 Internal file attributes -*38 4 External file attributes -*42 4 Relative offset of local file header. -*46 n File name -*46+n m Extra field -*46+n+m k File comment -*--------------------------------------------------------------------* - CONSTANTS: cv_end_central_directory(4) TYPE x VALUE '504B0506'. - DATA: lt_match_results TYPE match_result_tab, - lv_match_count TYPE i, - ls_match_result LIKE LINE OF lt_match_results, - - lv_entries_in_central_dir TYPE i, - lv_offset_central_dir TYPE i, - lv_offset_local_fileheader TYPE i, - lv_file_name_length TYPE i, - lv_extra_field_length TYPE i, - lv_file_comment_length TYPE i, - - lv_file_length TYPE i. - -* Read "end of central directory record" to find "central directory record" - FIND cv_end_central_directory IN zip IN BYTE MODE - RESULTS lt_match_results MATCH COUNT lv_match_count . - IF lv_match_count IS INITIAL. - RAISE zip_parse_error. "#EC RAISE_OK - ENDIF. - READ TABLE lt_match_results INTO ls_match_result INDEX lv_match_count. - - offset = ls_match_result-offset + 10. - read2 lv_entries_in_central_dir. - - offset = ls_match_result-offset + 16. - read4 lv_offset_central_dir. - - offset = lv_offset_central_dir. - - DO lv_entries_in_central_dir TIMES. - - offset = lv_offset_central_dir + 24. - read4 lv_file_length. " uncompressed size - - IF lv_file_length > 0. " Directoryentries in central file header have no local file header -*--------------------------------------------------------------------* -* Insert End - Get local file headers by central directory record -*--------------------------------------------------------------------* - -* WHILE offset < max_length AND zip+offset(4) = '504B0304'. "-cdr - - - file_no = file_no + 1. - APPEND INITIAL LINE TO files ASSIGNING <file>. - APPEND INITIAL LINE TO exts ASSIGNING <ext>. -*--------------------------------------------------------------------* -* Insert Begin - Get local file headers by central directory record -*--------------------------------------------------------------------* -* Get position of local file header -* CRC32, filesize, compressed size are set in central directory header -* but not necessarily in local file header --> use this here - offset = lv_offset_central_dir + 16. - read4 <ext>-crc32. " crc-32 - read4 <ext>-compsize. " compressed size - read4 <file>-size. " uncompressed size - ENDIF. - -* Get offset of local file header to continue old coding - offset = lv_offset_central_dir + 42. - read4 lv_offset_local_fileheader. - -* and prepare next central directory entry - offset = lv_offset_central_dir + 28. - read2 lv_file_name_length . - read2 lv_extra_field_length . - read2 lv_file_comment_length. - - ADD 46 TO lv_offset_central_dir. - ADD lv_file_name_length TO lv_offset_central_dir. - ADD lv_extra_field_length TO lv_offset_central_dir. - ADD lv_file_comment_length TO lv_offset_central_dir. - CHECK lv_file_length > 0. " Directoryentries in central file header have no local file header - - offset = lv_offset_local_fileheader. -*--------------------------------------------------------------------* -* Insert End - Get local file headers by central directory record -*--------------------------------------------------------------------* - next 4. " local file header signature - read2 <ext>-min_extract_version. " version needed to extract = 2.0 - File is compressed using Deflate - read2 <ext>-gen_flags. " general purpose bit flag - read2 <ext>-compressed. " compression method: deflated - read2 msdos_time. " last mod file time - read2 msdos_date. " last mod file date -* read4 <ext>-crc32. " crc-32 "-cdr -* read4 <ext>-compsize. " compressed size "-cdr -* read4 <file>-size. " uncompressed size "-cdr - next 12. "+cdr - read2 <ext>-filename_len. " file name length - read2 <ext>-extra_len. " extra field length - - gen_flags = <ext>-gen_flags. - gen_flags = gen_flags BIT-AND gen_flags_unicode. " bit 11: Language encoding flag - IF gen_flags <> 0 AND support_unicode_names = abap_true. - conv = conv_utf8. " utf-8 filename extension - ELSE. - conv = conv_cp437. " IBM CP437 - ENDIF. - - <ext>-filename = zip+offset(<ext>-filename_len). - conv->convert( EXPORTING input = <ext>-filename IMPORTING data = <file>-name ). - next <ext>-filename_len. - - <ext>-extra = zip+offset(<ext>-extra_len). - next <ext>-extra_len. - - IF <ext>-gen_flags <> 8. - - <ext>-content = zip+offset(<ext>-compsize). - next <ext>-compsize. - - ELSE. - -* Sometimes sequence in file and directory do not match. -* READ TABLE markers INTO marker WITH KEY no = file_no. -* DATA: cached_offset TYPE i. cached_offset = offset. offset = marker-offset + 16. - DATA result_tab TYPE match_result_tab. - FIELD-SYMBOLS <match> LIKE LINE OF result_tab. - FIND ALL OCCURRENCES OF <ext>-filename IN zip RESULTS result_tab IN BYTE MODE. -* --- start of modification: -* The following modification was necessary to handle zip-archives containing files -* where the name of one file is a sub-string of the name of another file - -* --- deleted code: -* Loop till the end of the result_tab to get the entry from the Central Directory -* LOOP at result_tab ASSIGNING <match>. -* ENDLOOP . -* DATA: cached_offset TYPE i. cached_offset = offset. offset = <match>-offset - 30. - - DATA: cached_offset TYPE i. cached_offset = offset. - DATA: l_filename_length TYPE i. - SORT result_tab BY offset DESCENDING. - LOOP AT result_tab ASSIGNING <match>. - offset = <match>-offset - 18. - read2 l_filename_length. - IF l_filename_length = XSTRLEN( <ext>-filename ). - EXIT. - ENDIF. - ENDLOOP . - - offset = <match>-offset - 30. -* --- end of modification - - read4 <ext>-crc32. - read4 <ext>-compsize. - read4 <file>-size. - next 18. - offset = cached_offset. - <ext>-content = zip+offset(<ext>-compsize). - next <ext>-compsize. - next 16. " I032850 - - ENDIF. - - <file>-time = msdos=>from_time( msdos_time ). - <file>-date = msdos=>from_date( msdos_date ). - - gen_flags = <ext>-gen_flags. - gen_flags = gen_flags BIT-AND gen_flags_encrypted. - - IF NOT ( <ext>-min_extract_version <= 20 ) -* OR NOT ( <ext>-gen_flags = 0 OR <ext>-gen_flags = 2 OR <ext>-gen_flags = 8 ) - OR ( gen_flags = gen_flags_encrypted ) - OR NOT ( <ext>-compressed = 0 OR <ext>-compressed = 8 ). - RAISE zip_parse_error. "#EC RAISE_OK - ENDIF. - -* ENDWHILE. "-cdr - ENDDO. "+cdr - -ENDMETHOD. - - - - METHOD SAVE. - -* Documentation from: http://www.pkware.com/company/standards/appnote/appnote.txt - - DATA: x2(2) TYPE x, x4(4) TYPE x. - - DEFINE writeX4. " write xstring - x4 = &2. - CONCATENATE &1 x4 INTO &1 IN BYTE MODE. - END-OF-DEFINITION. - - DEFINE write2. " write two bytes from integer - x2 = &2. - CONCATENATE &1 x2+1(1) x2+0(1) INTO &1 IN BYTE MODE. - END-OF-DEFINITION. - - DEFINE write4. " write four bytes from integer - x4 = &2. - CONCATENATE &1 x4+3(1) x4+2(1) x4+1(1) x4+0(1) INTO &1 IN BYTE MODE. - END-OF-DEFINITION. - -* Process all files. We write in parallel the zip and the central directory to use later - DATA: msdos_date TYPE i, msdos_time TYPE i. - FIELD-SYMBOLS: <file> TYPE t_file, - <ext> TYPE t_ext. - DATA: dir TYPE xstring, start_offset(4) TYPE x. - - LOOP AT files ASSIGNING <file>. - READ TABLE exts INDEX sy-tabix ASSIGNING <ext>. - start_offset = XSTRLEN( zip ). - - msdos_time = msdos=>to_time( <file>-time ). - msdos_date = msdos=>to_date( <file>-date ). - -* zip data stream - writeX4 zip '504B0304'. " local file header signature - write2 zip <ext>-min_extract_version. " version needed to extract = 2.0 - File is compressed using Deflate - write2 zip <ext>-gen_flags. " general purpose bit flag - write2 zip <ext>-compressed. " compression method: deflated - write2 zip msdos_time. " last mod file time - write2 zip msdos_date. " last mod file date - write4 zip <ext>-crc32. " crc-32 - write4 zip <ext>-compsize. " compressed size - write4 zip <file>-size. " uncompressed size - write2 zip <ext>-filename_len. " file name length - write2 zip <ext>-extra_len. " extra field length - - CONCATENATE zip <ext>-filename <ext>-extra <ext>-content INTO zip IN BYTE MODE. - -* central directory stream (which has a lare duplicate sequence of zip header) - DATA: dup_offset TYPE i. dup_offset = start_offset + 4. - writeX4 dir '504B0102'. " central file header signature - write2 dir 19. " version made by (== pkzip 2.04g) - CONCATENATE dir zip+dup_offset(26) INTO dir IN BYTE MODE. " part which matches exactly zip header - write2 dir 0. " file comment length - write2 dir 0. " disk number start - write2 dir 0. " internal file attributes - write4 dir 0. " external file attributes - write4 dir start_offset. " relative offset of local header - CONCATENATE dir <ext>-filename <ext>-extra INTO dir IN BYTE MODE. " file name + extra info - - ENDLOOP. - -* Write Central Directory - DATA: lines_files TYPE i. lines_files = LINES( files ). - DATA: xstrlen_dir TYPE i. xstrlen_dir = XSTRLEN( dir ). - DATA: offset_dir TYPE i. offset_dir = XSTRLEN( zip ). - - CONCATENATE zip dir INTO zip IN BYTE MODE. - writeX4 zip '504B0506'. " End of central directory - write2 zip 0. " number of this disk - write2 zip 0. " number of the disk with the start of the central directory - write2 zip lines_files. " total number of entries in the central directory on this disk - write2 zip lines_files. " total number of entries in the central directory - write4 zip xstrlen_dir. " size of the central directory - write4 zip offset_dir. " offset of start of central directory - write2 zip 0. " ZIP file comment length - -ENDMETHOD. - - - - - METHOD SPLICE. - -* Documentation from: http://www.pkware.com/company/standards/appnote/appnote.txt - -* Local variables. - FIELD-SYMBOLS: - <entry> LIKE LINE OF entries. - DATA: filename_len TYPE i, - extra_len TYPE i, - filename TYPE xstring. - -* Start to decode new ZIP file - CLEAR: entries. - REFRESH: entries. - -* Global offset for moving through file - DATA: offset TYPE i. - - DATA: w2(2) TYPE x, w4(4) TYPE x, xstr TYPE xstring. - DEFINE read2. "#EC NEEDED read two bytes as integer and move offset - w2 = zip+offset(2). - offset = offset + 2. - CONCATENATE w2+1(1) w2+0(1) INTO xstr IN BYTE MODE. - &1 = xstr. - END-OF-DEFINITION. - - DEFINE read4. "#EC NEEDED read four bytes as integer and move offset - w4 = zip+offset(4). - offset = offset + 4. - CONCATENATE w4+3(1) w4+2(1) w4+1(1) w4+0(1) INTO xstr IN BYTE MODE. - &1 = xstr. - END-OF-DEFINITION. - -* We convert all names from xstring into string - DATA: conv TYPE REF TO cl_abap_conv_in_ce. - conv = cl_abap_conv_in_ce=>create( ). - -* Extract information about all files. - WHILE zip+offset(4) = '504B0304'. " local file header signature - - APPEND INITIAL LINE TO entries ASSIGNING <entry>. - - offset = offset + 8. " next 4=(header). read2 <ext>-min_extract_version. read2 <ext>-gen_flags. - read2 <entry>-compressed. " compression method: deflated - offset = offset + 8. " read2 msdos_time. read2 msdos_date. read4 <ext>-crc32. - read4 <entry>-length. " compressed size - offset = offset + 4. " uncompressed size - read2 filename_len. " file name length - read2 extra_len. " extra field length - - filename = zip+offset(filename_len). - conv->convert( EXPORTING input = filename IMPORTING data = <entry>-name ). - - <entry>-offset = offset + filename_len + extra_len. - offset = <entry>-offset + <entry>-length. - - ENDWHILE. - - DELETE entries WHERE length = 0. - -ENDMETHOD. - - diff --git a/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk b/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk index 2f51664..4e832ab 100644 --- a/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk +++ b/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk @@ -1,13 +1,13 @@ - - - - - - - - - - - - - - - class ZCL_EXCEL_READER_2007 definition @@ -233,7 +233,7 @@ private section. data EXCEL2007 type XSTRING . data ZIP type ref to CL_ABAP_ZIP . - data ALTERNATE_ZIP type ref to ZCL_EXCEL_ABAP_ZIP . + data ALTERNATE_ZIP type ref to OBJECT . data SHARED_STRINGS type STRINGTAB . data STYLES type T_STYLE_REFS . *"* local class implementation for public class @@ -258,13 +258,13 @@ private section. IXML - + - METHOD zif_excel_reader~can_read_file. + method ZIF_EXCEL_READER~CAN_READ_FILE. *--------------------------------------------------------------------* * issue #230 - Pimp my Code * - Stefan Schmöcker, (done) 2012-11-07 @@ -274,10 +274,10 @@ private section. *--------------------------------------------------------------------* * For now always Unknown r_readable = abap_undefined. -ENDMETHOD. +endmethod. - METHOD zif_excel_reader~load. + method ZIF_EXCEL_READER~LOAD. *--------------------------------------------------------------------* * ToDos: * 2do§1 Map Document Properties to ZCL_EXCEL @@ -377,10 +377,10 @@ ENDMETHOD. ENDWHILE. -ENDMETHOD. +endmethod. - METHOD zif_excel_reader~load_file. + method ZIF_EXCEL_READER~LOAD_FILE. *--------------------------------------------------------------------* * ToDos: * 2do§1 decision whether to load from frontend or backend @@ -528,12 +528,12 @@ ENDMETHOD. *--------------------------------------------------------------------* -ENDMETHOD. +endmethod. - METHOD fill_struct_from_attributes. + method FILL_STRUCT_FROM_ATTRIBUTES. *--------------------------------------------------------------------* * issue #230 - Pimp my Code * - Stefan Schmöcker, (done) 2012-11-07 @@ -579,7 +579,7 @@ ENDMETHOD. ENDWHILE. -ENDMETHOD. +endmethod. @@ -607,7 +607,7 @@ ENDMETHOD. * 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 + IF me->zif_excel_reader~gv_use_alternate_zip IS INITIAL. "+#234 *--------------------------------------------------------------------* * Setup ABAP zip-class with binary exceldata if not done already *--------------------------------------------------------------------* @@ -652,12 +652,21 @@ ENDMETHOD. * May become obsolete if SAP fixes standard CL_ABAP_ZIP *--------------------------------------------------------------------* IF me->alternate_zip IS NOT BOUND. - CREATE OBJECT me->alternate_zip. - alternate_zip->load( EXPORTING - zip = me->excel2007 - EXCEPTIONS - zip_parse_error = 1 - OTHERS = 2 ). + 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 @@ -669,14 +678,22 @@ ENDMETHOD. *--------------------------------------------------------------------* * Extract requested filename from archive if possible *--------------------------------------------------------------------* - alternate_zip->get( EXPORTING - name = i_filename - IMPORTING - content = r_content " Contents - EXCEPTIONS - zip_index_error = 1 - zip_decompression_error = 2 - OTHERS = 3 ). + 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 @@ -695,7 +712,7 @@ ENDMETHOD. - METHOD get_ixml_from_zip_archive. + method GET_IXML_FROM_ZIP_ARCHIVE. *--------------------------------------------------------------------* * ToDos: * 2do§1 Add comment what is being achieved here @@ -734,13 +751,13 @@ ENDMETHOD. lo_parser->set_validating( mode = if_ixml_parser=>co_no_validation ). lo_parser->parse( ). -ENDMETHOD. +endmethod. - METHOD load_drawing_anchor. + method LOAD_DRAWING_ANCHOR. TYPES: BEGIN OF t_c_nv_pr, name TYPE string, @@ -881,12 +898,12 @@ ENDMETHOD. ip_width = ls_size-width ip_height = ls_size-height ). -ENDMETHOD. +endmethod. - METHOD load_shared_strings. + method LOAD_SHARED_STRINGS. *--------------------------------------------------------------------* * ToDos: * 2do§1 Support partial formatting of strings in cells @@ -1000,13 +1017,13 @@ ENDMETHOD. lo_node_si ?= lo_node_si->get_next( ). ENDWHILE. -ENDMETHOD. +endmethod. - METHOD load_styles. + method LOAD_STYLES. *--------------------------------------------------------------------* * issue #230 - Pimp my Code @@ -1184,12 +1201,12 @@ ENDMETHOD. ENDWHILE. ENDIF. -ENDMETHOD. +endmethod. - METHOD load_style_borders. + method LOAD_STYLE_BORDERS. *--------------------------------------------------------------------* * issue #230 - Pimp my Code @@ -1275,12 +1292,12 @@ ENDMETHOD. ENDWHILE. -ENDMETHOD. +endmethod. - METHOD load_style_fills. + method LOAD_STYLE_FILLS. *--------------------------------------------------------------------* * ToDos: * 2do§1 Support gradientFill @@ -1360,12 +1377,12 @@ ENDMETHOD. ENDWHILE. -ENDMETHOD. +endmethod. - METHOD load_style_fonts. + method LOAD_STYLE_FONTS. *--------------------------------------------------------------------* * issue #230 - Pimp my Code @@ -1447,12 +1464,12 @@ ENDMETHOD. ENDWHILE. -ENDMETHOD. +endmethod. - METHOD load_style_num_formats. + method LOAD_STYLE_NUM_FORMATS. *--------------------------------------------------------------------* * ToDos: * 2do§1 Explain gaps in predefined formats @@ -1541,13 +1558,13 @@ ENDMETHOD. * 2do§1 Is 49 really the last redefined format? -ENDMETHOD. +endmethod. - METHOD load_workbook. + method LOAD_WORKBOOK. *--------------------------------------------------------------------* * ToDos: * 2do§1 Move macro-reading from zcl_excel_reader_xlsm to this class @@ -1833,13 +1850,13 @@ ENDMETHOD. ENDWHILE. -ENDMETHOD. +endmethod. - METHOD load_worksheet. + method LOAD_WORKSHEET. TYPES: BEGIN OF t_cell, r TYPE string, t TYPE string, @@ -2359,13 +2376,13 @@ ENDMETHOD. ENDIF. " End fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 -ENDMETHOD. +endmethod. - METHOD load_worksheet_drawing. + method LOAD_WORKSHEET_DRAWING. TYPES: BEGIN OF t_c_nv_pr, name TYPE string, @@ -2472,12 +2489,12 @@ ENDMETHOD. ENDDO. -ENDMETHOD. +endmethod. - METHOD resolve_path. + method RESOLVE_PATH. *--------------------------------------------------------------------* * ToDos: * 2do§1 Determine whether the replacement should be done @@ -2515,6 +2532,6 @@ ENDMETHOD. REPLACE REGEX '[^/]*/\.\./' IN rp_result WITH ``. -ENDMETHOD. +endmethod. diff --git a/ZA2X/CLAS/ZCX_EXCEL.slnk b/ZA2X/CLAS/ZCX_EXCEL.slnk index 4bb07f7..4969668 100644 --- a/ZA2X/CLAS/ZCX_EXCEL.slnk +++ b/ZA2X/CLAS/ZCX_EXCEL.slnk @@ -1,5 +1,5 @@ - - + + class ZCX_EXCEL definition public inheriting from CX_STATIC_CHECK @@ -10,14 +10,17 @@ *"* do not include other source files here!!! public section. - constants ZCX_EXCEL type SOTR_CONC value 'DFA64849FDF4F6F1B39A000C29B7D360'. "#EC NOTEXT + constants ZCX_EXCEL type SOTR_CONC value 'E21BC660E7235AF1B7380050568C0F65'. "#EC NOTEXT data ERROR type STRING . methods CONSTRUCTOR importing !TEXTID like TEXTID optional !PREVIOUS like PREVIOUS optional - !ERROR type STRING optional . + !ERROR type STRING optional . + + methods IF_MESSAGE~GET_TEXT + redefinition . *"* protected components of class ZCX_EXCEL *"* do not include other source files here!!! protected section. @@ -32,18 +35,30 @@ private section. *"* implementation or private method's signature *"* use this source file for any macro definitions you need *"* in the implementation part of the class - - - - - + + + + - - - - - + + + + + METHOD if_message~get_text. + IF me->ERROR IS NOT INITIAL. + result = me->ERROR . + ELSE. + CALL METHOD super->if_message~get_text + RECEIVING + result = result. + ENDIF. +ENDMETHOD. + + + + + method CONSTRUCTOR. CALL METHOD SUPER->CONSTRUCTOR EXPORTING diff --git a/ZA2X/INTF/ZIF_EXCEL_READER.slnk b/ZA2X/INTF/ZIF_EXCEL_READER.slnk index 829b0d5..4c72c51 100644 --- a/ZA2X/INTF/ZIF_EXCEL_READER.slnk +++ b/ZA2X/INTF/ZIF_EXCEL_READER.slnk @@ -1,19 +1,19 @@ - + - + - + diff --git a/ZA2X/PROG/ZDEMO_EXCEL37.slnk b/ZA2X/PROG/ZDEMO_EXCEL37.slnk index f30a198..48fcb02 100644 --- a/ZA2X/PROG/ZDEMO_EXCEL37.slnk +++ b/ZA2X/PROG/ZDEMO_EXCEL37.slnk @@ -13,7 +13,9 @@ REPORT zdemo_excel37. DATA: excel TYPE REF TO zcl_excel, - reader TYPE REF TO zif_excel_reader. + reader TYPE REF TO zif_excel_reader, + go_error TYPE REF TO cx_root, + gv_message type string. CONSTANTS: gc_save_file_name TYPE string VALUE '37-passthrough.xlsx'. @@ -33,11 +35,22 @@ START-OF-SELECTION. TRY. CREATE OBJECT reader TYPE zcl_excel_reader_2007. * CREATE OBJECT reader TYPE zcl_excel_reader_xlsm. - excel = reader->load_file( p_upfile ). + excel = reader->load_file( p_upfile ). +*--------------------------------------------------------------------* +* CL_ABAP_ZIP may have problems reading LibreOffice generated files +* You may have to use alternate ZIP-Class - see comments in issue #234 in abap2xlsx at developers network +* excel = reader->load_file( i_filename = p_upfile +* iv_use_alternate_zip = 'ZCL_EXCEL_ABAP_ZIP' ). +*--------------------------------------------------------------------* + *** Create output lcl_output=>output( excel ). - CATCH cx_root. + CATCH cx_root INTO go_error. MESSAGE 'Error reading excelfile' TYPE 'I'. + gv_message = go_error->get_text( ). + IF gv_message IS NOT INITIAL. + MESSAGE gv_message TYPE 'I'. + ENDIF. ENDTRY.