From f24e354f6c8a149b3934024c6aa220fc105121b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20P=C4=99giel?= Date: Fri, 1 Apr 2016 19:37:14 +0200 Subject: [PATCH] New Daily Build with Themes --- build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg | 46132 ++++++++++++++++ build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg.zip | Bin 0 -> 378711 bytes 2 files changed, 46132 insertions(+) create mode 100644 build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg create mode 100644 build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg.zip diff --git a/build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg b/build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg new file mode 100644 index 0000000..88e9dfc --- /dev/null +++ b/build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg @@ -0,0 +1,46132 @@ + + + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + METHOD add. + + DATA: ls_autofilter LIKE LINE OF me->mt_autofilters. + + FIELD-SYMBOLS: <ls_autofilter> LIKE LINE OF me->mt_autofilters. + + READ TABLE me->mt_autofilters ASSIGNING <ls_autofilter> WITH TABLE KEY worksheet = io_sheet. + IF sy-subrc = 0. + RAISE EXCEPTION TYPE zcx_excel. " adding another autofilter to sheet is not allowed + ENDIF. + + CREATE OBJECT ro_autofilter + EXPORTING + io_sheet = io_sheet. + + ls_autofilter-worksheet = io_sheet. + ls_autofilter-autofilter = ro_autofilter. + INSERT ls_autofilter INTO TABLE me->mt_autofilters. + + +ENDMETHOD. + + + METHOD clear. + + CLEAR me->mt_autofilters. + +ENDMETHOD. + + + + + + METHOD get. + + DATA: ls_autofilter LIKE LINE OF me->mt_autofilters. + + FIELD-SYMBOLS: <ls_autofilter> LIKE LINE OF me->mt_autofilters. + + READ TABLE me->mt_autofilters ASSIGNING <ls_autofilter> WITH TABLE KEY worksheet = io_worksheet. + IF sy-subrc = 0. + ro_autofilter = <ls_autofilter>-autofilter. + ELSE. + CLEAR ro_autofilter. + ENDIF. + +ENDMETHOD. + + + + METHOD is_empty. + IF me->mt_autofilters IS INITIAL. + r_empty = abap_true. + ENDIF. +ENDMETHOD. + + + + METHOD remove. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet. + + FIELD-SYMBOLS: <ls_autofilter> LIKE LINE OF me->mt_autofilters. + + DELETE TABLE me->mt_autofilters WITH TABLE KEY worksheet = lo_worksheet. + +ENDMETHOD. + + + + METHOD size. + DESCRIBE TABLE me->mt_autofilters LINES r_size. +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + CLASS lcl_excel_common_test DEFINITION DEFERRED. +CLASS zcl_excel_common DEFINITION LOCAL FRIENDS lcl_excel_common_test. + +*----------------------------------------------------------------------* +* CLASS lcl_Excel_Common_Test DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_excel_common_test DEFINITION FOR TESTING "#AU Risk_Level Harmless + . "#AU Duration Short +*?<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> +*?<asx:values> +*?<TESTCLASS_OPTIONS> +*?<TEST_CLASS>lcl_Excel_Common_Test +*?</TEST_CLASS> +*?<TEST_MEMBER>f_Cut +*?</TEST_MEMBER> +*?<OBJECT_UNDER_TEST>ZCL_EXCEL_COMMON +*?</OBJECT_UNDER_TEST> +*?<OBJECT_IS_LOCAL/> +*?<GENERATE_FIXTURE>X +*?</GENERATE_FIXTURE> +*?<GENERATE_CLASS_FIXTURE>X +*?</GENERATE_CLASS_FIXTURE> +*?<GENERATE_INVOCATION>X +*?</GENERATE_INVOCATION> +*?<GENERATE_ASSERT_EQUAL>X +*?</GENERATE_ASSERT_EQUAL> +*?</TESTCLASS_OPTIONS> +*?</asx:values> +*?</asx:abap> + PRIVATE SECTION. +* ================ + DATA: + lx_excel TYPE REF TO zcx_excel, + ls_symsg_act TYPE symsg, " actual messageinformation of exception + ls_symsg_exp TYPE symsg, " expected messageinformation of exception + f_cut TYPE REF TO zcl_excel_common. "class under test + + CLASS-METHODS: class_setup. + CLASS-METHODS: class_teardown. + METHODS: setup. + METHODS: teardown. +* METHODS: char2hex FOR TESTING. + METHODS: convert_column2alpha FOR TESTING. + METHODS: convert_column2int FOR TESTING. + METHODS: date_to_excel_string FOR TESTING. + METHODS: encrypt_password FOR TESTING. + METHODS: excel_string_to_date FOR TESTING. + METHODS: excel_string_to_time FOR TESTING. +* METHODS: number_to_excel_string FOR TESTING. + METHODS: time_to_excel_string FOR TESTING. + METHODS: split_file FOR TESTING. + METHODS: convert_range2column_a_row FOR TESTING. + METHODS: describe_structure FOR TESTING. + METHODS: calculate_cell_distance FOR TESTING. + METHODS: shift_formula FOR TESTING. + METHODS: is_cell_in_range FOR TESTING. +ENDCLASS. "lcl_Excel_Common_Test + + +*----------------------------------------------------------------------* +* CLASS lcl_Excel_Common_Test IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_excel_common_test IMPLEMENTATION. +* =========================================== + + METHOD class_setup. +* =================== + + + ENDMETHOD. "class_Setup + + + METHOD class_teardown. +* ====================== + + + ENDMETHOD. "class_Teardown + + + METHOD setup. +* ============= + + CREATE OBJECT f_cut. + ENDMETHOD. "setup + + + METHOD teardown. +* ================ + + + ENDMETHOD. "teardown + + + METHOD convert_column2alpha. +* ============================ + DATA ep_column TYPE zexcel_cell_column_alpha. + +* Test 1. Simple test + TRY. + ep_column = zcl_excel_common=>convert_column2alpha( 1 ). + + zcl_excel_common=>assert_equals( + act = ep_column + exp = 'A' + msg = 'Wrong column conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Max column for OXML #16,384 = XFD + TRY. + ep_column = zcl_excel_common=>convert_column2alpha( 16384 ). + + zcl_excel_common=>assert_equals( + act = ep_column + exp = 'XFD' + msg = 'Wrong column conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 3. Index 0 is out of bounds + TRY. + ep_column = zcl_excel_common=>convert_column2alpha( 0 ). + + zcl_excel_common=>assert_equals( + act = ep_column + exp = 'A' + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>assert_equals( + act = lx_excel->error + exp = 'Index out of bounds' + msg = 'Colum index 0 is out of bounds, min column index is 1' + level = if_aunit_constants=>fatal + ). + ENDTRY. + +* Test 4. Exception should be thrown index out of bounds + TRY. + ep_column = zcl_excel_common=>convert_column2alpha( 16385 ). + + zcl_excel_common=>assert_differs( + act = ep_column + exp = 'XFE' + msg = 'Colum index 16385 is out of bounds, max column index is 16384' + level = if_aunit_constants=>fatal + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>assert_equals( + act = lx_excel->error + exp = 'Index out of bounds' + msg = 'Wrong exception is thrown' + level = if_aunit_constants=>tolerable + ). + ENDTRY. + ENDMETHOD. "convert_Column2alpha + + + METHOD convert_column2int. +* ========================== + DATA ep_column TYPE zexcel_cell_column. + +* Test 1. Basic test + TRY. + ep_column = zcl_excel_common=>convert_column2int( 'A' ). + + zcl_excel_common=>assert_equals( + act = ep_column + exp = 1 + msg = 'Wrong column conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Max column + TRY. + ep_column = zcl_excel_common=>convert_column2int( 'XFD' ). + + zcl_excel_common=>assert_equals( + act = ep_column + exp = 16384 + msg = 'Wrong column conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 3. Out of bounds + TRY. + ep_column = zcl_excel_common=>convert_column2int( '' ). + + zcl_excel_common=>assert_differs( act = ep_column + exp = '0' + msg = 'Wrong column conversion' + level = if_aunit_constants=>critical ). + CATCH zcx_excel INTO lx_excel. + CLEAR: ls_symsg_act, + ls_symsg_exp. + ls_symsg_exp-msgid = 'ZABAP2XLSX'. + ls_symsg_exp-msgno = '800'. + ls_symsg_act-msgid = lx_excel->syst_at_raise-msgid. + ls_symsg_act-msgno = lx_excel->syst_at_raise-msgno. + zcl_excel_common=>assert_equals( act = ls_symsg_act + exp = ls_symsg_exp + msg = 'Colum name should be a valid string' + level = if_aunit_constants=>fatal ). + ENDTRY. + +* Test 4. Out of bounds + TRY. + ep_column = zcl_excel_common=>convert_column2int( 'XFE' ). + + zcl_excel_common=>assert_differs( act = ep_column + exp = 16385 + msg = 'Wrong column conversion' + level = if_aunit_constants=>critical ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>assert_equals( act = lx_excel->error + exp = 'Index out of bounds' + msg = 'Colum XFE is out of range' + level = if_aunit_constants=>fatal ). + ENDTRY. + ENDMETHOD. "convert_Column2int + + + METHOD date_to_excel_string. +* ============================ + DATA ep_value TYPE zexcel_cell_value. + +* Test 1. Basic conversion + TRY. + ep_value = zcl_excel_common=>date_to_excel_string( '19000101' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = 1 + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. +* Check around the "Excel Leap Year" 1900 + TRY. + ep_value = zcl_excel_common=>date_to_excel_string( '19000228' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = 59 + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + TRY. + ep_value = zcl_excel_common=>date_to_excel_string( '19000301' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = 61 + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + + +* Test 2. Basic conversion + TRY. + ep_value = zcl_excel_common=>date_to_excel_string( '99991212' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = 2958446 + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 3. Initial date + TRY. + DATA: lv_date TYPE d. + ep_value = zcl_excel_common=>date_to_excel_string( lv_date ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Basic conversion + TRY. + DATA exp_value TYPE zexcel_cell_value VALUE 0. + ep_value = zcl_excel_common=>date_to_excel_string( '18991231' ). + + zcl_excel_common=>assert_differs( + act = ep_value + exp = exp_value + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>assert_equals( + act = lx_excel->error + exp = 'Index out of bounds' + msg = 'Dates prior of 1900 are not available in excel' + level = if_aunit_constants=>critical + ). + ENDTRY. + + ENDMETHOD. "date_To_Excel_String + + + METHOD encrypt_password. +* ======================== + DATA lv_encrypted_pwd TYPE zexcel_aes_password. + + TRY. + lv_encrypted_pwd = zcl_excel_common=>encrypt_password( 'test' ). + + zcl_excel_common=>assert_equals( + act = lv_encrypted_pwd + exp = 'CBEB' + msg = 'Wrong password encryption' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + ENDMETHOD. "encrypt_Password + + + METHOD excel_string_to_date. +* ============================ + DATA ep_value TYPE d. + + +* Test 1. Simple test -> ABAP Manage also date prior of 1900 + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( '0' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '18991231' + msg = 'Wrong date conversion' + level = if_aunit_constants=>tolerable + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. +* Check around the "Excel Leap Year" 1900 + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( '59' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '19000228' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( '61' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '19000301' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Simple test + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( '1' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '19000101' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 3. Index 0 is out of bounds + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( '2958446' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '99991212' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 4. Exception should be thrown index out of bounds + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( '2958447' ). + + zcl_excel_common=>assert_differs( + act = ep_value + exp = '99991212' + msg = 'Wrong date conversion' + level = if_aunit_constants=>fatal + ). + + zcl_excel_common=>assert_differs( + act = ep_value + exp = '00000000' + msg = 'Wrong date conversion' + level = if_aunit_constants=>fatal + ). + + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>assert_equals( + act = lx_excel->error + exp = 'Index out of bounds' + msg = 'Wrong exception is thrown' + level = if_aunit_constants=>tolerable + ). + ENDTRY. + ENDMETHOD. "excel_String_To_Date + + + METHOD excel_string_to_time. +* ============================ + DATA ep_value TYPE t. + +* Test 1. Simple test + TRY. + ep_value = zcl_excel_common=>excel_string_to_time( '0' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '000000' + msg = 'Wrong date conversion' + level = if_aunit_constants=>tolerable + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Simple test + TRY. + ep_value = zcl_excel_common=>excel_string_to_time( '1' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '000000' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 3. Simple test + TRY. + ep_value = zcl_excel_common=>excel_string_to_time( '0.99999' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '235959' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 4. Also string greater than 1 should be managed + TRY. + ep_value = zcl_excel_common=>excel_string_to_time( '4.1' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '022400' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 4. string is not a number + TRY. + ep_value = zcl_excel_common=>excel_string_to_time( 'NaN' ). + + zcl_excel_common=>assert_differs( + act = ep_value + exp = '000000' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>assert_equals( + act = lx_excel->error + exp = 'Unable to interpret time' + msg = 'Time should be a valid string' + level = if_aunit_constants=>fatal + ). + ENDTRY. + ENDMETHOD. "excel_String_To_Time + + + METHOD time_to_excel_string. +* ============================ + DATA ep_value TYPE zexcel_cell_value. + +* Test 1. Basic conversion + TRY. + ep_value = zcl_excel_common=>time_to_excel_string( '000001' ). + " A test directly in Excel returns the value 0.0000115740740740741000 + zcl_excel_common=>assert_equals( + act = ep_value + exp = '0.0000115740740741' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Basic conversion + TRY. + ep_value = zcl_excel_common=>time_to_excel_string( '235959' ). + " A test directly in Excel returns the value 0.9999884259259260000000 + zcl_excel_common=>assert_equals( + act = ep_value + exp = '0.9999884259259260' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 3. Initial date + TRY. + ep_value = zcl_excel_common=>time_to_excel_string( '000000' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '0' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + +* Test 2. Basic conversion + TRY. + ep_value = zcl_excel_common=>time_to_excel_string( '022400' ). + + zcl_excel_common=>assert_equals( + act = ep_value + exp = '0.1000000000000000' + msg = 'Wrong date conversion' + level = if_aunit_constants=>critical + ). + CATCH zcx_excel INTO lx_excel. + zcl_excel_common=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical " Error Severity + ). + ENDTRY. + + ENDMETHOD. "time_To_Excel_String + + METHOD split_file. +* ============================ + + DATA: ep_file TYPE text255, + ep_extension TYPE char10, + ep_dotextension TYPE char10. + + +* Test 1. Basic conversion + zcl_excel_common=>split_file( EXPORTING ip_file = 'filename.xml' + IMPORTING ep_file = ep_file + ep_extension = ep_extension + ep_dotextension = ep_dotextension ). + + zcl_excel_common=>assert_equals( + act = ep_file + exp = 'filename' + msg = 'Split filename failed' + level = if_aunit_constants=>critical ). + + zcl_excel_common=>assert_equals( + act = ep_extension + exp = 'xml' + msg = 'Split extension failed' + level = if_aunit_constants=>critical ). + + zcl_excel_common=>assert_equals( + act = ep_dotextension + exp = '.xml' + msg = 'Split extension failed' + level = if_aunit_constants=>critical ). + +* Test 2. no extension + zcl_excel_common=>split_file( EXPORTING ip_file = 'filename' + IMPORTING ep_file = ep_file + ep_extension = ep_extension + ep_dotextension = ep_dotextension ). + + zcl_excel_common=>assert_equals( + act = ep_file + exp = 'filename' + msg = 'Split filename failed' + level = if_aunit_constants=>critical ). + + zcl_excel_common=>assert_equals( + act = ep_extension + exp = '' + msg = 'Split extension failed' + level = if_aunit_constants=>critical ). + + zcl_excel_common=>assert_equals( + act = ep_dotextension + exp = '' + msg = 'Split extension failed' + level = if_aunit_constants=>critical ). + + ENDMETHOD. "split_file + + METHOD convert_range2column_a_row. + DATA: lv_range TYPE string. + DATA: lv_column_start TYPE zexcel_cell_column_alpha, + lv_column_end TYPE zexcel_cell_column_alpha, + lv_row_start TYPE zexcel_cell_row, + lv_row_end TYPE zexcel_cell_row, + lv_sheet TYPE string. + +* a) input empty --> nothing to do + zcl_excel_common=>convert_range2column_a_row( + EXPORTING + i_range = lv_range + IMPORTING + e_column_start = lv_column_start " Cell Column Start + e_column_end = lv_column_end " Cell Column End + e_row_start = lv_row_start " Cell Row + e_row_end = lv_row_end " Cell Row + e_sheet = lv_sheet " Title + ). + + zcl_excel_common=>assert_equals( + act = lv_column_start + exp = '' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_column_end + exp = '' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_start + exp = '' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_end + exp = '' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_sheet + exp = '' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). +* b) sheetname existing - starts with ' example 'Sheet 1'!$B$6:$D$13 + lv_range = `'Sheet 1'!$B$6:$D$13`. + zcl_excel_common=>convert_range2column_a_row( + EXPORTING + i_range = lv_range + IMPORTING + e_column_start = lv_column_start " Cell Column Start + e_column_end = lv_column_end " Cell Column End + e_row_start = lv_row_start " Cell Row + e_row_end = lv_row_end " Cell Row + e_sheet = lv_sheet " Title + ). + + zcl_excel_common=>assert_equals( + act = lv_column_start + exp = 'B' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_column_end + exp = 'D' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_start + exp = '6' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_end + exp = '13' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_sheet + exp = 'Sheet 1' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). +* c) sheetname existing - does not start with ' example Sheet1!$B$6:$D$13 + lv_range = `Sheet1!B6:$D$13`. + zcl_excel_common=>convert_range2column_a_row( + EXPORTING + i_range = lv_range + IMPORTING + e_column_start = lv_column_start " Cell Column Start + e_column_end = lv_column_end " Cell Column End + e_row_start = lv_row_start " Cell Row + e_row_end = lv_row_end " Cell Row + e_sheet = lv_sheet " Title + ). + + zcl_excel_common=>assert_equals( + act = lv_column_start + exp = 'B' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_column_end + exp = 'D' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_start + exp = '6' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_end + exp = '13' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_sheet + exp = 'Sheet1' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). +* d) no sheetname - just area example $B$6:$D$13 + lv_range = `$B$6:D13`. + zcl_excel_common=>convert_range2column_a_row( + EXPORTING + i_range = lv_range + IMPORTING + e_column_start = lv_column_start " Cell Column Start + e_column_end = lv_column_end " Cell Column End + e_row_start = lv_row_start " Cell Row + e_row_end = lv_row_end " Cell Row + e_sheet = lv_sheet " Title + ). + + zcl_excel_common=>assert_equals( + act = lv_column_start + exp = 'B' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_column_end + exp = 'D' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_start + exp = '6' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_row_end + exp = '13' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + zcl_excel_common=>assert_equals( + act = lv_sheet + exp = '' + msg = 'Conversion of range failed' + level = if_aunit_constants=>critical ). + ENDMETHOD. "convert_range2column_a_row + + + METHOD describe_structure. + DATA: ls_test TYPE scarr. + DATA: lo_structdescr TYPE REF TO cl_abap_structdescr. + DATA: lt_structure TYPE ddfields. + FIELD-SYMBOLS: <line> LIKE LINE OF lt_structure. + + " Test with DDIC Type + lo_structdescr ?= cl_abap_structdescr=>describe_by_data( p_data = ls_test ). + lt_structure = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + READ TABLE lt_structure ASSIGNING <line> INDEX 1. + zcl_excel_common=>assert_equals( + act = <line>-fieldname + exp = 'MANDT' + msg = 'Describe structure failed' + level = if_aunit_constants=>critical ). + + " Test with local defined structure having DDIC and non DDIC elements + TYPES: + BEGIN OF t_test, + carrid TYPE s_carr_id, + carrname TYPE s_carrname, + carrdesc TYPE string, + END OF t_test. + DATA: ls_ttest TYPE t_test. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data( p_data = ls_ttest ). + lt_structure = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + READ TABLE lt_structure ASSIGNING <line> INDEX 1. + zcl_excel_common=>assert_equals( + act = <line>-fieldname + exp = 'CARRID' + msg = 'Describe structure failed' + level = if_aunit_constants=>critical ). + + ENDMETHOD. "describe_structure + + + METHOD calculate_cell_distance. + DATA: lv_offset_rows TYPE i, + lv_offset_cols TYPE i, + lv_message TYPE string. + + DEFINE macro_calculate_cell_distance. + zcl_excel_common=>calculate_cell_distance( exporting iv_reference_cell = &1 + iv_current_cell = &2 + importing ev_row_difference = lv_offset_rows + ev_col_difference = lv_offset_cols ). +* Check delta columns + concatenate 'Error calculating column difference in test:' + &1 + '->' + &2 + into lv_message separated by space. + zcl_excel_common=>assert_equals( act = lv_offset_cols + exp = &3 + msg = lv_message + quit = 0 " continue tests + level = if_aunit_constants=>critical ). +* Check delta rows + concatenate 'Error calculating row difference in test:' + &1 + '->' + &2 + into lv_message separated by space. + zcl_excel_common=>assert_equals( act = lv_offset_rows + exp = &4 + msg = lv_message + quit = 0 " continue tests + level = if_aunit_constants=>critical ). + END-OF-DEFINITION. + + + macro_calculate_cell_distance: + 'C12' 'C12' 0 0 , " Same cell + 'C12' 'C13' 0 1 , " Shift down 1 place + 'C12' 'C25' 0 13 , " Shift down some places + 'C12' 'C11' 0 -1 , " Shift up 1 place + 'C12' 'C1' 0 -11 , " Shift up some place + 'C12' 'D12' 1 0 , " Shift right 1 place + 'C12' 'AA12' 24 0 , " Shift right some places + 'C12' 'B12' -1 0 , " Shift left 1 place + 'AA12' 'C12' -24 0 , " Shift left some place + 'AA121' 'C12' -24 -109 . " The full package. + + ENDMETHOD. "CALCULATE_CELL_DISTANCE + + METHOD shift_formula. + DATA: lv_resulting_formula TYPE string, + lv_message TYPE string, + lv_counter TYPE num8. + + DEFINE macro_shift_formula. + add 1 to lv_counter. + clear lv_resulting_formula. + try. + lv_resulting_formula = zcl_excel_common=>shift_formula( iv_reference_formula = &1 + iv_shift_cols = &2 + iv_shift_rows = &3 ). + concatenate 'Wrong result in test' + lv_counter + 'shifting formula ' + &1 + into lv_message separated by space. + zcl_excel_common=>assert_equals( act = lv_resulting_formula + exp = &4 + msg = lv_message + quit = 0 " continue tests + level = if_aunit_constants=>critical ). + catch zcx_excel. + concatenate 'Unexpected exception occurred in test' + lv_counter + 'shifting formula ' + &1 + into lv_message separated by space. + zcl_excel_common=>assert_equals( act = lv_resulting_formula + exp = &4 + msg = lv_message + quit = 0 " continue tests + level = if_aunit_constants=>critical ). + endtry. + END-OF-DEFINITION. + +* Test shifts that should result in a valid output + macro_shift_formula: + 'C17' 0 0 'C17', " Very basic check + 'C17' 2 3 'E20', " Check shift right and down + 'C17' -2 -3 'A14', " Check shift left and up + '$C$17' 1 1 '$C$17', " Fixed columns/rows + 'SUM($C17:C$23)+C30' 1 11 'SUM($C28:D$23)+D41', " Operators and Ranges, mixed fixed rows or columns + 'RNGNAME1+C7' -1 -4 'RNGNAME1+B3', " Operators and Rangename + '"Date:"&TEXT(B2)' 1 1 '"Date:"&TEXT(C3)', " String literals and string concatenation + '[TEST6.XLSX]SHEET1!A1' 1 11 '[TEST6.XLSX]SHEET1!B12', " External sheet reference + `X(B13, "KK" ) ` 1 1 `X(C14,"KK")`, " superflous blanks, multi-argument functions, literals in function, unknown functions +* 'SIN((((((B2))))))' 1 1 'SIN((((((C3))))))', " Deep nesting +* 'SIN(SIN(SIN(SIN(E22))))' 0 1 'SIN(SIN(SIN(SIN(E23))))', " Different type of deep nesting + `SIN(SIN(SIN(SIN(E22))))` 0 1 'SIN(SIN(SIN(SIN(E23))))', " same as above - but with string input instead of Char-input + 'HEUTE()' 2 5 'HEUTE()', " Functions w/o arguments, No cellreferences + '"B2"' 2 5 '"B2"', " No cellreferences + '' 2 5 '', " Empty + 'A1+$A1+A$1+$A$1+B2' -1 0 '#REF!+$A1+#REF!+$A$1+A2', " Referencing error , column only , underflow + 'A1+$A1+A$1+$A$1+B2' 0 -1 '#REF!+#REF!+A$1+$A$1+B1', " Referencing error , row only , underflow + 'A1+$A1+A$1+$A$1+B2' -1 -1 '#REF!+#REF!+#REF!+$A$1+A1'. " Referencing error , row and column , underflow + ENDMETHOD. "SHIFT_FORMULA + + METHOD is_cell_in_range. + DATA ep_cell_in_range TYPE abap_bool. + +* Test 1: upper left corner (in range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'B' + ip_row = 2 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_true + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 2: lower right corner (in range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'D' + ip_row = 4 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_true + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 3: left side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'A' + ip_row = 3 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 4: upper side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'C' + ip_row = 1 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 5: right side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'E' + ip_row = 3 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* Test 6: lower side (out of range) + TRY. + ep_cell_in_range = zcl_excel_common=>is_cell_in_range( + ip_column = 'C' + ip_row = 5 + ip_range = 'B2:D4' ). + + zcl_excel_common=>assert_equals( + act = ep_cell_in_range + exp = abap_false + msg = 'Check cell in range failed' + level = if_aunit_constants=>critical ). + CATCH zcx_excel. + zcl_excel_common=>fail( + msg = 'Unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + ENDMETHOD. + +ENDCLASS. "lcl_Excel_Common_Test + + + + + + + + + + + + + + + + + + ABAP + + + + + + + + + + + + + + + + + + + + method ASSERT_DIFFERS. + DATA: ls_seoclass TYPE seoclass. + +" Let see >=7.02 + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_differs + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + RECEIVING + assertion_failed = assertion_failed. + ELSE. +" Let see >=7.00 or even lower + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_AUNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_differs + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + RECEIVING + assertion_failed = assertion_failed. + ELSE. +* We do nothing for now not supported + ENDIF. + ENDIF. +endmethod. + + + + + + + + + + + METHOD assert_equals. + DATA: ls_seoclass TYPE seoclass. + + " Let see >=7.02 + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_equals + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + ignore_hash_sequence = ignore_hash_sequence + RECEIVING + assertion_failed = assertion_failed. + ELSE. + " Let see >=7.00 or even lower + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_AUNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>assert_equals + EXPORTING + exp = exp + act = act + msg = msg + level = level + tol = tol + quit = quit + ignore_hash_sequence = ignore_hash_sequence + RECEIVING + assertion_failed = assertion_failed. + ELSE. +* We do nothing for now not supported + ENDIF. + ENDIF. +ENDMETHOD. + + + + + + + + METHOD calculate_cell_distance. + + DATA: lv_reference_row TYPE i, + lv_reference_col_alpha TYPE zexcel_cell_column_alpha, + lv_reference_col TYPE i, + lv_current_row TYPE i, + lv_current_col_alpha TYPE zexcel_cell_column_alpha, + lv_current_col TYPE i. + +*--------------------------------------------------------------------* +* Split reference cell into numerical row/column representation +*--------------------------------------------------------------------* + convert_columnrow2column_a_row( EXPORTING + i_columnrow = iv_reference_cell + IMPORTING + e_column = lv_reference_col_alpha + e_row = lv_reference_row ). + lv_reference_col = convert_column2int( lv_reference_col_alpha ). + +*--------------------------------------------------------------------* +* Split current cell into numerical row/column representation +*--------------------------------------------------------------------* + convert_columnrow2column_a_row( EXPORTING + i_columnrow = iv_current_cell + IMPORTING + e_column = lv_current_col_alpha + e_row = lv_current_row ). + lv_current_col = convert_column2int( lv_current_col_alpha ). + +*--------------------------------------------------------------------* +* Calculate row and column difference +* Positive: Current cell below reference cell +* or Current cell right of reference cell +* Negative: Current cell above reference cell +* or Current cell left of reference cell +*--------------------------------------------------------------------* + ev_row_difference = lv_current_row - lv_reference_row. + ev_col_difference = lv_current_col - lv_reference_col. + +ENDMETHOD. + + + + + method CHAR2HEX. + + IF o_conv IS NOT BOUND. + o_conv = cl_abap_conv_out_ce=>create( endian = 'L' + ignore_cerr = abap_true + replacement = '#' ). + ENDIF. + + CALL METHOD o_conv->reset( ). + CALL METHOD o_conv->write( data = i_char ). + r_hex+1 = o_conv->get_buffer( ). " x'65' must be x'0065' + +endmethod. + + + METHOD class_constructor. + c_xlsx_file_filter = 'Excel Workbook (*.xlsx)|*.xlsx|'(005). +ENDMETHOD. + + + + + + METHOD convert_column2alpha. + + DATA: lv_uccpi TYPE i, + lv_text TYPE sychar02, + lv_module TYPE int4, + lv_column TYPE zexcel_cell_column. + +* Propagate zcx_excel if error occurs " issue #155 - less restrictive typing for ip_column + lv_column = convert_column2int( ip_column ). " issue #155 - less restrictive typing for ip_column + +*--------------------------------------------------------------------* +* Check whether column is in allowed range for EXCEL to handle ( 1-16384 ) +*--------------------------------------------------------------------* + IF lv_column > 16384 + OR lv_column < 1. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Index out of bounds'. + ENDIF. + +*--------------------------------------------------------------------* +* Build alpha representation of column +*--------------------------------------------------------------------* + WHILE lv_column GT 0. + + lv_module = ( lv_column - 1 ) MOD 26. + lv_uccpi = 65 + lv_module. + + lv_column = ( lv_column - lv_module ) / 26. + + lv_text = cl_abap_conv_in_ce=>uccpi( lv_uccpi ). + CONCATENATE lv_text ep_column INTO ep_column. + + ENDWHILE. + +ENDMETHOD. + + + + + + METHOD convert_column2int. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-12-29 +* - ... +* changes: renaming variables to naming conventions +* removing unused variables +* removing commented out code that is inactive for more then half a year +* message made to support multilinguality +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* +* issue#246 - error converting lower case column names +* - Stefan Schmoecker, 2012-12-29 +* changes: translating the correct variable to upper dase +* adding missing exception if input is a number +* that is out of bounds +* adding missing exception if input contains +* illegal characters like german umlauts +*--------------------------------------------------------------------* + + DATA: lv_column TYPE zexcel_cell_column_alpha, + lv_column_c TYPE char10, + lv_column_s TYPE string, + lv_errormessage TYPE string, " Can't pass '...'(abc) to exception-class + lv_modulo TYPE i. + +*--------------------------------------------------------------------* +* This module tries to identify which column a user wants to access +* Numbers as input are just passed back, anything else will be converted +* using EXCEL nomenclatura A = 1, AA = 27, ..., XFD = 16384 +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* Normalize input ( upper case , no gaps ) +*--------------------------------------------------------------------* + lv_column_c = ip_column. +* TRANSLATE lv_column TO UPPER CASE. " Fix #246 + TRANSLATE lv_column_c TO UPPER CASE. " Fix #246 + CONDENSE lv_column_c NO-GAPS. + IF lv_column_c EQ ''. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + +*--------------------------------------------------------------------* +* If a number gets passed, just convert it to an integer and return +* the converted value +*--------------------------------------------------------------------* + TRY. + IF lv_column_c CO '1234567890 '. " Fix #164 + ep_column = lv_column_c. " Fix #164 +*--------------------------------------------------------------------* +* Maximum column for EXCEL: XFD = 16384 " if anyone has a reference for this information - please add here instead of this comment +*--------------------------------------------------------------------* + IF ep_column > 16384 OR ep_column < 1. + lv_errormessage = 'Index out of bounds'(004). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + EXIT. + ENDIF. + CATCH cx_sy_conversion_no_number. "#EC NO_HANDLER + " Try the character-approach if approach via number has failed + ENDTRY. + +*--------------------------------------------------------------------* +* Raise error if unexpected characters turns up +*--------------------------------------------------------------------* + lv_column_s = lv_column_c. + IF lv_column_s CN sy-abcde. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + +*--------------------------------------------------------------------* +* Interpret input as number to base 26 with A=1, ... Z=26 +* Raise error if unexpected character turns up +*--------------------------------------------------------------------* +* 1st character +*--------------------------------------------------------------------* + lv_column = lv_column_c. + lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+0(1) ) MOD zcl_excel_common=>c_excel_col_module. + IF lv_modulo < 1 OR lv_modulo > 26. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + ep_column = lv_modulo. " Leftmost digit + +*--------------------------------------------------------------------* +* 2nd character if present +*--------------------------------------------------------------------* + CHECK lv_column+1(1) IS NOT INITIAL. " No need to continue if string ended + lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+1(1) ) MOD zcl_excel_common=>c_excel_col_module. + IF lv_modulo < 1 OR lv_modulo > 26. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + ep_column = 26 * ep_column + lv_modulo. " if second digit is present first digit is for 26^1 + +*--------------------------------------------------------------------* +* 3rd character if present +*--------------------------------------------------------------------* + CHECK lv_column+2(1) IS NOT INITIAL. " No need to continue if string ended + lv_modulo = cl_abap_conv_out_ce=>uccpi( lv_column+2(1) ) MOD zcl_excel_common=>c_excel_col_module. + IF lv_modulo < 1 OR lv_modulo > 26. +* lv_errormessage = 'Unable to interpret input as column'(003). +* RAISE EXCEPTION TYPE zcx_excel +* EXPORTING +* error = lv_errormessage. + MESSAGE e800(zabap2xlsx) INTO lv_errormessage. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + syst_at_raise = syst. + ENDIF. + ep_column = 26 * ep_column + lv_modulo. " if third digit is present first digit is for 26^2 and second digit for 26^1 + +*--------------------------------------------------------------------* +* Maximum column for EXCEL: XFD = 16384 " if anyone has a reference for this information - please add here instead of this comment +*--------------------------------------------------------------------* + IF ep_column > 16384 OR ep_column < 1. + lv_errormessage = 'Index out of bounds'(004). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + +ENDMETHOD. + + + + + + method CONVERT_COLUMNROW2COLUMN_A_ROW. +*--------------------------------------------------------------------* + "issue #256 - replacing char processing with regex +*--------------------------------------------------------------------* +* Stefan Schmoecker, 2013-08-11 +* Allow input to be CLIKE instead of STRING +*--------------------------------------------------------------------* + + DATA: pane_cell_row_a TYPE string, + lv_columnrow type string. + + lv_columnrow = i_columnrow. " Get rid of trailing blanks + + FIND REGEX '^(\D+)(\d+)$' IN lv_columnrow SUBMATCHES e_column + pane_cell_row_a. + e_row = pane_cell_row_a. + +endmethod. + + + + + + + + + + method CONVERT_RANGE2COLUMN_A_ROW. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-12-07 +* - ... +* changes: renaming variables to naming conventions +* aligning code +* added exceptionclass +* added errorhandling for invalid range +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* +* issue#241 - error when sheetname contains "!" +* - sheetname should be returned unescaped +* - Stefan Schmoecker, 2012-12-07 +* changes: changed coding to support sheetnames with "!" +* unescaping sheetname +*--------------------------------------------------------------------* +* issue#155 - lessening restrictions of input parameters +* - Stefan Schmoecker, 2012-12-07 +* changes: i_range changed to clike +* e_sheet changed to clike +*--------------------------------------------------------------------* + + DATA: lv_sheet TYPE string, + lv_range TYPE string, + lv_columnrow_start TYPE string, + lv_columnrow_end TYPE string, + lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + + +*--------------------------------------------------------------------* +* Split input range into sheetname and Area +* 4 cases - a) input empty --> nothing to do +* - b) sheetname existing - starts with ' example 'Sheet 1'!$B$6:$D$13 +* - c) sheetname existing - does not start with ' example Sheet1!$B$6:$D$13 +* - d) no sheetname - just area example $B$6:$D$13 +*--------------------------------------------------------------------* +* Initialize output parameters + CLEAR: e_column_start, + e_column_end, + e_row_start, + e_row_end, + e_sheet. + + IF i_range IS INITIAL. " a) input empty --> nothing to do + EXIT. + + ELSEIF i_range(1) = `'`. " b) sheetname existing - starts with ' + FIND REGEX '\![^\!]*$' IN i_range MATCH OFFSET sy-fdpos. " Find last ! + IF sy-subrc = 0. + lv_sheet = i_range(sy-fdpos). + ADD 1 TO sy-fdpos. + lv_range = i_range. + SHIFT lv_range LEFT BY sy-fdpos PLACES. + ELSE. + lv_errormessage = 'Invalid range'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ELSEIF i_range CS '!'. " c) sheetname existing - does not start with ' + SPLIT i_range AT '!' INTO lv_sheet lv_range. + + ELSE. " d) no sheetname - just area + lv_range = i_range. + ENDIF. + + REPLACE ALL OCCURRENCES OF '$' IN lv_range WITH ''. + SPLIT lv_range AT ':' INTO lv_columnrow_start lv_columnrow_end. + + convert_columnrow2column_a_row( EXPORTING + i_columnrow = lv_columnrow_start + IMPORTING + e_column = e_column_start + e_row = e_row_start ). + convert_columnrow2column_a_row( EXPORTING + i_columnrow = lv_columnrow_end + IMPORTING + e_column = e_column_end + e_row = e_row_end ). + + e_sheet = unescape_string( lv_sheet ). " Return in unescaped form +endmethod. + + + + + method DATE_TO_EXCEL_STRING. + DATA: lv_date_diff TYPE i. + + CHECK ip_value IS NOT INITIAL. + " Needed hack caused by the problem that: + " Excel 2000 incorrectly assumes that the year 1900 is a leap year + " http://support.microsoft.com/kb/214326/en-us + IF ip_value > c_excel_1900_leap_year. + lv_date_diff = ip_value - c_excel_baseline_date + 2. + ELSE. + lv_date_diff = ip_value - c_excel_baseline_date + 1. + ENDIF. + ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_date_diff ). +endmethod. + + + + + method DESCRIBE_STRUCTURE. + DATA: lt_components TYPE abap_component_tab, + lt_comps TYPE abap_component_tab, + lo_struct TYPE REF TO cl_abap_structdescr, + ls_component TYPE abap_componentdescr, + lo_elemdescr TYPE REF TO cl_abap_elemdescr, + ls_dfies TYPE dfies, + l_position TYPE tabfdpos. + + "for DDIC structure get the info directly + IF io_struct->is_ddic_type( ) = abap_true. + rt_dfies = io_struct->get_ddic_field_list( ). + ELSE. + lt_components = io_struct->get_components( ). + + LOOP AT lt_components INTO ls_component. + structure_case( EXPORTING is_component = ls_component + CHANGING xt_components = lt_comps ) . + ENDLOOP. + LOOP AT lt_comps INTO ls_component. + CLEAR ls_dfies. + IF ls_component-type->kind = cl_abap_typedescr=>kind_elem. "E Elementary Type + ADD 1 TO l_position. + lo_elemdescr ?= ls_component-type. + IF lo_elemdescr->is_ddic_type( ) = abap_true. + ls_dfies = lo_elemdescr->get_ddic_field( ). + ls_dfies-fieldname = ls_component-name. + ls_dfies-position = l_position. + ELSE. + ls_dfies-fieldname = ls_component-name. + ls_dfies-position = l_position. + ls_dfies-inttype = lo_elemdescr->type_kind. + ls_dfies-leng = lo_elemdescr->length. + ls_dfies-outputlen = lo_elemdescr->length. + ls_dfies-decimals = lo_elemdescr->decimals. + ls_dfies-fieldtext = ls_component-name. + ls_dfies-reptext = ls_component-name. + ls_dfies-scrtext_s = ls_component-name. + ls_dfies-scrtext_m = ls_component-name. + ls_dfies-scrtext_l = ls_component-name. + ls_dfies-dynpfld = abap_true. + ENDIF. + INSERT ls_dfies INTO TABLE rt_dfies. + ENDIF. + ENDLOOP. + ENDIF. +endmethod. + + + + + + + + METHOD determine_resulting_formula. + + DATA: lv_row_difference TYPE i, + lv_col_difference TYPE i. + +*--------------------------------------------------------------------* +* Calculate distance of reference and current cell +*--------------------------------------------------------------------* + calculate_cell_distance( EXPORTING + iv_reference_cell = iv_reference_cell + iv_current_cell = iv_current_cell + IMPORTING + ev_row_difference = lv_row_difference + ev_col_difference = lv_col_difference ). + +*--------------------------------------------------------------------* +* and shift formula by using the row- and columndistance +*--------------------------------------------------------------------* + ev_resulting_formula = shift_formula( iv_reference_formula = iv_reference_formula + iv_shift_rows = lv_row_difference + iv_shift_cols = lv_col_difference ). + +ENDMETHOD. "determine_resulting_formula + + + + + method ENCRYPT_PASSWORD. + + DATA lv_curr_offset TYPE i. + DATA lv_curr_char TYPE c LENGTH 1. + DATA lv_curr_hex TYPE zexcel_pwd_hash. + DATA lv_pwd_len TYPE zexcel_pwd_hash. + DATA lv_pwd_hash TYPE zexcel_pwd_hash. + + CONSTANTS: + lv_0x7fff TYPE zexcel_pwd_hash VALUE '7FFF', + lv_0x0001 TYPE zexcel_pwd_hash VALUE '0001', + lv_0xce4b TYPE zexcel_pwd_hash VALUE 'CE4B'. + + DATA lv_pwd TYPE zexcel_aes_password. + + lv_pwd = i_pwd(15). + + lv_pwd_len = STRLEN( lv_pwd ). + lv_curr_offset = lv_pwd_len - 1. + + WHILE lv_curr_offset GE 0. + + lv_curr_char = lv_pwd+lv_curr_offset(1). + lv_curr_hex = char2hex( lv_curr_char ). + + lv_pwd_hash = ( shr14( lv_pwd_hash ) BIT-AND lv_0x0001 ) BIT-OR ( shl01( lv_pwd_hash ) BIT-AND lv_0x7fff ). + + lv_pwd_hash = lv_pwd_hash BIT-XOR lv_curr_hex. + SUBTRACT 1 FROM lv_curr_offset. + ENDWHILE. + + lv_pwd_hash = ( shr14( lv_pwd_hash ) BIT-AND lv_0x0001 ) BIT-OR ( shl01( lv_pwd_hash ) BIT-AND lv_0x7fff ). + lv_pwd_hash = lv_pwd_hash BIT-XOR lv_0xce4b. + lv_pwd_hash = lv_pwd_hash BIT-XOR lv_pwd_len. + + WRITE lv_pwd_hash TO r_encrypted_pwd. + +endmethod. + + + + + method ESCAPE_STRING. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-12-08 +* - ... +* changes: aligning code +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* +* issue#242 - Support escaping for white-spaces +* - Escaping also necessary when ' encountered in input +* - Stefan Schmoecker, 2012-12-08 +* changes: switched check if escaping is necessary to regular expression +* and moved the "REPLACE" +*--------------------------------------------------------------------* +* issue#155 - lessening restrictions of input parameters +* - Stefan Schmoecker, 2012-12-08 +* changes: ip_value changed to clike +*--------------------------------------------------------------------* + DATA: lv_value TYPE string. + +*--------------------------------------------------------------------* +* There exist various situations when a space will be used to separate +* different parts of a string. When we have a string consisting spaces +* that will cause errors unless we "escape" the string by putting ' at +* the beginning and at the end of the string. +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* When allowing clike-input parameters we might encounter trailing +* "real" blanks . These are automatically eliminated when moving +* the input parameter to a string. +* Now any remaining spaces ( white-spaces or normal spaces ) should +* trigger the escaping as well as any ' +*--------------------------------------------------------------------* + lv_value = ip_value. + + + FIND REGEX `\s|'` IN lv_value. " \s finds regular and white spaces + IF sy-subrc = 0. + REPLACE ALL OCCURRENCES OF `'` IN lv_value WITH `''`. + CONCATENATE `'` lv_value `'` INTO lv_value . + ENDIF. + + ep_escaped_value = lv_value. + +endmethod. + + + + + + method EXCEL_STRING_TO_DATE. + DATA: lv_date_int TYPE i. + + TRY. + lv_date_int = ip_value. + ep_value = lv_date_int + c_excel_baseline_date - 2. + " Needed hack caused by the problem that: + " Excel 2000 incorrectly assumes that the year 1900 is a leap year + " http://support.microsoft.com/kb/214326/en-us + IF ep_value < c_excel_1900_leap_year. + ep_value = ep_value + 1. + ENDIF. + CATCH cx_sy_conversion_error. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Index out of bounds'. + ENDTRY. +endmethod. + + + + + + method EXCEL_STRING_TO_NUMBER. + +* If we encounter anything more complicated in EXCEL we might have to extend this +* But currently this works fine - even for numbers in scientific notation + + ep_value = ip_value. + +endmethod. + + + + + + method EXCEL_STRING_TO_TIME. + DATA: lv_seconds_in_day TYPE i, + lv_day_fraction TYPE f, + lc_seconds_in_day TYPE i VALUE 86400. + + TRY. + + lv_day_fraction = ip_value. + lv_seconds_in_day = lv_day_fraction * lc_seconds_in_day. + + ep_value = lv_seconds_in_day. + + CATCH cx_sy_conversion_error. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret time'. + ENDTRY. +endmethod. + + + + + + + method FAIL. + DATA: ls_seoclass TYPE seoclass. + + " Let see >=7.02 + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_ABAP_UNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>fail + EXPORTING + msg = msg + level = level + quit = quit + detail = detail. + ELSE. + " Let see >=7.00 or even lower + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_AUNIT_ASSERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>fail + EXPORTING + msg = msg + level = level + quit = quit + detail = detail. + ELSE. +* We do nothing for now not supported + ENDIF. + ENDIF. + +endmethod. + + + + + METHOD get_fieldcatalog. + DATA: lr_dref_tab TYPE REF TO data, + lo_salv_table TYPE REF TO cl_salv_table, + lo_salv_columns_table TYPE REF TO cl_salv_columns_table, + lt_salv_t_column_ref TYPE salv_t_column_ref, + ls_salv_t_column_ref LIKE LINE OF lt_salv_t_column_ref, + lo_salv_column_table TYPE REF TO cl_salv_column_table. + + FIELD-SYMBOLS: <tab> TYPE STANDARD TABLE. + FIELD-SYMBOLS: <fcat> LIKE LINE OF ep_fieldcatalog. + +* Get copy of IP_TABLE-structure <-- must be changeable to create salv + CREATE DATA lr_dref_tab LIKE ip_table. + ASSIGN lr_dref_tab->* TO <tab>. +* Create salv --> implicitly create fieldcat + TRY. + cl_salv_table=>factory( IMPORTING + r_salv_table = lo_salv_table + CHANGING + t_table = <tab> ). + lo_salv_columns_table = lo_salv_table->get_columns( ). + lt_salv_t_column_ref = lo_salv_columns_table->get( ). + CATCH cx_root. +* maybe some errorhandling here - just haven't made up my mind yet + ENDTRY. + +* Loop through columns and set relevant fields ( fieldname, texts ) + LOOP AT lt_salv_t_column_ref INTO ls_salv_t_column_ref. + + lo_salv_column_table ?= ls_salv_t_column_ref-r_column. + APPEND INITIAL LINE TO ep_fieldcatalog ASSIGNING <fcat>. + <fcat>-position = sy-tabix. + <fcat>-fieldname = ls_salv_t_column_ref-columnname. + <fcat>-scrtext_s = ls_salv_t_column_ref-r_column->get_short_text( ). + <fcat>-scrtext_m = ls_salv_t_column_ref-r_column->get_medium_text( ). + <fcat>-scrtext_l = ls_salv_t_column_ref-r_column->get_long_text( ). + <fcat>-abap_type = lo_salv_column_table->get_ddic_inttype( ). + + <fcat>-dynpfld = 'X'. " What in the world would we exclude here? + IF <fcat>-position = 1. " except for the MANDT-field of most tables ( 1st column that is ) + IF lo_salv_column_table->get_ddic_datatype( ) = 'CLNT'. + CLEAR <fcat>-dynpfld. + ENDIF. + ENDIF. + +* For fields that don't a description ( i.e. defined by "field type i," ) +* just use the fieldname as description - that is better than nothing + IF <fcat>-scrtext_s IS INITIAL + AND <fcat>-scrtext_m IS INITIAL + AND <fcat>-scrtext_l IS INITIAL. + CONCATENATE 'Col:' <fcat>-fieldname INTO <fcat>-scrtext_l SEPARATED BY space. + <fcat>-scrtext_m = <fcat>-scrtext_l. + <fcat>-scrtext_s = <fcat>-scrtext_l. + ENDIF. + + ENDLOOP. + +ENDMETHOD. + + + + + + + + method IS_CELL_IN_RANGE. + DATA lv_column_start TYPE zexcel_cell_column_alpha. + DATA lv_column_end TYPE zexcel_cell_column_alpha. + DATA lv_row_start TYPE zexcel_cell_row. + DATA lv_row_end TYPE zexcel_cell_row. + DATA lv_column_start_i TYPE zexcel_cell_column. + DATA lv_column_end_i TYPE zexcel_cell_column. + DATA lv_column_i TYPE zexcel_cell_column. + + +* Split range and convert columns + convert_range2column_a_row( + exporting + i_range = ip_range + IMPORTING + e_column_start = lv_column_start + e_column_end = lv_column_end + e_row_start = lv_row_start + e_row_end = lv_row_end ). + + lv_column_start_i = convert_column2int( ip_column = lv_column_start ). + lv_column_end_i = convert_column2int( ip_column = lv_column_end ). + + lv_column_i = convert_column2int( ip_column = ip_column ). + +* Check if cell is in range + IF lv_column_i >= lv_column_start_i AND + lv_column_i <= lv_column_end_i AND + ip_row >= lv_row_start AND + ip_row <= lv_row_end. + rp_in_range = abap_true. + ENDIF. +endmethod. + + + + + method NUMBER_TO_EXCEL_STRING. + DATA: lv_value_c TYPE c LENGTH 100. + + WRITE ip_value TO lv_value_c EXPONENT 0 NO-GROUPING NO-SIGN. + REPLACE ALL OCCURRENCES OF ',' IN lv_value_c WITH '.'. + + ep_value = lv_value_c. + CONDENSE ep_value. + + IF ip_value < 0. + CONCATENATE '-' ep_value INTO ep_value. + ELSEIF ip_value EQ 0. + ep_value = '0'. + ENDIF. +endmethod. + + + + + + method RECURSIVE_CLASS_TO_STRUCT. + " # issue 139 +* is working for me - but after looking through this coding I guess +* I'll rewrite this to a version w/o recursion +* This is private an no one using it so far except me, so no need to hurry + DATA: descr TYPE REF TO cl_abap_structdescr, + wa_component LIKE LINE OF descr->components, + attribute_name TYPE fieldname, + flag_class TYPE flag, + o_border TYPE REF TO zcl_excel_style_border. + + FIELD-SYMBOLS: <field> TYPE any, + <fieldx> TYPE any, + <class> TYPE REF TO object, + <attribute> TYPE any. + + + descr ?= cl_abap_structdescr=>describe_by_data( e_target ). + + LOOP AT descr->components INTO wa_component. + +* Assign structure and X-structure + ASSIGN COMPONENT wa_component-name OF STRUCTURE e_target TO <field>. + ASSIGN COMPONENT wa_component-name OF STRUCTURE e_targetx TO <fieldx>. +* At least one field in the structure should be marked - otherwise continue with next field + CLEAR flag_class. +* maybe source is just a structure - try assign component... + ASSIGN COMPONENT wa_component-name OF STRUCTURE i_source TO <attribute>. + IF sy-subrc <> 0. +* not - then it is an attribute of the class - use different assign then + CONCATENATE 'i_source->' wa_component-name INTO attribute_name. + ASSIGN (attribute_name) TO <attribute>. + IF sy-subrc <> 0. + EXIT. + ENDIF. " Should not happen if structure is built properly - otherwise just exit to create no dumps + flag_class = abap_true. + ENDIF. + + CASE wa_component-type_kind. + WHEN cl_abap_structdescr=>typekind_struct1 OR cl_abap_structdescr=>typekind_struct2. " Structure --> use recursio +* IF flag_class = abap_true. +** Only borders will be passed as unbound references. But since we want to set a value we have to create an instance +* ENDIF. + zcl_excel_common=>recursive_class_to_struct( EXPORTING i_source = <attribute> + CHANGING e_target = <field> + e_targetx = <fieldx> ). + WHEN OTHERS. + <field> = <attribute>. + <fieldx> = abap_true. + + ENDCASE. + ENDLOOP. + +endmethod. + + + + + + METHOD recursive_struct_to_class. + " # issue 139 +* is working for me - but after looking through this coding I guess +* I'll rewrite this to a version w/o recursion +* This is private an no one using it so far except me, so no need to hurry + DATA: descr TYPE REF TO cl_abap_structdescr, + wa_component LIKE LINE OF descr->components, + attribute_name TYPE fieldname, + flag_class TYPE flag, + o_border TYPE REF TO zcl_excel_style_border. + + FIELD-SYMBOLS: <field> TYPE any, + <fieldx> TYPE any, + <class> TYPE REF TO object, + <attribute> TYPE any, + <attribute_s> TYPE ANY TABLE. + + + descr ?= cl_abap_structdescr=>describe_by_data( i_source ). + + LOOP AT descr->components INTO wa_component. + +* Assign structure and X-structure + ASSIGN COMPONENT wa_component-name OF STRUCTURE i_source TO <field>. + ASSIGN COMPONENT wa_component-name OF STRUCTURE i_sourcex TO <fieldx>. +* At least one field in the structure should be marked - otherwise continue with next field + CHECK <fieldx> CA abap_true. + CLEAR flag_class. +* maybe target is just a structure - try assign component... + ASSIGN COMPONENT wa_component-name OF STRUCTURE e_target TO <attribute>. + IF sy-subrc <> 0. +* not - then it is an attribute of the class - use different assign then + CONCATENATE 'E_TARGET->' wa_component-name INTO attribute_name. + ASSIGN (attribute_name) TO <attribute>. + IF sy-subrc <> 0.EXIT.ENDIF. " Should not happen if structure is built properly - otherwise just exit to create no dumps + flag_class = abap_true. + ENDIF. + + CASE wa_component-type_kind. + WHEN cl_abap_structdescr=>typekind_struct1 OR cl_abap_structdescr=>typekind_struct2. " Structure --> use recursion + " To avoid dump with attribute GRADTYPE of class ZCL_EXCEL_STYLE_FILL + " quick and really dirty fix -> check the attribute name + " Border has to be initialized somewhere else + IF wa_component-name EQ 'GRADTYPE'. + flag_class = abap_false. + ENDIF. + + IF flag_class = abap_true AND <attribute> IS INITIAL. +* Only borders will be passed as unbound references. But since we want to set a value we have to create an instance + CREATE OBJECT o_border. + <attribute> = o_border. + ENDIF. + zcl_excel_common=>recursive_struct_to_class( EXPORTING i_source = <field> + i_sourcex = <fieldx> + CHANGING e_target = <attribute> ). +* WHEN cl_abap_structdescr=>typekind_struct2. " String +* CHECK <fieldx> = abap_true. " Marked for change +* <attribute_s> = <field>. + WHEN OTHERS. + CHECK <fieldx> = abap_true. " Marked for change + <attribute> = <field>. + + ENDCASE. + ENDLOOP. + +ENDMETHOD. + + + + + + + + METHOD shift_formula. + + CONSTANTS: lcv_operators TYPE string VALUE '+-/*^%=<>&, !', + lcv_letters TYPE string VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ$', + lcv_digits TYPE string VALUE '0123456789', + lcv_cell_reference_error TYPE string VALUE '#REF!'. + + DATA: lv_tcnt TYPE i, " Counter variable + lv_tlen TYPE i, " Temp variable length + lv_cnt TYPE i, " Counter variable + lv_cnt2 TYPE i, " Counter variable + lv_offset1 TYPE i, " Character offset + lv_numchars TYPE i, " Number of characters counter + lv_tchar(1) TYPE c, " Temp character + lv_tchar2(1) TYPE c, " Temp character + lv_cur_form(2000) TYPE c, " Formula for current cell + lv_ref_cell_addr TYPE string, " Reference cell address + lv_tcol1 TYPE string, " Temp column letter + lv_tcol2 TYPE string, " Temp column letter + lv_tcoln TYPE i, " Temp column number + lv_trow1 TYPE string, " Temp row number + lv_trow2 TYPE string, " Temp row number + lv_flen TYPE i, " Length of reference formula + lv_tlen2 TYPE i, " Temp variable length + lv_substr1 TYPE string, " Substring variable + lv_abscol TYPE string, " Absolute column symbol + lv_absrow TYPE string, " Absolute row symbol + + lv_errormessage TYPE string. + + FIELD-SYMBOLS: <find_my_include> TYPE ANY. + +*--------------------------------------------------------------------* +* When copying a cell in EXCEL to another cell any inherent formulas +* are copied as well. Cell-references in the formula are being adjusted +* by the distance of the new cell to the original one +*--------------------------------------------------------------------* +* §1 Parse reference formula character by character +* §2 Identify Cell-references +* §3 Shift cell-reference +* §4 Build resulting formula +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* No distance --> Reference = resulting cell/formula +*--------------------------------------------------------------------* + IF iv_shift_cols = 0 + AND iv_shift_rows = 0. + ev_resulting_formula = iv_reference_formula. + EXIT. " done + ENDIF. + + + lv_flen = STRLEN( iv_reference_formula ). + lv_numchars = 1. + +*--------------------------------------------------------------------* +* §1 Parse reference formula character by character +*--------------------------------------------------------------------* + DO lv_flen TIMES. + + CLEAR: lv_tchar, + lv_substr1, + lv_ref_cell_addr. + lv_cnt2 = lv_cnt + 1. + IF lv_cnt2 > lv_flen. + EXIT. " Done + ENDIF. + +*--------------------------------------------------------------------* +* Here we have the current character in the formula +*--------------------------------------------------------------------* + lv_tchar = iv_reference_formula+lv_cnt(1). + +*--------------------------------------------------------------------* +* Operators or opening parenthesis will separate possible cellreferences +*--------------------------------------------------------------------* + IF ( lv_tchar CA lcv_operators + OR lv_tchar CA '(' ) + AND lv_cnt2 = 1. + lv_substr1 = iv_reference_formula+lv_offset1(1). + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_numchars = 1. + CONTINUE. " --> next character in formula can be analyzed + ENDIF. + +*--------------------------------------------------------------------* +* Quoted literal text holds no cell reference --> advance to end of text +*--------------------------------------------------------------------* + IF lv_tchar EQ '"'. + lv_cnt = lv_cnt + 1. + lv_numchars = lv_numchars + 1. + lv_tchar = iv_reference_formula+lv_cnt(1). + WHILE lv_tchar NE '"'. + + lv_cnt = lv_cnt + 1. + lv_numchars = lv_numchars + 1. + lv_tchar = iv_reference_formula+lv_cnt(1). + + ENDWHILE. + lv_cnt2 = lv_cnt + 1. + lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars). + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + IF lv_cnt = lv_flen. + EXIT. + ENDIF. + lv_offset1 = lv_cnt. + lv_numchars = 1. + lv_tchar = iv_reference_formula+lv_cnt(1). + lv_cnt2 = lv_cnt + 1. + CONTINUE. " --> next character in formula can be analyzed + ENDIF. + + +*--------------------------------------------------------------------* +* Operators or parenthesis or last character in formula will separate possible cellreferences +*--------------------------------------------------------------------* + IF lv_tchar CA lcv_operators + OR lv_tchar CA '():' + OR lv_cnt2 = lv_flen. + IF lv_cnt > 0. + lv_substr1 = iv_reference_formula+lv_offset1(lv_numchars). +*--------------------------------------------------------------------* +* Check for text concatenation and functions +*--------------------------------------------------------------------* + IF ( lv_tchar CA lcv_operators AND lv_tchar EQ lv_substr1 ) OR lv_tchar EQ '('. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. " --> next character in formula can be analyzed + ENDIF. + + lv_tlen = lv_cnt2 - lv_offset1. +*--------------------------------------------------------------------* +* Exclude mathematical operators and closing parentheses +*--------------------------------------------------------------------* + IF lv_tchar CA lcv_operators + OR lv_tchar CA ':)'. + IF lv_cnt2 = lv_flen + AND lv_numchars = 1. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. " --> next character in formula can be analyzed + ELSE. + lv_tlen = lv_tlen - 1. + ENDIF. + ENDIF. +*--------------------------------------------------------------------* +* Capture reference cell address +*--------------------------------------------------------------------* + TRY. + MOVE: iv_reference_formula+lv_offset1(lv_tlen) TO lv_ref_cell_addr. "Ref cell address + CATCH cx_root. + lv_errormessage = 'Internal error in Class ZCL_EXCEL_COMMON Method SHIFT_FORMULA Spot 1 '. " Change to messageclass if possible + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDTRY. + +*--------------------------------------------------------------------* +* Split cell address into characters and numbers +*--------------------------------------------------------------------* + CLEAR: lv_tlen, + lv_tcnt, + lv_tcol1, + lv_trow1. + lv_tlen = STRLEN( lv_ref_cell_addr ). + IF lv_tlen <> 0. + CLEAR: lv_tcnt. + DO lv_tlen TIMES. + CLEAR: lv_tchar2. + lv_tchar2 = lv_ref_cell_addr+lv_tcnt(1). + IF lv_tchar2 CA lcv_letters. + CONCATENATE lv_tcol1 lv_tchar2 INTO lv_tcol1. + ELSEIF lv_tchar2 CA lcv_digits. + CONCATENATE lv_trow1 lv_tchar2 INTO lv_trow1. + ENDIF. + lv_tcnt = lv_tcnt + 1. + ENDDO. + ENDIF. +*--------------------------------------------------------------------* +* Check for invalid cell address +*--------------------------------------------------------------------* + IF lv_tcol1 IS INITIAL OR lv_trow1 IS INITIAL. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDIF. +*--------------------------------------------------------------------* +* Check for range names +*--------------------------------------------------------------------* + CLEAR: lv_tlen. + lv_tlen = STRLEN( lv_tcol1 ). + IF lv_tlen GT 3. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDIF. +*--------------------------------------------------------------------* +* Check for valid row +*--------------------------------------------------------------------* + IF lv_trow1 GT 1048576. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDIF. +*--------------------------------------------------------------------* +* Check for absolute column or row reference +*--------------------------------------------------------------------* + CLEAR: lv_tcol2, + lv_trow2, + lv_abscol, + lv_absrow. + lv_tlen2 = STRLEN( lv_tcol1 ) - 1. + IF lv_tcol1 IS NOT INITIAL. + lv_abscol = lv_tcol1(1). + ENDIF. + IF lv_tlen2 GE 0. + lv_absrow = lv_tcol1+lv_tlen2(1). + ENDIF. + IF lv_abscol EQ '$' AND lv_absrow EQ '$'. + lv_tlen2 = lv_tlen2 - 1. + IF lv_tlen2 > 0. + lv_tcol1 = lv_tcol1+1(lv_tlen2). + ENDIF. + lv_tlen2 = lv_tlen2 + 1. + ELSEIF lv_abscol EQ '$'. + lv_tcol1 = lv_tcol1+1(lv_tlen2). + ELSEIF lv_absrow EQ '$'. + lv_tcol1 = lv_tcol1(lv_tlen2). + ENDIF. +*--------------------------------------------------------------------* +* Check for valid column +*--------------------------------------------------------------------* + TRY. + lv_tcoln = zcl_excel_common=>convert_column2int( lv_tcol1 ) + iv_shift_cols. + CATCH zcx_excel. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDTRY. +*--------------------------------------------------------------------* +* Check whether there is a referencing problem +*--------------------------------------------------------------------* + lv_trow2 = lv_trow1 + iv_shift_rows. + IF ( lv_tcoln < 1 AND lv_abscol <> '$' ) " Maybe we should add here max-column and max row-tests as well. + OR ( lv_trow2 < 1 AND lv_absrow <> '$' ). " Check how EXCEL behaves in this case +*--------------------------------------------------------------------* +* Referencing problem encountered --> set error +*--------------------------------------------------------------------* + CONCATENATE lv_cur_form lcv_cell_reference_error INTO lv_cur_form. + ELSE. +*--------------------------------------------------------------------* +* No referencing problems --> adjust row and column +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* Adjust column +*--------------------------------------------------------------------* + IF lv_abscol EQ '$'. + CONCATENATE lv_cur_form lv_abscol lv_tcol1 INTO lv_cur_form. + ELSEIF iv_shift_cols EQ 0. + CONCATENATE lv_cur_form lv_tcol1 INTO lv_cur_form. + ELSE. + TRY. + lv_tcol2 = zcl_excel_common=>convert_column2alpha( lv_tcoln ). + CONCATENATE lv_cur_form lv_tcol2 INTO lv_cur_form. + CATCH zcx_excel. + CONCATENATE lv_cur_form lv_substr1 INTO lv_cur_form. + lv_cnt = lv_cnt + 1. + lv_offset1 = lv_cnt. + lv_cnt2 = lv_cnt + 1. + lv_numchars = 1. + CONTINUE. + ENDTRY. + ENDIF. +*--------------------------------------------------------------------* +* Adjust row +*--------------------------------------------------------------------* + IF lv_absrow EQ '$'. + CONCATENATE lv_cur_form lv_absrow lv_trow1 INTO lv_cur_form. + ELSEIF iv_shift_rows = 0. + CONCATENATE lv_cur_form lv_trow1 INTO lv_cur_form. +* elseif lv_trow2 < 1. +* CONCATENATE lv_cur_form lc_cell_reference_error INTO lv_cur_form. + ELSE. + CONCATENATE lv_cur_form lv_trow2 INTO lv_cur_form. + ENDIF. + ENDIF. + + lv_numchars = 0. + IF lv_tchar CA lcv_operators + OR lv_tchar CA ':)'. + CONCATENATE lv_cur_form lv_tchar INTO lv_cur_form. + ENDIF. + lv_offset1 = lv_cnt2. + ENDIF. + ENDIF. + lv_numchars = lv_numchars + 1. + lv_cnt = lv_cnt + 1. + lv_cnt2 = lv_cnt + 1. + + ENDDO. + + + +*--------------------------------------------------------------------* +* Return resulting formula +*--------------------------------------------------------------------* + IF lv_cur_form IS NOT INITIAL. + MOVE lv_cur_form TO ev_resulting_formula. + ENDIF. + +ENDMETHOD. + + + + + method SHL01. + + DATA: + lv_bit TYPE i, + lv_curr_pos TYPE i VALUE 2, + lv_prev_pos TYPE i VALUE 1. + + DO 15 TIMES. + GET BIT lv_curr_pos OF i_pwd_hash INTO lv_bit. + SET BIT lv_prev_pos OF r_pwd_hash TO lv_bit. + ADD 1 TO lv_curr_pos. + ADD 1 TO lv_prev_pos. + ENDDO. + SET BIT 16 OF r_pwd_hash TO 0. + +endmethod. + + + + + method SHR14. + + DATA: + lv_bit TYPE i, + lv_curr_pos TYPE i, + lv_next_pos TYPE i. + + r_pwd_hash = i_pwd_hash. + + DO 14 TIMES. + lv_curr_pos = 15. + lv_next_pos = 16. + + DO 15 TIMES. + GET BIT lv_curr_pos OF r_pwd_hash INTO lv_bit. + SET BIT lv_next_pos OF r_pwd_hash TO lv_bit. + SUBTRACT 1 FROM lv_curr_pos. + SUBTRACT 1 FROM lv_next_pos. + ENDDO. + SET BIT 1 OF r_pwd_hash TO 0. + ENDDO. + +endmethod. + + + + + + + method SPLIT_FILE. + + DATA: lt_hlp TYPE TABLE OF text255, + ls_hlp TYPE text255. + + DATA: lf_ext(10) TYPE c, + lf_dot_ext(10) TYPE c. + DATA: lf_str TYPE text255, + lf_anz TYPE i, + lf_len TYPE i. +** --------------------------------------------------------------------- + + CLEAR: lt_hlp, + ep_file, + ep_extension, + ep_dotextension. + +** Split the whole file at '.' + SPLIT ip_file AT '.' INTO TABLE lt_hlp. + +** get the extenstion from the last line of table + DESCRIBE TABLE lt_hlp LINES lf_anz. + IF lf_anz <= 1. + ep_file = ip_file. + EXIT. + ENDIF. + + READ TABLE lt_hlp INTO ls_hlp INDEX lf_anz. + ep_extension = ls_hlp. + lf_ext = ls_hlp. + IF NOT lf_ext IS INITIAL. + CONCATENATE '.' lf_ext INTO lf_dot_ext. + ENDIF. + ep_dotextension = lf_dot_ext. + +** get only the filename + lf_len = strlen( ip_file ) - strlen( lf_dot_ext ). + IF lf_len > 0. + ep_file = ip_file(lf_len). + ENDIF. + +endmethod. + + + + + method STRUCTURE_CASE. + DATA: lt_comp_str TYPE abap_component_tab. + + CASE is_component-type->kind. + WHEN cl_abap_typedescr=>kind_elem. "E Elementary Type + INSERT is_component INTO TABLE xt_components. + WHEN cl_abap_typedescr=>kind_table. "T Table + INSERT is_component INTO TABLE xt_components. + WHEN cl_abap_typedescr=>kind_struct. "S Structure + lt_comp_str = structure_recursive( is_component = is_component ). + INSERT LINES OF lt_comp_str INTO TABLE xt_components. + WHEN OTHERS. "cl_abap_typedescr=>kind_ref or cl_abap_typedescr=>kind_class or cl_abap_typedescr=>kind_intf. +* We skip it. for now. + ENDCASE. +endmethod. + + + + + method STRUCTURE_RECURSIVE. + DATA: lo_struct TYPE REF TO cl_abap_structdescr, + lt_components TYPE abap_component_tab, + ls_components TYPE abap_componentdescr. + + REFRESH rt_components. + + lo_struct ?= is_component-type. + lt_components = lo_struct->get_components( ). + + LOOP AT lt_components INTO ls_components. + structure_case( EXPORTING is_component = ls_components + CHANGING xt_components = rt_components ) . + ENDLOOP. + +endmethod. + + + + + method TIME_TO_EXCEL_STRING. + DATA: lv_seconds_in_day TYPE i, + lv_day_fraction TYPE f, + lc_time_baseline TYPE t VALUE '000000', + lc_seconds_in_day TYPE i VALUE 86400. + + lv_seconds_in_day = ip_value - lc_time_baseline. + lv_day_fraction = lv_seconds_in_day / lc_seconds_in_day. + ep_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_day_fraction ). +endmethod. + + + + + + method UNESCAPE_STRING. + + CONSTANTS lcv_regex TYPE string VALUE `^'[^']` & `|` & " Beginning single ' OR + `[^']'$` & `|` & " Trailing single ' OR + `[^']'[^']`. " Single ' somewhere in between + + + DATA: lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + +*--------------------------------------------------------------------* +* This method is used to extract the "real" string from an escaped string. +* An escaped string can be identified by a beginning ' which must be +* accompanied by a trailing ' +* All '' in between beginning and trailing ' are treated as single ' +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* When allowing clike-input parameters we might encounter trailing +* "real" blanks . These are automatically eliminated when moving +* the input parameter to a string. +*--------------------------------------------------------------------* + ev_unescaped_string = iv_escaped. " Pass through if not escaped + + CHECK ev_unescaped_string IS NOT INITIAL. " Nothing to do if empty + CHECK ev_unescaped_string(1) = `'`. " Nothing to do if not escaped + +*--------------------------------------------------------------------* +* Remove leading and trailing ' +*--------------------------------------------------------------------* + REPLACE REGEX `^'(.*)'$` IN ev_unescaped_string WITH '$1'. + IF sy-subrc <> 0. + lv_errormessage = 'Input not properly escaped - &'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Any remaining single ' should not be here +*--------------------------------------------------------------------* + FIND REGEX lcv_regex IN ev_unescaped_string. + IF sy-subrc = 0. + lv_errormessage = 'Input not properly escaped - &'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Replace '' with ' +*--------------------------------------------------------------------* + REPLACE ALL OCCURRENCES OF `''` IN ev_unescaped_string WITH `'`. + + +endmethod. + + + + + + + + + *"* 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 ts_alv_types, + seoclass TYPE seoclsname, + clsname TYPE seoclsname, + END OF ts_alv_types, + tt_alv_types TYPE HASHED TABLE OF ts_alv_types WITH UNIQUE KEY seoclass. + +TYPES: BEGIN OF ts_sort_values, + fieldname TYPE fieldname, + row_int TYPE zexcel_cell_row, + value TYPE REF TO data, + new TYPE flag, + sort_level TYPE int4, + is_collapsed type flag, + END OF ts_sort_values, + + tt_sort_values TYPE HASHED TABLE OF ts_sort_values WITH UNIQUE KEY fieldname. +TYPES: BEGIN OF ts_subtotal_rows, + row_int TYPE zexcel_cell_row, + row_int_start TYPE zexcel_cell_row, + columnname TYPE fieldname, + END OF ts_subtotal_rows, + + tt_subtotal_rows TYPE HASHED TABLE OF ts_subtotal_rows WITH UNIQUE KEY row_int. + +TYPES: BEGIN OF ts_styles, + type TYPE char1, + alignment TYPE zexcel_alignment, + inttype TYPE inttype, + decimals TYPE int1, + style TYPE REF TO zcl_excel_style, + guid TYPE zexcel_cell_style, + END OF ts_styles, + + tt_styles TYPE HASHED TABLE OF ts_styles WITH UNIQUE KEY type alignment inttype decimals. + +TYPES: BEGIN OF ts_color_styles, + guid_old TYPE zexcel_cell_style, + fontcolor TYPE zexcel_style_color_argb, + fillcolor TYPE zexcel_style_color_argb, + style_new TYPE REF TO zcl_excel_style, + END OF ts_color_styles, + + tt_color_styles TYPE HASHED TABLE OF ts_color_styles WITH UNIQUE KEY guid_old fontcolor fillcolor. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + ABAP + SLIS + SOI + + + + + + + + + + + + + + + + + + + + + + + + + + + + method ASK_OPTION. + DATA: ls_sval TYPE sval, + lt_sval TYPE STANDARD TABLE OF sval, + l_returncode TYPE string, + lt_fields TYPE ddfields, + ls_fields TYPE dfies. + + FIELD-SYMBOLS: <fs> TYPE ANY. + + rs_option = ws_option. + + CALL FUNCTION 'DDIF_FIELDINFO_GET' + EXPORTING + tabname = 'ZEXCEL_S_CONVERTER_OPTION' +* FIELDNAME = ' ' +* LANGU = sy-langu +* LFIELDNAME = ' ' +* ALL_TYPES = ' ' +* GROUP_NAMES = ' ' +* UCLEN = +* IMPORTING +* X030L_WA = +* DDOBJTYPE = +* DFIES_WA = +* LINES_DESCR = + TABLES + dfies_tab = lt_fields +* FIXED_VALUES = + EXCEPTIONS + not_found = 1 + internal_error = 2 + OTHERS = 3 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ENDIF. + + LOOP AT lt_fields INTO ls_fields. + ASSIGN COMPONENT ls_fields-fieldname OF STRUCTURE ws_option TO <fs>. + IF sy-subrc = 0. + CLEAR ls_sval. + ls_sval-tabname = ls_fields-tabname. + ls_sval-fieldname = ls_fields-fieldname. + ls_sval-value = <fs>. + ls_sval-field_attr = space. + ls_sval-field_obl = space. + ls_sval-comp_code = space. + ls_sval-fieldtext = ls_fields-scrtext_m. + ls_sval-comp_tab = space. + ls_sval-comp_field = space. + ls_sval-novaluehlp = space. + INSERT ls_sval INTO TABLE lt_sval. + ENDIF. + ENDLOOP. + + CALL FUNCTION 'POPUP_GET_VALUES' + EXPORTING +* NO_VALUE_CHECK = space + popup_title = 'Excel creation options'(008) +* START_COLUMN = '5' +* START_ROW = '5' + IMPORTING + returncode = l_returncode + TABLES + fields = lt_sval + EXCEPTIONS + error_in_fields = 1 + OTHERS = 2 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ELSE. + IF l_returncode = 'A'. + RAISE EXCEPTION TYPE zcx_excel. + ELSE. + LOOP AT lt_sval INTO ls_sval. + ASSIGN COMPONENT ls_sval-fieldname OF STRUCTURE ws_option TO <fs>. + IF sy-subrc = 0. + <fs> = ls_sval-value. + ENDIF. + ENDLOOP. + set_option( is_option = ws_option ) . + rs_option = ws_option. + ENDIF. + ENDIF. + endmethod. + + + + + method BIND_CELLS. + +* Do we need subtotals with grouping + READ TABLE wt_fieldcatalog TRANSPORTING NO FIELDS WITH KEY is_subtotalled = abap_true. + IF sy-subrc = 0 . + r_freeze_col = loop_subtotal( i_row_int = w_row_int + i_col_int = w_col_int ) . + ELSE. + r_freeze_col = loop_normal( i_row_int = w_row_int + i_col_int = w_col_int ) . + ENDIF. + + endmethod. + + + + + + method BIND_TABLE. + data: lt_field_catalog type zexcel_t_fieldcatalog, + ls_field_catalog type zexcel_s_fieldcatalog, + ls_fcat type zexcel_s_converter_fcat, + lo_col_dim type ref to zcl_excel_worksheet_columndime, + lo_row_dim type ref to zcl_excel_worksheet_rowdimensi, + l_col_int type zexcel_cell_column, + l_col_alpha type zexcel_cell_column_alpha, + ls_settings type zexcel_s_table_settings, + l_line type i. + + field-symbols: <fs_tab> type any table. + + assign wo_data->* to <fs_tab> . + + ls_settings-table_style = i_style_table. + ls_settings-top_left_column = zcl_excel_common=>convert_column2alpha( ip_column = w_col_int ). + ls_settings-top_left_row = w_row_int. + ls_settings-show_row_stripes = ws_layout-is_stripped. + + describe table wt_fieldcatalog lines l_line. + l_line = l_line + 1 + w_col_int. + ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( ip_column = l_line ). + + describe table <fs_tab> lines l_line. + ls_settings-bottom_right_row = l_line + 1 + w_row_int. + sort wt_fieldcatalog by position. + loop at wt_fieldcatalog into ls_fcat. + move-corresponding ls_fcat to ls_field_catalog. + ls_field_catalog-dynpfld = abap_true. + insert ls_field_catalog into table lt_field_catalog. + endloop. + + wo_worksheet->bind_table( + exporting + ip_table = <fs_tab> + it_field_catalog = lt_field_catalog + is_table_settings = ls_settings + importing + es_table_settings = ls_settings + ). + loop at wt_fieldcatalog into ls_fcat. + l_col_int = w_col_int + ls_fcat-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). +* Freeze panes + if ls_fcat-fix_column = abap_true. + add 1 to r_freeze_col. + endif. +* Now let's check for optimized + if ls_fcat-is_optimized = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + endif. +* Now let's check for visible + if ls_fcat-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + endif. + endloop. + + endmethod. + + + method CLASS_CONSTRUCTOR. + DATA: ls_objects TYPE ts_alv_types. + DATA: ls_option TYPE zexcel_s_converter_option, + l_uname TYPE sy-uname. + + GET PARAMETER ID 'ZUS' FIELD l_uname. + IF l_uname IS INITIAL OR l_uname = space. + l_uname = sy-uname. + ENDIF. + +* Object CL_GUI_ALV_GRID + ls_objects-seoclass = 'CL_GUI_ALV_GRID'. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_ALV_GRID'. + INSERT ls_objects INTO TABLE wt_objects. + +* Object CL_SALV_TABLE + ls_objects-seoclass = 'CL_SALV_TABLE'. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_SALV_TABLE'. + INSERT ls_objects INTO TABLE wt_objects. + +* Object CL_SALV_RESULT + ls_objects-seoclass = 'CL_SALV_EX_RESULT_DATA_TABLE '. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_RESULT_EX'. + INSERT ls_objects INTO TABLE wt_objects. +* Object CL_SALV_WD_RESULT + ls_objects-seoclass = 'CL_SALV_WD_RESULT_DATA_TABLE '. + ls_objects-clsname = 'ZCL_EXCEL_CONVERTER_RESULT_WD'. + INSERT ls_objects INTO TABLE wt_objects. + + CONCATENATE 'EXCEL_' sy-uname INTO ws_indx-srtfd. + + IMPORT p1 = ls_option FROM DATABASE indx(xl) TO ws_indx ID ws_indx-srtfd. + + IF sy-subrc = 0. + ws_option = ls_option. + ELSE. + init_option( ) . + ENDIF. + + endmethod. + + + method CLEAN_FIELDCATALOG. + DATA: l_position TYPE int1. + + FIELD-SYMBOLS: <fs_sfcat> TYPE zexcel_s_converter_fcat. + + SORT wt_fieldcatalog BY position col_id. + + CLEAR l_position. + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + ADD 1 TO l_position. + <fs_sfcat>-position = l_position. +* Default stype with alignment and format + <fs_sfcat>-style_hdr = get_style( i_type = c_type_hdr + i_alignment = <fs_sfcat>-alignment ). + IF ws_layout-is_stripped = abap_true. + <fs_sfcat>-style_stripped = get_style( i_type = c_type_str + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + ENDIF. + <fs_sfcat>-style_normal = get_style( i_type = c_type_nor + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + <fs_sfcat>-style_subtotal = get_style( i_type = c_type_sub + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + <fs_sfcat>-style_total = get_style( i_type = c_type_tot + i_alignment = <fs_sfcat>-alignment + i_inttype = <fs_sfcat>-inttype + i_decimals = <fs_sfcat>-decimals ). + ENDLOOP. + + endmethod. + + + + + + + + + + + + + method CONVERT. + + IF is_option IS SUPPLIED. + ws_option = is_option. + ENDIF. + + TRY. + execute_converter( EXPORTING io_object = io_alv + it_table = it_table ) . + ENDTRY. + + IF io_worksheet IS SUPPLIED AND io_worksheet IS BOUND. + wo_worksheet = io_worksheet. + ENDIF. + IF co_excel IS SUPPLIED. + IF co_excel IS NOT BOUND. + CREATE OBJECT co_excel. + co_excel->zif_excel_book_properties~creator = sy-uname. + ENDIF. + wo_excel = co_excel. + ENDIF. + +* Move table to data object and clean it up + IF wt_fieldcatalog IS NOT INITIAL. + create_table( ). + ELSE. + wo_data = wo_table . + ENDIF. + + IF wo_excel IS NOT BOUND. + CREATE OBJECT wo_excel. + wo_excel->zif_excel_book_properties~creator = sy-uname. + ENDIF. + IF wo_worksheet IS NOT BOUND. + " Get active sheet + wo_worksheet = wo_excel->get_active_worksheet( ). + wo_worksheet->set_title( ip_title = 'Sheet1'(001) ). + ENDIF. + + IF i_row_int <= 0. + w_row_int = 1. + ELSE. + w_row_int = i_row_int. + ENDIF. + IF i_column_int <= 0. + w_col_int = 1. + ELSE. + w_col_int = i_column_int. + ENDIF. + + create_worksheet( i_table = i_table + i_style_table = i_style_table ) . + + endmethod. + + + + + + method CREATE_COLOR_STYLE. + DATA: ls_styles TYPE ts_styles. + DATA: lo_style TYPE REF TO zcl_excel_style. + + READ TABLE wt_styles INTO ls_styles WITH KEY guid = i_style. + IF sy-subrc = 0. + lo_style = wo_excel->add_new_style( ). +* lo_style->borders = ls_styles-style->borders. +* lo_style->protection = ls_styles-style->protection. + lo_style->font->bold = ls_styles-style->font->bold. + lo_style->alignment->horizontal = ls_styles-style->alignment->horizontal. + lo_style->number_format->format_code = ls_styles-style->number_format->format_code. + + lo_style->font->color-rgb = is_colors-fontcolor. + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = is_colors-fillcolor. + + ro_style = lo_style. + ENDIF. + endmethod. + + + + + + + + method CREATE_FORMULAR_SUBTOTAL. + data: l_row_alpha_start type string, + l_row_alpha_end type string, + l_func_num type string. + + l_row_alpha_start = i_row_int_start. + l_row_alpha_end = i_row_int_end. + + l_func_num = get_function_number( i_totals_function = i_totals_function ). + concatenate 'SUBTOTAL(' l_func_num ',' i_column l_row_alpha_start ':' i_column l_row_alpha_end ')' into r_formula. + endmethod. + + + + + + + method CREATE_FORMULAR_TOTAL. + data: l_row_alpha type string, + l_row_e_alpha type string. + + l_row_alpha = w_row_int + 1. + l_row_e_alpha = i_row_int. + + concatenate i_totals_function '(' i_column l_row_alpha ':' i_column l_row_e_alpha ')' into r_formula. + endmethod. + + + + method CREATE_PATH. + DATA: l_sep TYPE c , + l_path TYPE string, + l_return TYPE i . + + CLEAR r_path. + + " Save the file + cl_gui_frontend_services=>get_sapgui_workdir( + CHANGING + sapworkdir = l_path + EXCEPTIONS + get_sapworkdir_failed = 1 + cntl_error = 2 + error_no_gui = 3 + not_supported_by_gui = 4 + ). + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + CONCATENATE 'Excel_' w_fcount '.xlsx' INTO r_path. + ELSE. + DO. + ADD 1 TO w_fcount. +*-obtain file separator character--------------------------------------- + CALL METHOD cl_gui_frontend_services=>get_file_separator + CHANGING + file_separator = l_sep + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4. + + IF sy-subrc <> 0. + l_sep = ''. + ENDIF. + + CONCATENATE l_path l_sep 'Excel_' w_fcount '.xlsx' INTO r_path. + + IF cl_gui_frontend_services=>file_exist( file = r_path ) = abap_true. + cl_gui_frontend_services=>file_delete( EXPORTING filename = r_path + CHANGING rc = l_return + EXCEPTIONS OTHERS = 1 ). + IF sy-subrc = 0 . + RETURN. + ENDIF. + ELSE. + RETURN. + ENDIF. + ENDDO. + ENDIF. + + endmethod. + + + + + method CREATE_STYLE_HDR. + data: lo_style type ref to zcl_excel_style. + + lo_style = wo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + lo_style->font->color-rgb = zcl_excel_style_color=>c_white. + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = 'FF4F81BD'. + if i_alignment is supplied and i_alignment is not initial. + lo_style->alignment->horizontal = i_alignment. + endif. + ro_style = lo_style . + endmethod. + + + + + + + method CREATE_STYLE_NORMAL. + DATA: lo_style TYPE REF TO zcl_excel_style, + l_format TYPE zexcel_number_format. + + IF i_inttype IS SUPPLIED AND i_inttype IS NOT INITIAL. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + ENDIF. + IF l_format IS NOT INITIAL OR + ( i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL ) . + + lo_style = wo_excel->add_new_style( ). + + IF i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL. + lo_style->alignment->horizontal = i_alignment. + ENDIF. + + IF l_format IS NOT INITIAL. + lo_style->number_format->format_code = l_format. + ENDIF. + + ro_style = lo_style . + + ENDIF. + endmethod. + + + + + + + method CREATE_STYLE_STRIPPED. + data: lo_style type ref to zcl_excel_style. + data: l_format type zexcel_number_format. + + lo_style = wo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = 'FFDBE5F1'. + if i_alignment is supplied and i_alignment is not initial. + lo_style->alignment->horizontal = i_alignment. + endif. + if i_inttype is supplied and i_inttype is not initial. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + if l_format is not initial. + lo_style->number_format->format_code = l_format. + endif. + endif. + ro_style = lo_style. + + endmethod. + + + + + + + method CREATE_STYLE_SUBTOTAL. + data: lo_style type ref to zcl_excel_style. + data: l_format type zexcel_number_format. + + lo_style = wo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + + if i_alignment is supplied and i_alignment is not initial. + lo_style->alignment->horizontal = i_alignment. + endif. + if i_inttype is supplied and i_inttype is not initial. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + if l_format is not initial. + lo_style->number_format->format_code = l_format. + endif. + endif. + + ro_style = lo_style . + + endmethod. + + + + + + + method CREATE_STYLE_TOTAL. + DATA: lo_style TYPE REF TO zcl_excel_style. + DATA: l_format TYPE zexcel_number_format. + + lo_style = wo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + + CREATE OBJECT lo_style->borders->top. + lo_style->borders->top->border_style = zcl_excel_style_border=>c_border_thin. + lo_style->borders->top->border_color-rgb = zcl_excel_style_color=>c_black. + + CREATE OBJECT lo_style->borders->right. + lo_style->borders->right->border_style = zcl_excel_style_border=>c_border_none. + lo_style->borders->right->border_color-rgb = zcl_excel_style_color=>c_black. + + CREATE OBJECT lo_style->borders->down. + lo_style->borders->down->border_style = zcl_excel_style_border=>c_border_double. + lo_style->borders->down->border_color-rgb = zcl_excel_style_color=>c_black. + + CREATE OBJECT lo_style->borders->left. + lo_style->borders->left->border_style = zcl_excel_style_border=>c_border_none. + lo_style->borders->left->border_color-rgb = zcl_excel_style_color=>c_black. + + IF i_alignment IS SUPPLIED AND i_alignment IS NOT INITIAL. + lo_style->alignment->horizontal = i_alignment. + ENDIF. + IF i_inttype IS SUPPLIED AND i_inttype IS NOT INITIAL. + l_format = set_cell_format( i_inttype = i_inttype + i_decimals = i_decimals ) . + IF l_format IS NOT INITIAL. + lo_style->number_format->format_code = l_format. + ENDIF. + ENDIF. + + ro_style = lo_style . + + endmethod. + + + method CREATE_TABLE. + TYPES: BEGIN OF ts_output, + fieldname TYPE fieldname, + function TYPE funcname, + END OF ts_output. + + DATA: lo_data TYPE REF TO data. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + lt_components_tab TYPE cl_abap_structdescr=>component_table, + ls_components TYPE abap_componentdescr, + lo_table TYPE REF TO cl_abap_tabledescr, + lo_struc TYPE REF TO cl_abap_structdescr, + lt_fieldcatalog TYPE zexcel_t_converter_fcat. + + FIELD-SYMBOLS: <fs_scat> TYPE zexcel_s_converter_fcat, + <fs_stab> TYPE ANY, + <fs_ttab> TYPE STANDARD TABLE, + <fs> TYPE ANY, + <fs_table> TYPE STANDARD TABLE. + + SORT wt_fieldcatalog BY position. + ASSIGN wo_table->* TO <fs_table>. + + READ TABLE <fs_table> ASSIGNING <fs_stab> INDEX 1. + IF sy-subrc EQ 0 . + LOOP AT wt_fieldcatalog ASSIGNING <fs_scat>. + ASSIGN COMPONENT <fs_scat>-columnname OF STRUCTURE <fs_stab> TO <fs>. + IF sy-subrc = 0. + ls_components-name = <fs_scat>-columnname. + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). + CATCH cx_sy_move_cast_error. + CLEAR lo_addit. + DELETE TABLE wt_fieldcatalog FROM <fs_scat>. + ENDTRY. + IF lo_addit IS BOUND. + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ENDIF. + ENDIF. + ENDLOOP. + IF lt_components_tab IS NOT INITIAL. + "create new line type + TRY. + lo_struc = cl_abap_structdescr=>create( P_COMPONENTS = lt_components_tab + P_STRICT = abap_false ). + CATCH cx_sy_struct_creation. + RETURN. " We can not do anything in this case. + ENDTRY. + + lo_table = cl_abap_tabledescr=>create( lo_struc ). + + CREATE DATA wo_data TYPE HANDLE lo_table. + CREATE DATA lo_data TYPE HANDLE lo_struc. + + ASSIGN wo_data->* TO <fs_ttab>. + ASSIGN lo_data->* TO <fs_stab>. + LOOP AT <fs_table> ASSIGNING <fs>. + CLEAR <fs_stab>. + MOVE-CORRESPONDING <fs> TO <fs_stab>. + APPEND <fs_stab> TO <fs_ttab>. + ENDLOOP. + ENDIF. + ENDIF. + + endmethod. + + + + + + METHOD create_text_subtotal. + DATA: l_string(256) TYPE c, + l_func TYPE string. + + CASE i_totals_function. + WHEN zcl_excel_table=>totals_function_sum. " Total + l_func = 'Total'(003). + WHEN zcl_excel_table=>totals_function_min. " Minimum + l_func = 'Minimum'(004). + WHEN zcl_excel_table=>totals_function_max. " Maximum + l_func = 'Maximum'(005). + WHEN zcl_excel_table=>totals_function_average. " Mean Value + l_func = 'Average'(006). + WHEN zcl_excel_table=>totals_function_count. " Count + l_func = 'Count'(007). + WHEN OTHERS. + CLEAR l_func. + ENDCASE. + + MOVE i_value TO l_string. + + CONCATENATE l_string l_func INTO r_text SEPARATED BY space. + +ENDMETHOD. + + + + + + method CREATE_WORKSHEET. + DATA: l_freeze_col TYPE i. + DATA: l_guid TYPE oltpguid16. + + IF wo_data IS BOUND AND wo_worksheet IS BOUND. + + wo_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. " By default is on + + IF wt_fieldcatalog IS INITIAL. + set_fieldcatalog( ) . + ELSE. + clean_fieldcatalog( ) . + ENDIF. + + IF i_table = abap_true. + l_freeze_col = bind_table( i_style_table = i_style_table ) . + ELSE. +* Let's check for filter. + IF wt_filter IS NOT INITIAL. + wo_autofilter = wo_excel->add_new_autofilter( io_sheet = wo_worksheet ). + l_freeze_col = bind_cells( ) . + set_autofilter_area( ) . + ELSE. + l_freeze_col = bind_cells( ) . + ENDIF. + + ENDIF. + +* Check for freeze panes + IF ws_layout-is_fixed = abap_true. + IF l_freeze_col = 0. + l_freeze_col = w_col_int. + ENDIF. + wo_worksheet->freeze_panes( EXPORTING ip_num_columns = l_freeze_col + ip_num_rows = w_row_int ) . + ENDIF. + ENDIF. + + endmethod. + + + + + + method EXECUTE_CONVERTER. + DATA: lt_fieldcatalog TYPE zexcel_t_fieldcatalog, + ls_fieldcatalog TYPE zexcel_s_converter_fcat, + lo_if TYPE REF TO zif_excel_converter, + ls_types TYPE ts_alv_types, + lo_addit TYPE REF TO cl_abap_classdescr, + lo_addit_superclass type ref to cl_abap_classdescr. + + IF io_object IS BOUND. + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_object_ref( io_object ). + CATCH cx_sy_move_cast_error. + RAISE EXCEPTION TYPE zcx_excel. + ENDTRY. + ls_types-seoclass = lo_addit->get_relative_name( ). + READ TABLE wt_objects INTO ls_types WITH TABLE KEY seoclass = ls_types-seoclass. + if sy-subrc ne 0. + do. + free lo_addit_superclass. + lo_addit_superclass = lo_addit->get_super_class_type( ). + if lo_addit_superclass is initial. + sy-subrc = '4'. + exit. + endif. + lo_addit = lo_addit_superclass. + ls_types-seoclass = lo_addit->get_relative_name( ). + read table wt_objects into ls_types with table key seoclass = ls_types-seoclass. + if sy-subrc eq 0. + exit. + endif. + enddo. + endif. + if sy-subrc = 0. + CREATE OBJECT lo_if type (ls_types-clsname). + try. + lo_if->create_fieldcatalog( + exporting + is_option = ws_option + io_object = io_object + it_table = it_table + importing + es_layout = ws_layout + et_fieldcatalog = wt_fieldcatalog + eo_table = wo_table + et_colors = wt_colors + et_filter = wt_filter + ). + endtry. +* data lines of highest level. + if ws_layout-max_subtotal_level > 0. add 1 to ws_layout-max_subtotal_level. endif. + else. + RAISE EXCEPTION type zcx_excel. + endif. + else. + refresh wt_fieldcatalog. + get reference of it_table into wo_table. + endif. +endmethod. + + + + + + + method GET_COLOR_STYLE. + DATA: ls_colors TYPE zexcel_s_converter_col, + ls_color_styles TYPE ts_color_styles, + lo_style TYPE REF TO zcl_excel_style. + + r_style = i_style. " Default we change nothing + + IF wt_colors IS NOT INITIAL. +* Full line has color + READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row + columnname = space. + IF sy-subrc = 0. + READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style + fontcolor = ls_colors-fontcolor + fillcolor = ls_colors-fillcolor. + IF sy-subrc = 0. + r_style = ls_color_styles-style_new->get_guid( ). + ELSE. + lo_style = create_color_style( i_style = i_style + is_colors = ls_colors ) . + r_style = lo_style->get_guid( ) . + ls_color_styles-guid_old = i_style. + ls_color_styles-fontcolor = ls_colors-fontcolor. + ls_color_styles-fillcolor = ls_colors-fillcolor. + ls_color_styles-style_new = lo_style. + INSERT ls_color_styles INTO TABLE wt_color_styles. + ENDIF. + ELSE. +* Only field has color + READ TABLE wt_colors INTO ls_colors WITH KEY rownumber = i_row + columnname = i_fieldname. + IF sy-subrc = 0. + READ TABLE wt_color_styles INTO ls_color_styles WITH KEY guid_old = i_style + fontcolor = ls_colors-fontcolor + fillcolor = ls_colors-fillcolor. + IF sy-subrc = 0. + r_style = ls_color_styles-style_new->get_guid( ). + ELSE. + lo_style = create_color_style( i_style = i_style + is_colors = ls_colors ) . + ls_color_styles-guid_old = i_style. + ls_color_styles-fontcolor = ls_colors-fontcolor. + ls_color_styles-fillcolor = ls_colors-fillcolor. + ls_color_styles-style_new = lo_style. + INSERT ls_color_styles INTO TABLE wt_color_styles. + r_style = ls_color_styles-style_new->get_guid( ). + ENDIF. + ELSE. + r_style = i_style. + ENDIF. + ENDIF. + ELSE. + r_style = i_style. + ENDIF. + + endmethod. + + + + + + method GET_FILE. + data: lo_excel_writer type ref to zif_excel_writer, + lo_excel type ref to zcl_excel. + + data: ls_seoclass type seoclass. + + + if wo_excel is bound. + create object lo_excel_writer type zcl_excel_writer_2007. + e_file = lo_excel_writer->write_file( wo_excel ). + + select single * into ls_seoclass + from seoclass + where clsname = 'CL_BCS_CONVERT'. + + if sy-subrc = 0. + call method (ls_seoclass-clsname)=>xstring_to_solix + exporting + iv_xstring = e_file + receiving + et_solix = et_file. + e_bytecount = xstrlen( e_file ). + else. + " Convert to binary + call function 'SCMS_XSTRING_TO_BINARY' + exporting + buffer = e_file + importing + output_length = e_bytecount + tables + binary_tab = et_file. + endif. + endif. + + endmethod. + + + + + method GET_FUNCTION_NUMBER. +*Number Function +*1 AVERAGE +*2 COUNT +*3 COUNTA +*4 MAX +*5 MIN +*6 PRODUCT +*7 STDEV +*8 STDEVP +*9 SUM +*10 VAR +*11 VARP + + case i_totals_function. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_SUM. " Total + r_function_number = 9. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MIN. " Minimum + r_function_number = 5. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_MAX. " Maximum + r_function_number = 4. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_AVERAGE. " Mean Value + r_function_number = 1. + when ZCL_EXCEL_TABLE=>TOTALS_FUNCTION_count. " Count + r_function_number = 2. + when others. + clear r_function_number. + endcase. + endmethod. + + + + method GET_OPTION. + + rs_option = ws_option. + + endmethod. + + + + + + + + method GET_STYLE. + DATA: ls_styles TYPE ts_styles, + lo_style TYPE REF TO zcl_excel_style. + + CLEAR r_style. + + READ TABLE wt_styles INTO ls_styles WITH TABLE KEY type = i_type + alignment = i_alignment + inttype = i_inttype + decimals = i_decimals. + IF sy-subrc = 0. + r_style = ls_styles-guid. + ELSE. + CASE i_type. + WHEN c_type_hdr. " Header + lo_style = create_style_hdr( i_alignment = i_alignment ). + WHEN c_type_str. "Stripped + lo_style = create_style_stripped( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_nor. "Normal + lo_style = create_style_normal( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_sub. "Subtotals + lo_style = create_style_subtotal( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + WHEN c_type_tot. "Totals + lo_style = create_style_total( i_alignment = i_alignment + i_inttype = i_inttype + i_decimals = i_decimals ). + ENDCASE. + IF lo_style IS NOT INITIAL. + r_style = lo_style->get_guid( ). + ls_styles-type = i_type. + ls_styles-alignment = i_alignment. + ls_styles-inttype = i_inttype. + ls_styles-decimals = i_decimals. + ls_styles-guid = r_style. + ls_styles-style = lo_style. + INSERT ls_styles INTO TABLE wt_styles. + ENDIF. + ENDIF. + endmethod. + + + method INIT_OPTION. + + ws_option-filter = abap_true. + ws_option-hidenc = abap_true. + ws_option-subtot = abap_true. + + endmethod. + + + + + + + method LOOP_NORMAL. + DATA: lo_data TYPE REF TO data, + l_row_header TYPE zexcel_cell_row VALUE 2, + l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + l_row_int_start TYPE zexcel_cell_row, + l_row_int_end TYPE zexcel_cell_row, + l_row_int TYPE zexcel_cell_row, + l_col_int TYPE zexcel_cell_column, + l_col_alpha TYPE zexcel_cell_column_alpha, + l_col_alpha_start TYPE zexcel_cell_column_alpha, + l_cell_value TYPE zexcel_cell_value, + l_s_color TYPE abap_bool, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + l_formula TYPE zexcel_cell_formula, + l_style TYPE zexcel_cell_style, + l_cells TYPE i, + l_count TYPE i, + l_table_row TYPE i. + + FIELD-SYMBOLS: <fs_stab> TYPE ANY, + <fs_tab> TYPE STANDARD TABLE, + <fs_sfcat> TYPE zexcel_s_converter_fcat, + <fs_fldval> TYPE ANY, + <fs_cell_value> TYPE zexcel_cell_value. + + ASSIGN wo_data->* TO <fs_tab> . + + DESCRIBE TABLE wt_fieldcatalog LINES l_cells. + DESCRIBE TABLE <fs_tab> LINES l_count. + l_cells = l_cells * l_count. + +* It is better to loop column by column + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + l_row_int = i_row_int. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + +* Freeze panes + IF <fs_sfcat>-fix_column = abap_true. + ADD 1 TO r_freeze_col. + ENDIF. + l_s_color = abap_true. + + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + +* Only if the Header is required create it. + IF ws_option-hidehd IS INITIAL. + " First of all write column header + l_cell_value = <fs_sfcat>-scrtext_m. + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_style = <fs_sfcat>-style_hdr ). + ADD 1 TO l_row_int. + ENDIF. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_table_row = sy-tabix. +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. +* Now let's write the cell values + IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_stripped ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + CLEAR l_s_color. + ELSE. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_normal ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + l_s_color = abap_true. + ENDIF. + READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row + columnname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + wo_worksheet->get_cell( EXPORTING + ip_column = l_col_alpha + ip_row = l_row_int + IMPORTING + ep_value = l_cell_value ). + wo_autofilter->set_value( i_column = l_col_int + i_value = l_cell_value ). + ENDIF. + ADD 1 TO l_row_int. + ENDLOOP. +* Now let's check for optimized + IF <fs_sfcat>-is_optimized = abap_true . + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + ENDIF. +* Now let's check for visible + IF <fs_sfcat>-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + ENDIF. +* Now let's check for total versus subtotal. + IF <fs_sfcat>-totals_function IS NOT INITIAL. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_total( i_row_int = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_total ). + ENDIF. + ENDLOOP. + endmethod. + + + + + + + method LOOP_SUBTOTAL. + + DATA: lo_data TYPE REF TO data, + l_row_header TYPE zexcel_cell_row VALUE 2, + l_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + l_row_int_start TYPE zexcel_cell_row, + l_row_int_end TYPE zexcel_cell_row, + l_row_int TYPE zexcel_cell_row, + l_col_int TYPE zexcel_cell_column, + l_col_alpha TYPE zexcel_cell_column_alpha, + l_col_alpha_start TYPE zexcel_cell_column_alpha, + l_cell_value TYPE zexcel_cell_value, + l_s_color TYPE abap_bool, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + l_formula TYPE zexcel_cell_formula, + l_style TYPE zexcel_cell_style, + l_subtotalled TYPE flag, + l_text TYPE string, + ls_sort_values TYPE ts_sort_values, + ls_subtotal_rows TYPE ts_subtotal_rows, + l_sort_level TYPE int4, + l_hidden TYPE int4, + l_line TYPE i, + l_guid TYPE guid_22, + l_tabix TYPE sy-tabix, + l_cells TYPE i, + l_count TYPE i, + l_table_row TYPE i, + lt_fcat TYPE zexcel_t_converter_fcat. + + FIELD-SYMBOLS: <fs_stab> TYPE ANY, + <fs_tab> TYPE STANDARD TABLE, + <fs_sfcat> TYPE zexcel_s_converter_fcat, + <fs_fldval> TYPE ANY, + <fs_sortval> TYPE ANY, + <fs_sortv> TYPE ts_sort_values, + <fs_cell_value> TYPE zexcel_cell_value. + + ASSIGN wo_data->* TO <fs_tab> . + + REFRESH: wt_sort_values, + wt_subtotal_rows. + + DESCRIBE TABLE wt_fieldcatalog LINES l_cells. + DESCRIBE TABLE <fs_tab> LINES l_count. + l_cells = l_cells * l_count. + + READ TABLE <fs_tab> ASSIGNING <fs_stab> INDEX 1. + IF sy-subrc = 0. + l_row_int = i_row_int + 1. + lt_fcat = wt_fieldcatalog. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. + ls_sort_values-fieldname = <fs_sfcat>-columnname. + ls_sort_values-row_int = l_row_int. + ls_sort_values-sort_level = <fs_sfcat>-sort_level. + ls_sort_values-is_collapsed = <fs_sfcat>-is_collapsed. + CREATE DATA ls_sort_values-value LIKE <fs_fldval>. + ASSIGN ls_sort_values-value->* TO <fs_sortval>. + <fs_sortval> = <fs_fldval>. + INSERT ls_sort_values INTO TABLE wt_sort_values. + ENDLOOP. + ENDIF. + l_row_int = i_row_int. +* Let's check if we need to hide a sort level. + DESCRIBE TABLE wt_sort_values LINES l_line. + IF l_line <= 1. + CLEAR l_hidden. + ELSE. + LOOP AT wt_sort_values INTO ls_sort_values WHERE is_collapsed = abap_false. + IF l_hidden < ls_sort_values-sort_level. + l_hidden = ls_sort_values-sort_level. + ENDIF. + ENDLOOP. + ENDIF. + ADD 1 TO l_hidden. " As this is the first level we show. +* First loop without formular only addtional rows with subtotal text. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + ADD 1 TO l_row_int. " 1 is for header row. + l_row_int_start = l_row_int. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. + IF sy-subrc = 0. + READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + ASSIGN <fs_sortv>-value->* TO <fs_sortval>. + IF <fs_sortval> <> <fs_fldval> OR <fs_sortv>-new = abap_true. +* First let's remmember the subtotal values as it has to appear later. + ls_subtotal_rows-row_int = l_row_int. + ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. + ls_subtotal_rows-columnname = <fs_sfcat>-columnname. + INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. +* Now let's write the subtotal line + l_cell_value = create_text_subtotal( i_value = <fs_sortval> + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = <fs_sfcat>-sort_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. +* Now let's change the key + ADD 1 TO l_row_int. + <fs_sortval> = <fs_fldval>. + <fs_sortv>-new = abap_false. + l_line = <fs_sortv>-sort_level. + LOOP AT wt_sort_values ASSIGNING <fs_sortv> WHERE sort_level >= l_line. + <fs_sortv>-row_int = l_row_int. + ENDLOOP. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + ENDLOOP. + ADD 1 TO l_row_int. + l_row_int_start = l_row_int. + SORT lt_fcat BY sort_level DESCENDING. + LOOP AT lt_fcat ASSIGNING <fs_sfcat> WHERE is_subtotalled = abap_true. + l_col_int = i_col_int + <fs_sfcat>-position - 1. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + READ TABLE wt_sort_values ASSIGNING <fs_sortv> WITH TABLE KEY fieldname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + ASSIGN <fs_sortv>-value->* TO <fs_sortval>. + ls_subtotal_rows-row_int = l_row_int. + ls_subtotal_rows-row_int_start = <fs_sortv>-row_int. + ls_subtotal_rows-columnname = <fs_sfcat>-columnname. + INSERT ls_subtotal_rows INTO TABLE wt_subtotal_rows. +* First let's write the value as it has to appear. + l_cell_value = create_text_subtotal( i_value = <fs_sortval> + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + + l_sort_level = <fs_sfcat>-sort_level. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. + ADD 1 TO l_row_int. + ENDIF. + ENDLOOP. +* Let's write the Grand total + l_sort_level = 0. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = l_sort_level ) . +* lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . Not on grand total + + l_text = create_text_subtotal( i_value = 'Grand'(002) + i_totals_function = <fs_sfcat>-totals_function ). + + l_col_alpha_start = zcl_excel_common=>convert_column2alpha( i_col_int ). + wo_worksheet->set_cell( ip_column = l_col_alpha_start + ip_row = l_row_int + ip_value = l_text + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_subtotal ). + +* It is better to loop column by column second time around +* Second loop with formular and data. + LOOP AT wt_fieldcatalog ASSIGNING <fs_sfcat>. + l_row_int = i_row_int. + l_col_int = i_col_int + <fs_sfcat>-position - 1. +* Freeze panes + IF <fs_sfcat>-fix_column = abap_true. + ADD 1 TO r_freeze_col. + ENDIF. + l_s_color = abap_true. + l_col_alpha = zcl_excel_common=>convert_column2alpha( l_col_int ). + " First of all write column header + l_cell_value = <fs_sfcat>-scrtext_m. + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = l_cell_value + ip_abap_type = cl_abap_typedescr=>typekind_string + ip_style = <fs_sfcat>-style_hdr ). + ADD 1 TO l_row_int. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_table_row = sy-tabix. +* Now the cell values + ASSIGN COMPONENT <fs_sfcat>-columnname OF STRUCTURE <fs_stab> TO <fs_fldval>. +* Let's check for subtotal lines + DO. + READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + DO. + READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + l_row_int_start = ls_subtotal_rows-row_int_start. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). + IF <fs_sfcat>-sort_level > l_hidden. + lo_row_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + ENDIF. + ADD 1 TO l_row_int. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + ADD 1 TO l_row_int. + ENDIF. + ELSE. + EXIT. + ENDIF. + ENDDO. +* Let's set the row dimension values + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_outline_level( ip_outline_level = ws_layout-max_subtotal_level ) . + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim->set_visible( ip_visible = abap_false ) . + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ) . + ENDIF. +* Now let's write the cell values + IF ws_layout-is_stripped = abap_true AND l_s_color = abap_true. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_stripped ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + CLEAR l_s_color. + ELSE. + l_style = get_color_style( i_row = l_table_row + i_fieldname = <fs_sfcat>-columnname + i_style = <fs_sfcat>-style_normal ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_value = <fs_fldval> + ip_style = l_style ). + l_s_color = abap_true. + ENDIF. + READ TABLE wt_filter TRANSPORTING NO FIELDS WITH TABLE KEY rownumber = l_table_row + columnname = <fs_sfcat>-columnname. + IF sy-subrc = 0. + wo_worksheet->get_cell( EXPORTING + ip_column = l_col_alpha + ip_row = l_row_int + IMPORTING + ep_value = l_cell_value ). + wo_autofilter->set_value( i_column = l_col_int + i_value = l_cell_value ). + ENDIF. + ADD 1 TO l_row_int. + ENDLOOP. +* Let's check for subtotal lines + DO. + READ TABLE wt_subtotal_rows TRANSPORTING NO FIELDS WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + DO. + READ TABLE wt_subtotal_rows INTO ls_subtotal_rows WITH TABLE KEY row_int = l_row_int. + IF sy-subrc = 0. + l_row_int_start = ls_subtotal_rows-row_int_start. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + IF <fs_sfcat>-is_collapsed = abap_true. + lo_row_dim = wo_worksheet->get_row_dimension( ip_row = l_row_int ). + lo_row_dim->set_collapsed( ip_collapsed = <fs_sfcat>-is_collapsed ). + ENDIF. + ADD 1 TO l_row_int. + ELSE. + EXIT. + ENDIF. + ENDDO. + ELSE. + ADD 1 TO l_row_int. + ENDIF. + ELSE. + EXIT. + ENDIF. + ENDDO. +* Now let's check for Grand total + IF <fs_sfcat>-is_subtotalled = abap_false AND + <fs_sfcat>-totals_function IS NOT INITIAL. + l_row_int_start = i_row_int + 1. + l_row_int_end = l_row_int - 1. + + l_formula = create_formular_subtotal( i_row_int_start = l_row_int_start + i_row_int_end = l_row_int_end + i_column = l_col_alpha + i_totals_function = <fs_sfcat>-totals_function ). + wo_worksheet->set_cell( ip_column = l_col_alpha + ip_row = l_row_int + ip_formula = l_formula + ip_style = <fs_sfcat>-style_subtotal ). + ENDIF. +* Now let's check for optimized + IF <fs_sfcat>-is_optimized = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_auto_size( ip_auto_size = abap_true ) . + ENDIF. +* Now let's check for visible + IF <fs_sfcat>-is_hidden = abap_true. + lo_col_dim = wo_worksheet->get_column_dimension( ip_column = l_col_alpha ). + lo_col_dim->set_visible( ip_visible = abap_false ) . + ENDIF. + ENDLOOP. + + endmethod. + + + method OPEN_FILE. + data: l_bytecount type i, + lt_file type solix_tab, + l_dir type string, + l_sep type c. + + field-symbols: <fs_data> type any table. + + assign wo_data->* to <fs_data>. + +* catch zcx_excel . +*endtry. + if wo_excel is bound. + get_file( importing e_bytecount = l_bytecount + et_file = lt_file ) . + + l_dir = create_path( ) . + + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_dir + filetype = 'BIN' + changing data_tab = lt_file ). + cl_gui_frontend_services=>execute( + exporting + document = l_dir +* application = +* parameter = +* default_directory = +* maximized = +* minimized = +* synchronous = +* operation = 'OPEN' + exceptions + cntl_error = 1 + error_no_gui = 2 + bad_parameter = 3 + file_not_found = 4 + path_not_found = 5 + file_extension_unknown = 6 + error_execute_failed = 7 + synchronous_failed = 8 + not_supported_by_gui = 9 + ). + if sy-subrc <> 0. + message id sy-msgid type sy-msgty number sy-msgno + with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + endif. + + endif. + + + endmethod. + + + method SET_AUTOFILTER_AREA. + DATA: ls_area TYPE zexcel_s_autofilter_area, + l_lines TYPE i, + lt_values TYPE zexcel_t_autofilter_values, + ls_values TYPE zexcel_s_autofilter_values. + +* Let's check for filter. + IF wo_autofilter IS BOUND. + ls_area-row_start = 1. + lt_values = wo_autofilter->get_values( ) . + SORT lt_values BY column ASCENDING. + DESCRIBE TABLE lt_values LINES l_lines. + READ TABLE lt_values INTO ls_values INDEX 1. + IF sy-subrc = 0. + ls_area-col_start = ls_values-column. + ENDIF. + READ TABLE lt_values INTO ls_values INDEX l_lines. + IF sy-subrc = 0. + ls_area-col_end = ls_values-column. + ENDIF. + wo_autofilter->set_filter_area( is_area = ls_area ) . + ENDIF. + + endmethod. + + + + + + method SET_CELL_FORMAT. + DATA: l_format TYPE zexcel_number_format. + + CLEAR r_format. + CASE i_inttype. + WHEN cl_abap_typedescr=>typekind_date. + r_format = wo_worksheet->get_default_excel_date_format( ). + WHEN cl_abap_typedescr=>typekind_time. + r_format = wo_worksheet->get_default_excel_time_format( ). + WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. + IF i_decimals > 0 . + l_format = '#,##0.'. + DO i_decimals TIMES. + CONCATENATE l_format '0' INTO l_format. + ENDDO. + r_format = l_format. + ENDIF. + WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. + r_format = '#,##0'. + ENDCASE. + + endmethod. + + + method SET_FIELDCATALOG. + + DATA: lr_data TYPE REF TO data, + lo_structdescr TYPE REF TO cl_abap_structdescr, + lt_dfies TYPE ddfields, + ls_dfies TYPE dfies, + ls_fieldcatalog TYPE zexcel_s_fieldcatalog. + DATA: ls_fcat TYPE zexcel_s_converter_fcat. + + FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. + + ASSIGN wo_data->* TO <fs_tab> . + + CREATE DATA lr_data LIKE LINE OF <fs_tab>. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + + LOOP AT lt_dfies INTO ls_dfies. + MOVE-CORRESPONDING ls_dfies TO ls_fcat. + ls_fcat-columnname = ls_dfies-fieldname. + INSERT ls_fcat INTO TABLE wt_fieldcatalog. + ENDLOOP. + + clean_fieldcatalog( ). + + endmethod. + + + + method SET_OPTION. + + IF ws_indx-begdt IS INITIAL. + ws_indx-begdt = sy-datum. + ENDIF. + + ws_indx-aedat = sy-datum. + ws_indx-usera = sy-uname. + ws_indx-pgmid = sy-cprog. + + EXPORT p1 = is_option TO DATABASE indx(xl) FROM ws_indx ID ws_indx-srtfd. + + IF sy-subrc = 0. + ws_option = is_option. + ENDIF. + + endmethod. + + + + method WRITE_FILE. + data: l_bytecount type i, + lt_file type solix_tab, + l_dir type string. + + field-symbols: <fs_data> type any table. + + assign wo_data->* to <fs_data>. + +* catch zcx_excel . +*endtry. + if wo_excel is bound. + get_file( importing e_bytecount = l_bytecount + et_file = lt_file ) . + if i_path is initial. + l_dir = create_path( ) . + else. + l_dir = i_path. + endif. + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_dir + filetype = 'BIN' + changing data_tab = lt_file ). + endif. + endmethod. + + + + + *"* 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 ts_col_converter, + col TYPE lvc_col, + int TYPE lvc_int, + inv TYPE lvc_inv, + fontcolor TYPE zexcel_style_color_argb, + fillcolor TYPE zexcel_style_color_argb, + END OF ts_col_converter, + + tt_col_converter TYPE HASHED TABLE OF ts_col_converter WITH UNIQUE KEY col int inv. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + ABAP + KKBLO + + + + + + + + + + method APPLY_SORT. + DATA: lt_otab TYPE abap_sortorder_tab, + ls_otab TYPE abap_sortorder. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE, + <fs_sort> TYPE lvc_s_sort. + + CREATE DATA eo_table LIKE it_table. + ASSIGN eo_table->* TO <fs_table>. + + <fs_table> = it_table. + + SORT wt_sort BY spos. + LOOP AT wt_sort ASSIGNING <fs_sort>. + IF <fs_sort>-up = abap_true. + ls_otab-name = <fs_sort>-fieldname. + ls_otab-descending = abap_false. +* ls_otab-astext = abap_true. " not only text fields + INSERT ls_otab INTO TABLE lt_otab. + ENDIF. + IF <fs_sort>-down = abap_true. + ls_otab-name = <fs_sort>-fieldname. + ls_otab-descending = abap_true. +* ls_otab-astext = abap_true. " not only text fields + INSERT ls_otab INTO TABLE lt_otab. + ENDIF. + ENDLOOP. + IF lt_otab IS NOT INITIAL. + SORT <fs_table> BY (lt_otab). + ENDIF. + + endmethod. + + + method CLASS_CONSTRUCTOR. +* let's fill the color conversion routines. + DATA: ls_color TYPE ts_col_converter. +* 0 all combination the same + ls_color-col = 0. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 0. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 0. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 0. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* Blue + ls_color-col = 1. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFB0E4FC'. " 176 228 252 blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 1. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFB0E4FC'. " 176 228 252 blue + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 1. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FF5FCBFE'. " 095 203 254 Int blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 1. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF5FCBFE'. " 095 203 254 + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 + INSERT ls_color INTO TABLE wt_colors. + +* Gray + ls_color-col = 2. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. + ls_color-fillcolor = 'FFE5EAF0'. " 229 234 240 gray + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 2. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFE5EAF0'. " 229 234 240 gray + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 2. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFD8E8F4'. " 216 234 244 int gray + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 2. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FFD8E8F4'. " 216 234 244 int gray + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +*Yellow + ls_color-col = 3. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFEFEB8'. " 254 254 184 yellow + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 3. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFFEFEB8'. " 254 254 184 yellow + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 3. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFF9ED5D'. " 249 237 093 int yellow + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 3. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FFF9ED5D'. " 249 237 093 int yellow + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* light blue + ls_color-col = 4. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFCEE7FB'. " 206 231 251 light blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 4. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFCEE7FB'. " 206 231 251 light blue + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 4. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FF9ACCEF'. " 154 204 239 int light blue + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 4. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF9ACCEF'. " 154 204 239 int light blue + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* Green + ls_color-col = 5. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFCEF8AE'. " 206 248 174 Green + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 5. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFCEF8AE'. " 206 248 174 Green + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 5. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FF7AC769'. " 122 199 105 int Green + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 5. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FF7AC769'. " 122 199 105 int Green + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + +* Red + ls_color-col = 6. + ls_color-int = 0. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFDBBBC'. " 253 187 188 Red + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 6. + ls_color-int = 0. + ls_color-inv = 1. + ls_color-fontcolor = 'FFFDBBBC'. " 253 187 188 Red + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 6. + ls_color-int = 1. + ls_color-inv = 0. + ls_color-fontcolor = 'FF000000'. " 000 000 000 Black + ls_color-fillcolor = 'FFFB6B6B'. " 251 107 107 int Red + INSERT ls_color INTO TABLE wt_colors. + + ls_color-col = 6. + ls_color-int = 1. + ls_color-inv = 1. + ls_color-fontcolor = 'FFFB6B6B'. " 251 107 107 int Red + ls_color-fillcolor = 'FFFFFFFF'. " 255 255 255 White + INSERT ls_color INTO TABLE wt_colors. + + endmethod. + + + + + method GET_COLOR. + DATA: ls_con_col TYPE zexcel_s_converter_col, + ls_color TYPE ts_col_converter, + l_line TYPE i, + l_color(4) TYPE c. + FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE, + <fs_stab> TYPE ANY, + <fs> TYPE ANY, + <fs_tcol> TYPE lvc_t_scol, + <fs_scol> TYPE lvc_s_scol, + <ft_slis> type standard table, + <fs_slis> type any. + +* Loop trough the table to set the color properties of each line. The color properties field is +* Char 4 and the characters is set as follows: +* Char 1 = C = This is a color property +* Char 2 = 6 = Color code (1 - 7) +* Char 3 = Intensified on/of = 1 = on +* Char 4 = Inverse display = 0 = of + + ASSIGN io_table->* TO <fs_tab>. + + IF ws_layo-info_fname IS NOT INITIAL OR + ws_layo-ctab_fname IS NOT INITIAL. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_line = sy-tabix. + IF ws_layo-info_fname IS NOT INITIAL. + ASSIGN COMPONENT ws_layo-info_fname OF STRUCTURE <fs_stab> TO <fs>. + IF sy-subrc = 0. + IF <fs> IS NOT INITIAL. + l_color = <fs>. + IF l_color(1) = 'C'. + READ TABLE wt_colors INTO ls_color WITH TABLE KEY col = l_color+1(1) + int = l_color+2(1) + inv = l_color+3(1). + IF sy-subrc = 0. + ls_con_col-rownumber = l_line. + ls_con_col-columnname = space. + ls_con_col-fontcolor = ls_color-fontcolor. + ls_con_col-fillcolor = ls_color-fillcolor. + INSERT ls_con_col INTO TABLE et_colors. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + if ws_layo-ctab_fname is not initial. + + assign component ws_layo-ctab_fname of structure <fs_stab> to <ft_slis>. + if sy-subrc = 0. + loop at <ft_slis> assigning <fs_slis>. + assign component 'COLOR' of structure <fs_slis> to <fs>. + if sy-subrc = 0. + if <fs> is not initial. + field-symbols: <col> type any, + <int> type any, + <inv> type any, + <fname> type any, + <nokeycol> type any. + assign component 'COL' of structure <fs> to <col>. + assign component 'INT' of structure <fs> to <int>. + assign component 'INV' of structure <fs> to <inv>. + read table wt_colors into ls_color with table key col = <col> + int = <int> + inv = <inv>. + if sy-subrc = 0. + ls_con_col-rownumber = l_line. + assign component 'FNAME' of structure <fs_slis> to <fname>. + if sy-subrc ne 0. + assign component 'FIELDNAME' of structure <fs_slis> to <fname>. + if sy-subrc eq 0. + ls_con_col-columnname = <fname>. + endif. + else. + ls_con_col-columnname = <fname>. + endif. + + ls_con_col-fontcolor = ls_color-fontcolor. + ls_con_col-fillcolor = ls_color-fillcolor. + assign component 'NOKEYCOL' of structure <fs_slis> to <nokeycol>. + if sy-subrc eq 0. + ls_con_col-nokeycol = <nokeycol>. + endif. + insert ls_con_col into table et_colors. + endif. + endif. + endif. + endloop. + endif. + endif. + ENDLOOP. + ENDIF. + endmethod. + + + + + METHOD get_filter. + DATA: ls_filt TYPE lvc_s_filt, + l_line TYPE i, + ls_filter TYPE zexcel_s_converter_fil. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + lt_components_tab TYPE cl_abap_structdescr=>component_table, + ls_components TYPE abap_componentdescr, + lo_table TYPE REF TO cl_abap_tabledescr, + lo_struc TYPE REF TO cl_abap_structdescr, + lo_trange TYPE REF TO data, + lo_srange TYPE REF TO data, + lo_ltabdata TYPE REF TO data. + + FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE, + <fs_ltab> TYPE STANDARD TABLE, + <fs_stab> TYPE any, + <fs> TYPE any, + <fs1> TYPE any, + <fs_srange> TYPE any, + <fs_trange> TYPE STANDARD TABLE. + + IF ws_option-filter = abap_false. + REFRESH et_filter. + RETURN. + ENDIF. + + ASSIGN xo_table->* TO <fs_tab>. + + CREATE DATA lo_ltabdata LIKE <fs_tab>. + ASSIGN lo_ltabdata->* TO <fs_ltab>. + + LOOP AT wt_filt INTO ls_filt. + LOOP AT <fs_tab> ASSIGNING <fs_stab>. + l_line = sy-tabix. + ASSIGN COMPONENT ls_filt-fieldname OF STRUCTURE <fs_stab> TO <fs>. + IF sy-subrc = 0. + IF l_line = 1. + REFRESH lt_components_tab. + ls_components-name = 'SIGN'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ls_filt-sign ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ls_components-name = 'OPTION'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ls_filt-option ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ls_components-name = 'LOW'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + ls_components-name = 'HIGH'. + lo_addit ?= cl_abap_typedescr=>describe_by_data( <fs> ). + ls_components-type = lo_addit . + INSERT ls_components INTO TABLE lt_components_tab. + "create new line type + TRY. + lo_struc = cl_abap_structdescr=>create( p_components = lt_components_tab + p_strict = abap_false ). + CATCH cx_sy_struct_creation. + CONTINUE. + ENDTRY. + lo_table = cl_abap_tabledescr=>create( lo_struc ). + + CREATE DATA lo_trange TYPE HANDLE lo_table. + CREATE DATA lo_srange TYPE HANDLE lo_struc. + + ASSIGN lo_trange->* TO <fs_trange>. + ASSIGN lo_srange->* TO <fs_srange>. + ENDIF. + REFRESH <fs_trange>. + ASSIGN COMPONENT 'SIGN' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-sign. + ASSIGN COMPONENT 'OPTION' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-option. + ASSIGN COMPONENT 'LOW' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-low. + ASSIGN COMPONENT 'HIGH' OF STRUCTURE <fs_srange> TO <fs1>. + <fs1> = ls_filt-high. + INSERT <fs_srange> INTO TABLE <fs_trange>. + IF <fs> IN <fs_trange>. + IF ws_option-filter = abap_true. + ls_filter-rownumber = l_line. + ls_filter-columnname = ls_filt-fieldname. + INSERT ls_filter INTO TABLE et_filter. + ELSE. + INSERT <fs_stab> INTO TABLE <fs_ltab>. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + IF ws_option-filter = abap_undefined. + <fs_tab> = <fs_ltab>. + REFRESH <fs_ltab>. + ENDIF. + ENDLOOP. + +ENDMETHOD. + + + + + method UPDATE_CATALOG. + DATA: ls_fieldcatalog TYPE zexcel_s_converter_fcat, + ls_ref TYPE salv_s_ddic_reference, + ls_fcat TYPE lvc_s_fcat, + ls_sort TYPE lvc_s_sort, + l_decimals TYPE lvc_decmls. + + FIELD-SYMBOLS: <fs_scat> TYPE zexcel_s_converter_fcat. + + IF ws_layo-zebra IS NOT INITIAL. + cs_layout-is_stripped = abap_true. + ENDIF. + IF ws_layo-no_keyfix IS INITIAL OR + ws_layo-no_keyfix = '0'. + cs_layout-is_fixed = abap_true. + ENDIF. + + LOOP AT wt_fcat INTO ls_fcat. + CLEAR: ls_fieldcatalog, + l_decimals. + CASE ws_option-hidenc. + WHEN abap_false. " We make hiden columns visible + CLEAR ls_fcat-no_out. + WHEN abap_true. +* We convert column and hide it. + WHEN abap_undefined. "We don't convert hiden columns + IF ls_fcat-no_out = abap_true. + ls_fcat-tech = abap_true. + ENDIF. + ENDCASE. + IF ls_fcat-tech = abap_false. + ls_fieldcatalog-tabname = ls_fcat-tabname. + ls_fieldcatalog-fieldname = ls_fcat-fieldname . + ls_fieldcatalog-columnname = ls_fcat-fieldname . + ls_fieldcatalog-position = ls_fcat-col_pos. + ls_fieldcatalog-col_id = ls_fcat-col_id. + ls_fieldcatalog-convexit = ls_fcat-convexit. + ls_fieldcatalog-inttype = ls_fcat-inttype. + ls_fieldcatalog-scrtext_s = ls_fcat-scrtext_s . + ls_fieldcatalog-scrtext_m = ls_fcat-scrtext_m . + ls_fieldcatalog-scrtext_l = ls_fcat-scrtext_l. + l_decimals = ls_fcat-decimals_o. + IF l_decimals IS NOT INITIAL. + ls_fieldcatalog-decimals = l_decimals. + ELSE. + ls_fieldcatalog-decimals = ls_fcat-decimals . + ENDIF. + CASE ws_option-subtot. + WHEN abap_false. " We ignore subtotals + CLEAR ls_fcat-do_sum. + WHEN abap_true. " We convert subtotals and detail + + WHEN abap_undefined. " We should only take subtotals and displayed detail +* for now abap_true + ENDCASE. + CASE ls_fcat-do_sum. + WHEN abap_true. + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_sum. + WHEN 'A'. + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_min. + WHEN 'B' . + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_max. + WHEN 'C' . + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_average. + WHEN OTHERS. + CLEAR ls_fieldcatalog-totals_function . + ENDCASE. + ls_fieldcatalog-fix_column = ls_fcat-fix_column. + IF ws_layo-cwidth_opt IS INITIAL. + IF ls_fcat-col_opt IS NOT INITIAL. + ls_fieldcatalog-is_optimized = abap_true. + ENDIF. + ELSE. + ls_fieldcatalog-is_optimized = abap_true. + ENDIF. + IF ls_fcat-no_out IS NOT INITIAL. + ls_fieldcatalog-is_hidden = abap_true. + ls_fieldcatalog-position = ls_fieldcatalog-col_id. " We hide based on orginal data structure + ENDIF. +* Alignment in each cell + CASE ls_fcat-just. + WHEN 'R'. + ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_right. + WHEN 'L'. + ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_left. + WHEN 'C'. + ls_fieldcatalog-alignment = zcl_excel_style_alignment=>c_horizontal_center. + WHEN OTHERS. + CLEAR ls_fieldcatalog-alignment. + ENDCASE. +* Check for subtotals. + READ TABLE wt_sort INTO ls_sort WITH KEY fieldname = ls_fcat-fieldname. + IF sy-subrc = 0 AND ws_option-subtot <> abap_false. + ls_fieldcatalog-sort_level = 0 . +* IF ls_fieldcatalog-totals_function IS INITIAL. " Not clear why not +* CLEAR ls_fieldcatalog-is_subtotalled. +* ELSE. + ls_fieldcatalog-is_subtotalled = ls_sort-subtot. +* ENDIF. + ls_fieldcatalog-is_collapsed = ls_sort-expa. + IF ls_fieldcatalog-is_subtotalled = abap_true. + ls_fieldcatalog-sort_level = ls_sort-spos. + ls_fieldcatalog-totals_function = zcl_excel_table=>totals_function_sum. " we need function for text + ENDIF. + ENDIF. + APPEND ls_fieldcatalog TO ct_fieldcatalog. + ENDIF. + ENDLOOP. + + SORT ct_fieldcatalog BY sort_level ASCENDING. + cs_layout-max_subtotal_level = 0. + LOOP AT ct_fieldcatalog ASSIGNING <fs_scat> WHERE sort_level > 0. + cs_layout-max_subtotal_level = cs_layout-max_subtotal_level + 1. + <fs_scat>-sort_level = cs_layout-max_subtotal_level. + ENDLOOP. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method ZIF_EXCEL_CONVERTER~CAN_CONVERT_OBJECT. + data: lo_alv type REF TO cl_gui_alv_grid. + + try. + lo_alv ?= io_object. + catch cx_sy_move_cast_error . + raise exception type zcx_excel. + endtry. + +endmethod. + + + METHOD zif_excel_converter~create_fieldcatalog. + DATA: lo_alv TYPE REF TO cl_gui_alv_grid. + + TRY. + zif_excel_converter~can_convert_object( io_object = io_object ). + ENDTRY. + + ws_option = is_option. + + lo_alv ?= io_object. + + CLEAR: es_layout, + et_fieldcatalog. + + IF lo_alv IS BOUND. + lo_alv->get_frontend_fieldcatalog( IMPORTING et_fieldcatalog = wt_fcat ). + lo_alv->get_frontend_layout( IMPORTING es_layout = ws_layo ). + lo_alv->get_sort_criteria( IMPORTING et_sort = wt_sort ) . + lo_alv->get_filter_criteria( IMPORTING et_filter = wt_filt ) . + + apply_sort( EXPORTING it_table = it_table + IMPORTING eo_table = eo_table ) . + + get_color( EXPORTING io_table = eo_table + IMPORTING et_colors = et_colors ) . + + get_filter( IMPORTING et_filter = et_filter + CHANGING xo_table = eo_table ) . + + update_catalog( CHANGING cs_layout = es_layout + ct_fieldcatalog = et_fieldcatalog ). + ENDIF. +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + method GET_TABLE. + DATA: lo_object TYPE REF TO object, + ls_seoclass TYPE seoclass, + l_method TYPE string. + + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'IF_SALV_BS_DATA_SOURCE'. + + IF sy-subrc = 0. + l_method = 'GET_TABLE_REF'. + lo_object ?= io_object. + CALL METHOD lo_object->(l_method) + RECEIVING + value = ro_data. + ELSE. + l_method = 'GET_REF_TO_TABLE'. + lo_object ?= io_object. + CALL METHOD lo_object->(l_method) + RECEIVING + value = ro_data. + ENDIF. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + METHOD ZIF_EXCEL_CONVERTER~CAN_CONVERT_OBJECT. + + DATA: lo_result TYPE REF TO cl_salv_ex_result_data_table. + + TRY. + lo_result ?= io_object. + CATCH cx_sy_move_cast_error . + RAISE EXCEPTION TYPE zcx_excel. + ENDTRY. + +ENDMETHOD. + + + METHOD zif_excel_converter~create_fieldcatalog. + DATA: lo_result TYPE REF TO cl_salv_ex_result_data_table, + lo_ex_cm TYPE REF TO cl_salv_ex_cm, + lo_data TYPE REF TO data. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + + TRY. + zif_excel_converter~can_convert_object( io_object = io_object ). + ENDTRY. + + ws_option = is_option. + + lo_result ?= io_object. + + CLEAR: es_layout, + et_fieldcatalog. + + IF lo_result IS BOUND. + lo_data = get_table( io_object = lo_result->r_model->r_data ). + IF lo_data IS BOUND. + ASSIGN lo_data->* TO <fs_table> . + + lo_ex_cm ?= lo_result->r_model->r_model. + ws_layo = lo_ex_cm->s_layo. +* T_DRDN Instance Attribute Public Type LVC_T_DROP + wt_fcat = lo_ex_cm->t_fcat. + wt_filt = lo_ex_cm->t_filt. +* T_HYPE Instance Attribute Public Type LVC_T_HYPE +* T_SELECTED_CELLS Instance Attribute Public Type LVC_T_CELL +* T_SELECTED_COLUMNS Instance Attribute Public Type LVC_T_COL + wt_sort = lo_ex_cm->t_sort. + + apply_sort( EXPORTING it_table = <fs_table> + IMPORTING eo_table = eo_table ) . + + get_color( EXPORTING io_table = eo_table + IMPORTING et_colors = et_colors ) . + + get_filter( IMPORTING et_filter = et_filter + CHANGING xo_table = eo_table ) . + + update_catalog( CHANGING cs_layout = es_layout + ct_fieldcatalog = et_fieldcatalog ). + else. +* We have a problem and should stop here. + ENDIF. + ENDIF. +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + METHOD ZIF_EXCEL_CONVERTER~CAN_CONVERT_OBJECT. + + DATA: lo_result TYPE REF TO cl_salv_wd_result_data_table. + + TRY. + lo_result ?= io_object. + CATCH cx_sy_move_cast_error . + RAISE EXCEPTION TYPE zcx_excel. + ENDTRY. + +ENDMETHOD. + + + METHOD zif_excel_converter~create_fieldcatalog. + DATA: lo_result TYPE REF TO cl_salv_wd_result_data_table, + lo_data TYPE REF TO data. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + + TRY. + zif_excel_converter~can_convert_object( io_object = io_object ). + ENDTRY. + + ws_option = is_option. + + lo_result ?= io_object. + + CLEAR: es_layout, + et_fieldcatalog. + + IF lo_result IS BOUND. + lo_data = get_table( io_object = lo_result->r_model->r_data ). + IF lo_data IS BOUND. + ASSIGN lo_data->* TO <fs_table> . + + wo_config ?= lo_result->r_model->r_model. + + IF wo_config IS BOUND. + wt_fields = wo_config->if_salv_wd_field_settings~get_fields( ) . + wt_columns = wo_config->if_salv_wd_column_settings~get_columns( ) . + ENDIF. + + create_wt_fcat( io_table = lo_data ). + create_wt_sort( ). + create_wt_filt( ). + + apply_sort( EXPORTING it_table = <fs_table> + IMPORTING eo_table = eo_table ) . + +* get_color( EXPORTING io_table = eo_table +* IMPORTING et_colors = et_colors ) . + + get_filter( IMPORTING et_filter = et_filter + CHANGING xo_table = eo_table ) . + + update_catalog( CHANGING cs_layout = es_layout + ct_fieldcatalog = et_fieldcatalog ). + ELSE. +* We have a problem and should stop here + ENDIF. + ENDIF. +ENDMETHOD. + + + + method CREATE_WT_FCAT. + DATA: lr_data TYPE REF TO data, + lo_structdescr TYPE REF TO cl_abap_structdescr, + lt_dfies TYPE ddfields, + ls_dfies TYPE dfies, + lv_sytabix TYPE sytabix. + + DATA: ls_fcat TYPE lvc_s_fcat. + + FIELD-SYMBOLS: <fs_tab> TYPE ANY TABLE. + + ASSIGN io_table->* TO <fs_tab> . + CREATE DATA lr_data LIKE LINE OF <fs_tab>. + + lo_structdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + lt_dfies = zcl_excel_common=>describe_structure( io_struct = lo_structdescr ). + + loop at lt_dfies into ls_dfies. + MOVE-CORRESPONDING ls_dfies TO ls_fcat. +* ls_fcat-columnname = ls_dfies-fieldname. + ls_fcat-col_pos = ls_dfies-position. + ls_fcat-key = ls_dfies-keyflag. + get_fields_info( CHANGING xs_fcat = ls_fcat ) . + + ls_fcat-col_opt = abap_true. + + get_columns_info( CHANGING xs_fcat = ls_fcat ) . + + INSERT ls_fcat INTO TABLE wt_fcat. + endloop. + + endmethod. + + + method CREATE_WT_FILT. +* No neeed for superclass. +* Only for WD + DATA: lt_otab TYPE abap_sortorder_tab, + ls_otab TYPE abap_sortorder. + DATA: lt_filters TYPE salv_wd_t_filter_rule_ref, + ls_filt TYPE lvc_s_filt. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref, + <fs_filter> TYPE salv_wd_s_filter_rule_ref. + + LOOP AT wt_fields ASSIGNING <fs_fields>. + REFRESH lt_filters. + lt_filters = <fs_fields>-r_field->if_salv_wd_filter~get_filter_rules( ) . + LOOP AT lt_filters ASSIGNING <fs_filter>. + ls_filt-fieldname = <fs_fields>-fieldname. + IF <fs_filter>-r_filter_rule->get_included( ) = abap_true. + ls_filt-sign = 'I'. + ELSE. + ls_filt-sign = 'E'. + ENDIF. + ls_filt-option = <fs_filter>-r_filter_rule->get_operator( ). + ls_filt-high = <fs_filter>-r_filter_rule->get_high_value( ) . + ls_filt-low = <fs_filter>-r_filter_rule->get_low_value( ) . + INSERT ls_filt INTO TABLE wt_filt. + ENDLOOP. + ENDLOOP. + + endmethod. + + + method CREATE_WT_SORT. + DATA: lo_sort TYPE REF TO cl_salv_wd_sort_rule, + l_sort_order TYPE salv_wd_constant, + ls_sort TYPE lvc_s_sort. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. + + LOOP AT wt_fields ASSIGNING <fs_fields>. + lo_sort = <fs_fields>-r_field->if_salv_wd_sort~get_sort_rule( ) . + IF lo_sort IS BOUND. + l_sort_order = lo_sort->get_sort_order( ). + IF l_sort_order <> if_salv_wd_c_sort=>sort_order. + CLEAR ls_sort. + ls_sort-spos = lo_sort->get_sort_position( ). + ls_sort-fieldname = <fs_fields>-fieldname. +* ls_sort-GROUP + ls_sort-subtot = lo_sort->get_group_aggregation( ). +* ls_sort-COMP +* ls_sort-EXPA +* ls_sort-SELTEXT +* ls_sort-OBLIGATORY +* ls_sort-LEVEL +* ls_sort-NO_OUT + IF l_sort_order = if_salv_wd_c_sort=>sort_order_ascending. + ls_sort-up = abap_true. + ELSE. + ls_sort-down = abap_true. + ENDIF. + INSERT ls_sort INTO TABLE wt_sort. + ENDIF. + ENDIF. + ENDLOOP. + + endmethod. + + + + method GET_COLUMNS_INFO. + DATA: l_numc2 TYPE salv_wd_constant. + + + FIELD-SYMBOLS: <fs_column> TYPE salv_wd_s_column_ref. + + READ TABLE wt_columns ASSIGNING <fs_column> WITH KEY id = xs_fcat-fieldname . + IF sy-subrc = 0. + xs_fcat-col_pos = <fs_column>-r_column->get_position( ) . + l_numc2 = <fs_column>-r_column->get_fixed_position( ). + IF l_numc2 = '02'. + xs_fcat-fix_column = abap_true . + ENDIF. + l_numc2 = <fs_column>-r_column->get_visible( ). + IF l_numc2 = '01'. + xs_fcat-no_out = abap_true . + ENDIF. + ENDIF. + + endmethod. + + + + method GET_FIELDS_INFO. + DATA: lo_aggr TYPE REF TO cl_salv_wd_aggr_rule, + l_aggrtype TYPE salv_wd_constant. + + FIELD-SYMBOLS: <fs_fields> TYPE salv_wd_s_field_ref. + + READ TABLE wt_fields ASSIGNING <fs_fields> WITH KEY fieldname = xs_fcat-fieldname. + IF sy-subrc = 0. + lo_aggr = <fs_fields>-r_field->if_salv_wd_aggr~get_aggr_rule( ) . + IF lo_aggr IS BOUND. + l_aggrtype = lo_aggr->get_aggregation_type( ) . + CASE l_aggrtype. + WHEN if_salv_wd_c_aggregation=>aggrtype_total. + xs_fcat-do_sum = abap_true. + WHEN if_salv_wd_c_aggregation=>aggrtype_minimum. + xs_fcat-do_sum = 'A'. + WHEN if_salv_wd_c_aggregation=>aggrtype_maximum . + xs_fcat-do_sum = 'B'. + WHEN if_salv_wd_c_aggregation=>aggrtype_average . + xs_fcat-do_sum = 'C'. + WHEN OTHERS. + CLEAR xs_fcat-do_sum . + ENDCASE. + ENDIF. + ENDIF. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + METHOD zif_excel_converter~can_convert_object. + + DATA: lo_salv TYPE REF TO cl_salv_table. + + TRY. + lo_salv ?= io_object. + CATCH cx_sy_move_cast_error . + RAISE EXCEPTION TYPE zcx_excel. + ENDTRY. + +ENDMETHOD. + + + METHOD zif_excel_converter~create_fieldcatalog. + DATA: lo_salv TYPE REF TO cl_salv_table. + + TRY. + zif_excel_converter~can_convert_object( io_object = io_object ). + ENDTRY. + + ws_option = is_option. + + lo_salv ?= io_object. + + CLEAR: es_layout, + et_fieldcatalog, + et_colors . + + IF lo_salv IS BOUND. + load_data( EXPORTING io_salv = lo_salv + it_table = it_table ). + apply_sort( EXPORTING it_table = it_table + IMPORTING eo_table = eo_table ) . + + get_color( EXPORTING io_table = eo_table + IMPORTING et_colors = et_colors ) . + + get_filter( IMPORTING et_filter = et_filter + CHANGING xo_table = eo_table ) . + + update_catalog( CHANGING cs_layout = es_layout + ct_fieldcatalog = et_fieldcatalog ). + ENDIF. +ENDMETHOD. + + + + + method LOAD_DATA. + DATA: lo_columns TYPE REF TO cl_salv_columns_table, + lo_aggregations TYPE REF TO cl_salv_aggregations, + lo_sorts TYPE REF TO cl_salv_sorts, + lo_filters TYPE REF TO cl_salv_filters, + lo_functional TYPE REF TO cl_salv_functional_settings, + lo_display TYPE REF TO cl_salv_display_settings, + lo_selections TYPE REF TO cl_salv_selections. + + DATA: ls_vari TYPE disvariant, + lo_layout TYPE REF TO cl_salv_layout. + + DATA: lr_form_tol TYPE REF TO cl_salv_form, + lr_form_eol TYPE REF TO cl_salv_form. + + DATA lt_kkblo_fieldcat TYPE kkblo_t_fieldcat. + DATA ls_kkblo_layout TYPE kkblo_layout. + DATA lt_kkblo_filter TYPE kkblo_t_filter. + DATA lt_kkblo_sort TYPE kkblo_t_sortinfo. + + lo_layout = io_salv->get_layout( ) . + lo_columns = io_salv->get_columns( ). + lo_aggregations = io_salv->get_aggregations( ) . + lo_sorts = io_salv->get_sorts( ) . + lo_filters = io_salv->get_filters( ) . + lo_display = io_salv->get_display_settings( ) . + lo_functional = io_salv->get_functional_settings( ) . + + REFRESH: wt_fcat, + wt_sort, + wt_filt. + +* First update metadata if we can. + IF io_salv->is_offline( ) = abap_false. + io_salv->get_metadata( ) . + ELSE. +* If we are offline we need to build this. + cl_salv_controller_metadata=>get_variant( + EXPORTING + r_layout = lo_layout + CHANGING + s_variant = ls_vari ). + ENDIF. + +*... get the column information + wt_fcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog( + r_columns = lo_columns + r_aggregations = lo_aggregations ). + +*... get the layout information + cl_salv_controller_metadata=>get_lvc_layout( + EXPORTING + r_functional_settings = lo_functional + r_display_settings = lo_display + r_columns = lo_columns + r_aggregations = lo_aggregations + CHANGING + s_layout = ws_layo ). + +* the fieldcatalog is not complete yet! + CALL FUNCTION 'LVC_FIELDCAT_COMPLETE' + EXPORTING + i_complete = 'X' + i_refresh_buffer = space + i_buffer_active = space + is_layout = ws_layo + i_test = '1' + i_fcat_complete = 'X' + IMPORTING +* E_EDIT = + es_layout = ws_layo + CHANGING + ct_fieldcat = wt_fcat. + + IF ls_vari IS NOT INITIAL AND io_salv->is_offline( ) = abap_true. + CALL FUNCTION 'LVC_TRANSFER_TO_KKBLO' + EXPORTING + it_fieldcat_lvc = wt_fcat + is_layout_lvc = ws_layo + IMPORTING + et_fieldcat_kkblo = lt_kkblo_fieldcat + es_layout_kkblo = ls_kkblo_layout + TABLES + it_data = it_table + EXCEPTIONS + it_data_missing = 1 + it_fieldcat_lvc_missing = 2 + OTHERS = 3. + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ENDIF. + + CALL FUNCTION 'LT_VARIANT_LOAD' + EXPORTING +* I_TOOL = 'LT' + i_tabname = '1' +* I_TABNAME_SLAVE = + i_dialog = ' ' +* I_USER_SPECIFIC = ' ' +* I_DEFAULT = 'X' +* I_NO_REPTEXT_OPTIMIZE = +* I_VIA_GRID = + i_fcat_complete = 'X' + IMPORTING +* E_EXIT = + et_fieldcat = lt_kkblo_fieldcat + et_sort = lt_kkblo_sort + et_filter = lt_kkblo_filter + CHANGING + cs_layout = ls_kkblo_layout + ct_default_fieldcat = lt_kkblo_fieldcat + cs_variant = ls_vari + EXCEPTIONS + wrong_input = 1 + fc_not_complete = 2 + not_found = 3 + OTHERS = 4 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ENDIF. + + CALL FUNCTION 'LVC_TRANSFER_FROM_KKBLO' + EXPORTING +* I_TECH_COMPLETE = +* I_STRUCTURE_NAME = + it_fieldcat_kkblo = lt_kkblo_fieldcat + it_sort_kkblo = lt_kkblo_sort + it_filter_kkblo = lt_kkblo_filter +* IT_SPECIAL_GROUPS_KKBLO = +* IT_FILTERED_ENTRIES_KKBLO = +* IT_GROUPLEVELS_KKBLO = +* IS_SUBTOT_OPTIONS_KKBLO = + is_layout_kkblo = ls_kkblo_layout +* IS_REPREP_ID_KKBLO = +* I_CALLBACK_PROGRAM_KKBLO = +* IT_ADD_FIELDCAT = +* IT_EXCLUDING_KKBLO = +* IT_EXCEPT_QINFO_KKBLO = + IMPORTING + et_fieldcat_lvc = wt_fcat + et_sort_lvc = wt_sort + et_filter_lvc = wt_filt +* ET_SPECIAL_GROUPS_LVC = +* ET_FILTER_INDEX_LVC = +* ET_GROUPLEVELS_LVC = +* ES_TOTAL_OPTIONS_LVC = + es_layout_lvc = ws_layo +* ES_VARIANT_LVC = +* E_VARIANT_SAVE_LVC = +* ES_PRINT_INFO_LVC = +* ES_REPREP_LVC = +* E_REPREP_ACTIVE_LVC = +* ET_EXCLUDING_LVC = +* ET_EXCEPT_QINFO_LVC = + TABLES + it_data = it_table + EXCEPTIONS + it_data_missing = 1 + OTHERS = 2 + . + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ENDIF. + + ELSE. +* ... get the sort information + wt_sort = cl_salv_controller_metadata=>get_lvc_sort( lo_sorts ). + +* ... get the filter information + wt_filt = cl_salv_controller_metadata=>get_lvc_filter( lo_filters ). + ENDIF. + + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + " Initialise instance variables + formula1 = ''. + formula2 = ''. + type = me->c_type_none. + errorstyle = me->c_style_stop. + operator = ''. + allowblank = abap_false. + showdropdown = abap_false. + showinputmessage = abap_true. + showerrormessage = abap_true. + errortitle = ''. + error = ''. + prompttitle = ''. + prompt = ''. +* inizialize dimension range + cell_row = 1. + cell_column = 'A'. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + method ADD. + data_validations->add( ip_data_validation ). + endmethod. + + + method CLEAR. + data_validations->clear( ). + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT data_validations. + + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= data_validations->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = data_validations->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + data_validations->remove( ip_data_validation ). + endmethod. + + + + method SIZE. + ep_size = data_validations->if_object_collection~size( ). + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + METHOD constructor. + +* CALL FUNCTION 'GUID_CREATE' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = me->guid. + me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call + + IF ip_title IS NOT INITIAL. + title = ip_title. + ELSE. + title = me->guid. + ENDIF. + + me->type = ip_type. + +* inizialize dimension range + anchor = anchor_one_cell. + from_loc-col = 1. + from_loc-row = 1. +ENDMETHOD. + + + + method CREATE_MEDIA_NAME. + +* if media name is initial, create unique name + CHECK media_name IS INITIAL. + + index = ip_index. + CONCATENATE me->type index INTO media_name. + CONDENSE media_name NO-GAPS. + endmethod. + + + + + + METHOD emu2pixel. +* suppose 96 DPI + IF ip_dpi IS SUPPLIED. +* r_emu = ip_pixel * 914400 / ip_dpi. + r_pixel = ip_emu * ip_dpi / 914400. + ELSE. +* suppose 96 DPI +* r_emu = ip_pixel * 914400 / 96. + r_pixel = ip_emu * 96 / 914400. + ENDIF. +ENDMETHOD. + + + + method GET_FROM_COL. + r_from_col = me->from_loc-col. + endmethod. + + + + method GET_FROM_ROW. + r_from_row = me->from_loc-row. + endmethod. + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + method GET_HEIGHT_EMU_STR. + r_height = pixel2emu( size-height ). + CONDENSE r_height NO-GAPS. + endmethod. + + + + method GET_INDEX. + rp_index = me->index. + endmethod. + + + + METHOD get_media. + + DATA: lv_language TYPE sylangu. + DATA: lt_bin_mime TYPE sdokcntbins. + DATA: lt_mime TYPE tsfmime, + lv_filesize TYPE i, + lv_filesizec(10). + + CASE media_source. + WHEN c_media_source_xstring. + r_media = media. + WHEN c_media_source_www. + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = media_key_www + TABLES + mime = lt_mime + EXCEPTIONS + OTHERS = 1. + + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = media_key_www-relid + objid = media_key_www-objid + name = 'filesize' + IMPORTING + value = lv_filesizec. + + lv_filesize = lv_filesizec. + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filesize + IMPORTING + buffer = r_media + TABLES + binary_tab = lt_mime + EXCEPTIONS + failed = 1 + OTHERS = 2. + WHEN c_media_source_mime. + lv_language = sy-langu. + cl_wb_mime_repository=>load_mime( EXPORTING + io = me->io + IMPORTING + filesize = lv_filesize + bin_data = lt_bin_mime + CHANGING + language = lv_language ). + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filesize + IMPORTING + buffer = r_media + TABLES + binary_tab = lt_bin_mime + EXCEPTIONS + failed = 1 + OTHERS = 2. + ENDCASE. +ENDMETHOD. + + + + method GET_MEDIA_NAME. + CONCATENATE media_name `.` media_type INTO r_name. + endmethod. + + + + method GET_MEDIA_TYPE. + r_type = media_type. + endmethod. + + + + method GET_NAME. + r_name = title. + endmethod. + + + + method GET_POSITION. + rp_position-anchor = anchor. + rp_position-from = from_loc. + rp_position-to = to_loc. + rp_position-size = size. + endmethod. + + + + method GET_TO_COL. + r_to_col = me->to_loc-col. + endmethod. + + + + method GET_TO_ROW. + r_to_row = me->to_loc-row. + endmethod. + + + + method GET_TYPE. + rp_type = me->type. + endmethod. + + + + method GET_WIDTH_EMU_STR. + r_width = pixel2emu( size-width ). + CONDENSE r_width NO-GAPS. + endmethod. + + + + method LOAD_CHART_ATTRIBUTES. + DATA: node TYPE REF TO if_ixml_element. + DATA: node2 TYPE REF TO if_ixml_element. + DATA: node3 TYPE REF TO if_ixml_element. + DATA: node4 TYPE REF TO if_ixml_element. + DATA: iterator TYPE REF TO if_ixml_node_iterator. + + DATA: chartspace TYPE REF TO if_ixml_node_collection. + DATA: coll_length TYPE i. + DATA: chartelem TYPE REF TO if_ixml_element. + + DATA lo_barchart TYPE REF TO zcl_excel_graph_bars. + DATA lo_piechart TYPE REF TO zcl_excel_graph_pie. + DATA lo_linechart TYPE REF TO zcl_excel_graph_line. + + TYPES: BEGIN OF t_prop, + val TYPE string, + rtl TYPE string, + lang TYPE string, + formatcode TYPE string, + sourcelinked TYPE string, + END OF t_prop. + + TYPES: BEGIN OF t_pagemargins, + b TYPE string, + l TYPE string, + r TYPE string, + t TYPE string, + header TYPE string, + footer TYPE string, + END OF t_pagemargins. + + DATA ls_prop TYPE t_prop. + DATA ls_pagemargins TYPE t_pagemargins. + + DATA lo_collection TYPE REF TO if_ixml_node_collection. + DATA lo_node TYPE REF TO if_ixml_node. + DATA lo_iterator TYPE REF TO if_ixml_node_iterator. + DATA lv_idx TYPE i. + DATA lv_order TYPE i. + DATA lv_invertifnegative TYPE string. + DATA lv_symbol TYPE string. + DATA lv_smooth TYPE c. + DATA lv_sername TYPE string. + DATA lv_label TYPE string. + DATA lv_value TYPE string. + DATA lv_axid TYPE string. + DATA lv_orientation TYPE string. + DATA lv_delete TYPE string. + DATA lv_axpos TYPE string. + DATA lv_formatcode TYPE string. + DATA lv_sourcelinked TYPE string. + DATA lv_majortickmark TYPE string. + DATA lv_minortickmark TYPE string. + DATA lv_ticklblpos TYPE string. + DATA lv_crossax TYPE string. + DATA lv_crosses TYPE string. + DATA lv_auto TYPE string. + DATA lv_lblalgn TYPE string. + DATA lv_lbloffset TYPE string. + DATA lv_nomultilvllbl TYPE string. + DATA lv_crossbetween TYPE string. + + node ?= ip_chart->if_ixml_node~get_first_child( ). + CHECK node IS NOT INITIAL. + + CASE me->graph_type. + WHEN c_graph_bars. + CREATE OBJECT lo_barchart. + me->graph = lo_barchart. + WHEN c_graph_pie. + CREATE OBJECT lo_piechart. + me->graph = lo_piechart. + WHEN c_graph_line. + CREATE OBJECT lo_linechart. + me->graph = lo_linechart. + WHEN OTHERS. + ENDCASE. + + "Fill properties + node2 ?= node->find_from_name( name = 'date1904' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_1904val = ls_prop-val. + node2 ?= node->find_from_name( name = 'lang' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_langval = ls_prop-val. + node2 ?= node->find_from_name( name = 'roundedCorners' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_roundedcornersval = ls_prop-val. + + "style + node2 ?= node->find_from_name( name = 'style' namespace = 'c14' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_c14styleval = ls_prop-val. + node2 ?= node->find_from_name( name = 'style' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_styleval = ls_prop-val. + "---------------------------Read graph properties + node2 ?= node->find_from_name( name = 'autoTitleDeleted' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_autotitledeletedval = ls_prop-val. + + "plotArea + CASE me->graph_type. + WHEN c_graph_bars. + node2 ?= node->find_from_name( name = 'barDir' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_bardirval = ls_prop-val. + node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_groupingval = ls_prop-val. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'invertIfNegative' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_invertifnegative = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_barchart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_invertifnegative = lv_invertifnegative + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_showbubblesizeval = ls_prop-val. + node2 ?= node->find_from_name( name = 'gapWidth' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_gapwidthval = ls_prop-val. + + "Load axes + node2 ?= node->find_from_name( name = 'barChart' namespace = 'c' ). + CALL METHOD node2->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'axId' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lv_axid = ls_prop-val. + IF sy-index EQ 1. "catAx + node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_auto = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lblalgn = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lbloffset = ls_prop-val. + node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_nomultilvllbl = ls_prop-val. + CALL METHOD lo_barchart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_bars=>c_catax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_auto = lv_auto + ip_lblalgn = lv_lblalgn + ip_lbloffset = lv_lbloffset + ip_nomultilvllbl = lv_nomultilvllbl. + ELSEIF sy-index EQ 2. "valAx + node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossbetween = ls_prop-val. + CALL METHOD lo_barchart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_bars=>c_valax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_crossbetween = lv_crossbetween. + ENDIF. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + + WHEN c_graph_pie. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_piechart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showbubblesizeval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showLeaderLines' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_showleaderlinesval = ls_prop-val. + node2 ?= node->find_from_name( name = 'firstSliceAng' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_firstsliceangval = ls_prop-val. + WHEN c_graph_line. + node2 ?= node->find_from_name( name = 'grouping' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_groupingval = ls_prop-val. + node2 ?= node->find_from_name( name = 'varyColors' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_varycolorsval = ls_prop-val. + + "Load series + CALL METHOD node->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'ser' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + node3 ?= node2->find_from_name( name = 'idx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_idx = ls_prop-val. + node3 ?= node2->find_from_name( name = 'order' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_order = ls_prop-val. + node3 ?= node2->find_from_name( name = 'symbol' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_symbol = ls_prop-val. + node3 ?= node2->find_from_name( name = 'smooth' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_smooth = ls_prop-val. + node3 ?= node2->find_from_name( name = 'v' namespace = 'c' ). + IF node3 IS BOUND. + lv_sername = node3->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'strRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_label = node4->get_value( ). + ENDIF. + node3 ?= node2->find_from_name( name = 'numRef' namespace = 'c' ). + IF node3 IS BOUND. + node4 ?= node3->find_from_name( name = 'f' namespace = 'c' ). + lv_value = node4->get_value( ). + ENDIF. + CALL METHOD lo_linechart->create_serie + EXPORTING + ip_idx = lv_idx + ip_order = lv_order + ip_symbol = lv_symbol + ip_smooth = lv_smooth + ip_lbl = lv_label + ip_ref = lv_value + ip_sername = lv_sername. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + "note: numCache avoided + node2 ?= node->find_from_name( name = 'showLegendKey' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showlegendkeyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showVal' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showvalval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showCatName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showcatnameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showSerName' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showsernameval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showPercent' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showpercentval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showBubbleSize' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_showbubblesizeval = ls_prop-val. + + node ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). + node2 ?= node->find_from_name( name = 'marker' namespace = 'c' DEPTH = '1' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->NS_MARKERVAL = ls_prop-val. + node2 ?= node->find_from_name( name = 'smooth' namespace = 'c' DEPTH = '1' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->NS_SMOOTHVAL = ls_prop-val. + node ?= ip_chart->if_ixml_node~get_first_child( ). + CHECK node IS NOT INITIAL. + + "Load axes + node2 ?= node->find_from_name( name = 'lineChart' namespace = 'c' ). + CALL METHOD node2->get_elements_by_tag_name + EXPORTING +* depth = 0 + name = 'axId' +* namespace = '' + RECEIVING + rval = lo_collection. + CALL METHOD lo_collection->create_iterator + RECEIVING + rval = lo_iterator. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + WHILE lo_node IS BOUND. + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lv_axid = ls_prop-val. + IF sy-index EQ 1. "catAx + node2 ?= node->find_from_name( name = 'catAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. +* node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). +* zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). +* lv_formatcode = ls_prop-formatcode. +* lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'auto' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_auto = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblAlgn' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lblalgn = ls_prop-val. + node3 ?= node2->find_from_name( name = 'lblOffset' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_lbloffset = ls_prop-val. + node3 ?= node2->find_from_name( name = 'noMultiLvlLbl' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_nomultilvllbl = ls_prop-val. + CALL METHOD lo_linechart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_line=>c_catax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_auto = lv_auto + ip_lblalgn = lv_lblalgn + ip_lbloffset = lv_lbloffset + ip_nomultilvllbl = lv_nomultilvllbl. + ELSEIF sy-index EQ 2. "valAx + node2 ?= node->find_from_name( name = 'valAx' namespace = 'c' ). + node3 ?= node2->find_from_name( name = 'orientation' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_orientation = ls_prop-val. + node3 ?= node2->find_from_name( name = 'delete' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_delete = ls_prop-val. + node3 ?= node2->find_from_name( name = 'axPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_axpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'numFmt' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_formatcode = ls_prop-formatcode. + lv_sourcelinked = ls_prop-sourcelinked. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_majortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'majorTickMark' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_minortickmark = ls_prop-val. + node3 ?= node2->find_from_name( name = 'tickLblPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_ticklblpos = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossAx' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossax = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crosses' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crosses = ls_prop-val. + node3 ?= node2->find_from_name( name = 'crossBetween' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = ls_prop ). + lv_crossbetween = ls_prop-val. + CALL METHOD lo_linechart->create_ax + EXPORTING + ip_axid = lv_axid + ip_type = zcl_excel_graph_line=>c_valax + ip_orientation = lv_orientation + ip_delete = lv_delete + ip_axpos = lv_axpos + ip_formatcode = lv_formatcode + ip_sourcelinked = lv_sourcelinked + ip_majortickmark = lv_majortickmark + ip_minortickmark = lv_minortickmark + ip_ticklblpos = lv_ticklblpos + ip_crossax = lv_crossax + ip_crosses = lv_crosses + ip_crossbetween = lv_crossbetween. + ENDIF. + lo_node = lo_iterator->get_next( ). + IF lo_node IS BOUND. + node2 ?= lo_node->query_interface( ixml_iid_element ). + ENDIF. + ENDWHILE. + WHEN OTHERS. + ENDCASE. + + "legend + CASE me->graph_type. + WHEN c_graph_bars. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_barchart->ns_overlayval = ls_prop-val. + WHEN c_graph_line. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_linechart->ns_overlayval = ls_prop-val. + WHEN c_graph_pie. + node2 ?= node->find_from_name( name = 'legendPos' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_legendposval = ls_prop-val. + node2 ?= node->find_from_name( name = 'overlay' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_overlayval = ls_prop-val. + node2 ?= node->find_from_name( name = 'pPr' namespace = 'a' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_pprrtl = ls_prop-rtl. + node2 ?= node->find_from_name( name = 'endParaRPr' namespace = 'a' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + lo_piechart->ns_endpararprlang = ls_prop-lang. + + WHEN OTHERS. + ENDCASE. + + node2 ?= node->find_from_name( name = 'plotVisOnly' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_plotvisonlyval = ls_prop-val. + node2 ?= node->find_from_name( name = 'dispBlanksAs' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_dispblanksasval = ls_prop-val. + node2 ?= node->find_from_name( name = 'showDLblsOverMax' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_prop ). + me->graph->ns_showdlblsovermaxval = ls_prop-val. + "--------------------- + + node2 ?= node->find_from_name( name = 'pageMargins' namespace = 'c' ). + zcl_excel_reader_2007=>fill_struct_from_attributes( EXPORTING ip_element = node2 CHANGING cp_structure = ls_pagemargins ). + me->graph->pagemargins = ls_pagemargins. + + + endmethod. + + + + + + method PIXEL2EMU. +* suppose 96 DPI + IF ip_dpi IS SUPPLIED. + r_emu = ip_pixel * 914400 / ip_dpi. + ELSE. +* suppose 96 DPI + r_emu = ip_pixel * 914400 / 96. + ENDIF. + endmethod. + + + + + + + method SET_MEDIA. + IF ip_media IS SUPPLIED. + media = ip_media. + ENDIF. + media_type = ip_media_type. + media_source = c_media_source_xstring. + IF ip_width IS SUPPLIED. + size-width = ip_width. + ENDIF. + IF ip_height IS SUPPLIED. + size-height = ip_height. + ENDIF. + endmethod. + + + + + + METHOD set_media_mime. + + DATA: lv_language TYPE sylangu. + + io = ip_io. + media_source = c_media_source_mime. + size-width = ip_width. + size-height = ip_height. + + lv_language = sy-langu. + cl_wb_mime_repository=>load_mime( EXPORTING + io = ip_io + IMPORTING + filename = media_name + "mimetype = media_type + CHANGING + language = lv_language ). + + SPLIT media_name AT '.' INTO media_name media_type. + +ENDMETHOD. + + + + + + method SET_MEDIA_WWW. + DATA: lv_value(20). + + media_key_www = ip_key. + media_source = c_media_source_www. + + CALL FUNCTION 'WWWPARAMS_READ' + EXPORTING + relid = media_key_www-relid + objid = media_key_www-objid + name = 'fileextension' + IMPORTING + value = lv_value. + media_type = lv_value. + SHIFT media_type LEFT DELETING LEADING '.'. + + size-width = ip_width. + size-height = ip_height. + endmethod. + + + + + + + method SET_POSITION. + from_loc-col = zcl_excel_common=>convert_column2int( ip_from_col ) - 1. + IF ip_coloff IS SUPPLIED. + from_loc-col_offset = ip_coloff. + ENDIF. + from_loc-row = ip_from_row - 1. + IF ip_rowoff IS SUPPLIED. + from_loc-row_offset = ip_rowoff. + ENDIF. + anchor = anchor_one_cell. + endmethod. + + + + + + method SET_POSITION2. + + data: lv_anchor type zexcel_drawing_anchor. + lv_anchor = ip_anchor. + + IF lv_anchor IS INITIAL. + IF ip_to IS NOT INITIAL. + lv_anchor = anchor_two_cell. + ELSE. + lv_anchor = anchor_one_cell. + ENDIF. + ENDIF. + + CASE lv_anchor. + WHEN anchor_absolute OR anchor_one_cell. + CLEAR: me->to_loc. + WHEN anchor_two_cell. + CLEAR: me->size. + ENDCASE. + + me->from_loc = ip_from. + me->to_loc = ip_to. + me->anchor = lv_anchor. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + method ADD. + DATA: lv_index TYPE i. + + drawings->add( ip_drawing ). + lv_index = drawings->if_object_collection~size( ). + ip_drawing->create_media_name( + ip_index = lv_index ). + endmethod. + + + method CLEAR. + + drawings->clear( ). + endmethod. + + + + method CONSTRUCTOR. + + CREATE OBJECT drawings. + type = ip_type. + + endmethod. + + + + + method GET. + + DATA lv_index TYPE i. + lv_index = ip_index. + eo_drawing ?= drawings->if_object_collection~get( lv_index ). + endmethod. + + + + method GET_ITERATOR. + + eo_iterator ?= drawings->if_object_collection~get_iterator( ). + endmethod. + + + + method GET_TYPE. + rp_type = me->type. + endmethod. + + + + method INCLUDE. + drawings->add( ip_drawing ). + endmethod. + + + + method IS_EMPTY. + + is_empty = drawings->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + + drawings->remove( ip_drawing ). + endmethod. + + + + method SIZE. + + ep_size = drawings->if_object_collection~size( ). + endmethod. + + + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + "Load default values + me->pagemargins-b = '0.75'. + me->pagemargins-l = '0.7'. + me->pagemargins-r = '0.7'. + me->pagemargins-t = '0.75'. + me->pagemargins-header = '0.3'. + me->pagemargins-footer = '0.3'. + endmethod. + + + + + + + + + + + + + + + + + + + + method CREATE_SERIE. + DATA ls_serie TYPE s_series. + + DATA: lv_start_row_c TYPE char7, + lv_stop_row_c TYPE char7. + + + IF ip_lbl IS NOT SUPPLIED. + lv_stop_row_c = ip_lbl_to_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_lbl_from_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + ls_serie-lbl = ip_sheet. + ls_serie-lbl = zcl_excel_common=>escape_string( ip_value = ls_serie-lbl ). + CONCATENATE ls_serie-lbl '!$' ip_lbl_from_col '$' lv_start_row_c ':$' ip_lbl_to_col '$' lv_stop_row_c INTO ls_serie-lbl. + CLEAR: lv_start_row_c, lv_stop_row_c. + ELSE. + ls_serie-lbl = ip_lbl. + ENDIF. + IF ip_ref IS NOT SUPPLIED. + lv_stop_row_c = ip_ref_to_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_ref_from_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + ls_serie-ref = ip_sheet. + ls_serie-ref = zcl_excel_common=>escape_string( ip_value = ls_serie-ref ). + CONCATENATE ls_serie-ref '!$' ip_ref_from_col '$' lv_start_row_c ':$' ip_ref_to_col '$' lv_stop_row_c INTO ls_serie-ref. + CLEAR: lv_start_row_c, lv_stop_row_c. + ELSE. + ls_serie-ref = ip_ref. + ENDIF. + ls_serie-idx = ip_idx. + ls_serie-order = ip_order. + ls_serie-invertifnegative = ip_invertifnegative. + ls_serie-symbol = ip_symbol. + ls_serie-smooth = ip_smooth. + ls_serie-sername = ip_sername. + APPEND ls_serie TO me->series. + SORT me->series BY order ASCENDING. + endmethod. + + + + method SET_PRINT_LBL. + me->print_label = ip_value. + endmethod. + + + + method SET_STYLE. + me->ns_c14styleval = ip_style-c14style. + CONDENSE me->ns_c14styleval NO-GAPS. + me->ns_styleval = ip_style-cstyle. + CONDENSE me->ns_styleval NO-GAPS. + endmethod. + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CREATE_AX. + DATA ls_ax TYPE s_ax. + ls_ax-type = ip_type. + + if ip_type = c_catax. + if ip_axid is SUPPLIED. + ls_ax-axid = ip_axid. + else. + ls_ax-axid = '1'. + endif. + if ip_orientation is SUPPLIED. + ls_ax-orientation = ip_orientation. + else. + ls_ax-orientation = 'minMax'. + endif. + if ip_delete is SUPPLIED. + ls_ax-delete = ip_delete. + else. + ls_ax-delete = '0'. + endif. + if ip_axpos is SUPPLIED. + ls_ax-axpos = ip_axpos. + else. + ls_ax-axpos = 'b'. + endif. + if ip_formatcode is SUPPLIED. + ls_ax-formatcode = ip_formatcode. + else. + ls_ax-formatcode = 'General'. + endif. + if ip_sourcelinked is SUPPLIED. + ls_ax-sourcelinked = ip_sourcelinked. + else. + ls_ax-sourcelinked = '1'. + endif. + if ip_majorTickMark is SUPPLIED. + ls_ax-majorTickMark = ip_majorTickMark. + else. + ls_ax-majorTickMark = 'out'. + endif. + if ip_minorTickMark is SUPPLIED. + ls_ax-minorTickMark = ip_minorTickMark. + else. + ls_ax-minorTickMark = 'none'. + endif. + if ip_ticklblpos is SUPPLIED. + ls_ax-ticklblpos = ip_ticklblpos. + else. + ls_ax-ticklblpos = 'nextTo'. + endif. + if ip_crossax is SUPPLIED. + ls_ax-crossax = ip_crossax. + else. + ls_ax-crossax = '2'. + endif. + if ip_crosses is SUPPLIED. + ls_ax-crosses = ip_crosses. + else. + ls_ax-crosses = 'autoZero'. + endif. + if ip_auto is SUPPLIED. + ls_ax-auto = ip_auto. + else. + ls_ax-auto = '1'. + endif. + if ip_lblAlgn is SUPPLIED. + ls_ax-lblAlgn = ip_lblAlgn. + else. + ls_ax-lblAlgn = 'ctr'. + endif. + if ip_lblOffset is SUPPLIED. + ls_ax-lblOffset = ip_lblOffset. + else. + ls_ax-lblOffset = '100'. + endif. + if ip_noMultiLvlLbl is SUPPLIED. + ls_ax-noMultiLvlLbl = ip_noMultiLvlLbl. + else. + ls_ax-noMultiLvlLbl = '0'. + endif. + elseif ip_type = c_valax. + if ip_axid is SUPPLIED. + ls_ax-axid = ip_axid. + else. + ls_ax-axid = '2'. + endif. + if ip_orientation is SUPPLIED. + ls_ax-orientation = ip_orientation. + else. + ls_ax-orientation = 'minMax'. + endif. + if ip_delete is SUPPLIED. + ls_ax-delete = ip_delete. + else. + ls_ax-delete = '0'. + endif. + if ip_axpos is SUPPLIED. + ls_ax-axpos = ip_axpos. + else. + ls_ax-axpos = 'l'. + endif. + if ip_formatcode is SUPPLIED. + ls_ax-formatcode = ip_formatcode. + else. + ls_ax-formatcode = 'General'. + endif. + if ip_sourcelinked is SUPPLIED. + ls_ax-sourcelinked = ip_sourcelinked. + else. + ls_ax-sourcelinked = '1'. + endif. + if ip_majorTickMark is SUPPLIED. + ls_ax-majorTickMark = ip_majorTickMark. + else. + ls_ax-majorTickMark = 'out'. + endif. + if ip_minorTickMark is SUPPLIED. + ls_ax-minorTickMark = ip_minorTickMark. + else. + ls_ax-minorTickMark = 'none'. + endif. + if ip_ticklblpos is SUPPLIED. + ls_ax-ticklblpos = ip_ticklblpos. + else. + ls_ax-ticklblpos = 'nextTo'. + endif. + if ip_crossax is SUPPLIED. + ls_ax-crossax = ip_crossax. + else. + ls_ax-crossax = '1'. + endif. + if ip_crosses is SUPPLIED. + ls_ax-crosses = ip_crosses. + else. + ls_ax-crosses = 'autoZero'. + endif. + if ip_crossBetween is SUPPLIED. + ls_ax-crossBetween = ip_crossBetween. + else. + ls_ax-crossBetween = 'between'. + endif. + endif. + + APPEND ls_ax TO me->axes. + sort me->axes by axid ascending. + endmethod. + + + + method SET_SHOW_CAT_NAME. + ns_showcatnameval = ip_value. + endmethod. + + + + method SET_SHOW_LEGEND_KEY. + ns_showlegendkeyval = ip_value. + endmethod. + + + + method SET_SHOW_PERCENT. + ns_showpercentval = ip_value. + endmethod. + + + + method SET_SHOW_SER_NAME. + ns_showsernameval = ip_value. + endmethod. + + + + method SET_SHOW_VALUES. + ns_showvalval = ip_value. + endmethod. + + + + method SET_VARYCOLOR. + ns_varycolorsval = ip_value. + endmethod. + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CREATE_AX. + DATA ls_ax TYPE s_ax. + ls_ax-type = ip_type. + + IF ip_type = c_catax. + IF ip_axid IS SUPPLIED. + ls_ax-axid = ip_axid. + ELSE. + ls_ax-axid = '1'. + ENDIF. + IF ip_orientation IS SUPPLIED. + ls_ax-orientation = ip_orientation. + ELSE. + ls_ax-orientation = 'minMax'. + ENDIF. + IF ip_delete IS SUPPLIED. + ls_ax-delete = ip_delete. + ELSE. + ls_ax-delete = '0'. + ENDIF. + IF ip_axpos IS SUPPLIED. + ls_ax-axpos = ip_axpos. + ELSE. + ls_ax-axpos = 'b'. + ENDIF. + IF ip_formatcode IS SUPPLIED. + ls_ax-formatcode = ip_formatcode. + ELSE. + ls_ax-formatcode = 'General'. + ENDIF. + IF ip_sourcelinked IS SUPPLIED. + ls_ax-sourcelinked = ip_sourcelinked. + ELSE. + ls_ax-sourcelinked = '1'. + ENDIF. + IF ip_majortickmark IS SUPPLIED. + ls_ax-majortickmark = ip_majortickmark. + ELSE. + ls_ax-majortickmark = 'out'. + ENDIF. + IF ip_minortickmark IS SUPPLIED. + ls_ax-minortickmark = ip_minortickmark. + ELSE. + ls_ax-minortickmark = 'none'. + ENDIF. + IF ip_ticklblpos IS SUPPLIED. + ls_ax-ticklblpos = ip_ticklblpos. + ELSE. + ls_ax-ticklblpos = 'nextTo'. + ENDIF. + IF ip_crossax IS SUPPLIED. + ls_ax-crossax = ip_crossax. + ELSE. + ls_ax-crossax = '2'. + ENDIF. + IF ip_crosses IS SUPPLIED. + ls_ax-crosses = ip_crosses. + ELSE. + ls_ax-crosses = 'autoZero'. + ENDIF. + IF ip_auto IS SUPPLIED. + ls_ax-auto = ip_auto. + ELSE. + ls_ax-auto = '1'. + ENDIF. + IF ip_lblalgn IS SUPPLIED. + ls_ax-lblalgn = ip_lblalgn. + ELSE. + ls_ax-lblalgn = 'ctr'. + ENDIF. + IF ip_lbloffset IS SUPPLIED. + ls_ax-lbloffset = ip_lbloffset. + ELSE. + ls_ax-lbloffset = '100'. + ENDIF. + IF ip_nomultilvllbl IS SUPPLIED. + ls_ax-nomultilvllbl = ip_nomultilvllbl. + ELSE. + ls_ax-nomultilvllbl = '0'. + ENDIF. + ELSEIF ip_type = c_valax. + IF ip_axid IS SUPPLIED. + ls_ax-axid = ip_axid. + ELSE. + ls_ax-axid = '2'. + ENDIF. + IF ip_orientation IS SUPPLIED. + ls_ax-orientation = ip_orientation. + ELSE. + ls_ax-orientation = 'minMax'. + ENDIF. + IF ip_delete IS SUPPLIED. + ls_ax-delete = ip_delete. + ELSE. + ls_ax-delete = '0'. + ENDIF. + IF ip_axpos IS SUPPLIED. + ls_ax-axpos = ip_axpos. + ELSE. + ls_ax-axpos = 'l'. + ENDIF. + IF ip_formatcode IS SUPPLIED. + ls_ax-formatcode = ip_formatcode. + ELSE. + ls_ax-formatcode = 'General'. + ENDIF. + IF ip_sourcelinked IS SUPPLIED. + ls_ax-sourcelinked = ip_sourcelinked. + ELSE. + ls_ax-sourcelinked = '1'. + ENDIF. + IF ip_majortickmark IS SUPPLIED. + ls_ax-majortickmark = ip_majortickmark. + ELSE. + ls_ax-majortickmark = 'out'. + ENDIF. + IF ip_minortickmark IS SUPPLIED. + ls_ax-minortickmark = ip_minortickmark. + ELSE. + ls_ax-minortickmark = 'none'. + ENDIF. + IF ip_ticklblpos IS SUPPLIED. + ls_ax-ticklblpos = ip_ticklblpos. + ELSE. + ls_ax-ticklblpos = 'nextTo'. + ENDIF. + IF ip_crossax IS SUPPLIED. + ls_ax-crossax = ip_crossax. + ELSE. + ls_ax-crossax = '1'. + ENDIF. + IF ip_crosses IS SUPPLIED. + ls_ax-crosses = ip_crosses. + ELSE. + ls_ax-crosses = 'autoZero'. + ENDIF. + IF ip_crossbetween IS SUPPLIED. + ls_ax-crossbetween = ip_crossbetween. + ELSE. + ls_ax-crossbetween = 'between'. + ENDIF. + ENDIF. + + APPEND ls_ax TO me->axes. + SORT me->axes BY axid ASCENDING. + endmethod. + + + + method SET_SHOW_CAT_NAME. + ns_showcatnameval = ip_value. + endmethod. + + + + method SET_SHOW_LEGEND_KEY. + ns_showlegendkeyval = ip_value. + endmethod. + + + + method SET_SHOW_PERCENT. + ns_showpercentval = ip_value. + endmethod. + + + + method SET_SHOW_SER_NAME. + ns_showsernameval = ip_value. + endmethod. + + + + method SET_SHOW_VALUES. + ns_showvalval = ip_value. + endmethod. + + + + method SET_VARYCOLOR. + ns_varycolorsval = ip_value. + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + method SET_SHOW_CAT_NAME. + ns_showcatnameval = ip_value. + endmethod. + + + + method SET_SHOW_LEADER_LINES. + ns_showleaderlinesval = ip_value. + endmethod. + + + + method SET_SHOW_LEGEND_KEY. + ns_showlegendkeyval = ip_value. + endmethod. + + + + method SET_SHOW_PERCENT. + ns_showpercentval = ip_value. + endmethod. + + + + method SET_SHOW_SER_NAME. + ns_showsernameval = ip_value. + endmethod. + + + + method SET_SHOW_VALUES. + ns_showvalval = ip_value. + endmethod. + + + + method SET_VARYCOLOR. + ns_varycolorsval = ip_value. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + method CREATE. + data: lo_hyperlink type REF TO zcl_excel_hyperlink. + + create OBJECT lo_hyperlink. + + lo_hyperlink->location = iv_url. + lo_hyperlink->internal = iv_internal. + + ov_link = lo_hyperlink. + endmethod. + + + + + method CREATE_EXTERNAL_LINK. + + ov_link = zcl_excel_hyperlink=>create( iv_url = iv_url + iv_internal = abap_false ). + endmethod. + + + + + method CREATE_INTERNAL_LINK. + ov_link = zcl_excel_hyperlink=>create( iv_url = iv_location + iv_internal = abap_true ). + endmethod. + + + + method GET_REF. + ev_ref = row. + CONDENSE ev_ref. + CONCATENATE column ev_ref INTO ev_ref. + endmethod. + + + + method GET_URL. + ev_url = me->location. + endmethod. + + + + method IS_INTERNAL. + ev_ret = me->internal. + endmethod. + + + + + + method SET_CELL_REFERENCE. + me->column = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column + me->row = ip_row. + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + method CONSTRUCTOR. + " default Excel palette based on + " http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.indexedcolors.aspx + + APPEND '00000000' TO colors. + APPEND '00FFFFFF' TO colors. + APPEND '00FF0000' TO colors. + APPEND '0000FF00' TO colors. + APPEND '000000FF' TO colors. + APPEND '00FFFF00' TO colors. + APPEND '00FF00FF' TO colors. + APPEND '0000FFFF' TO colors. + APPEND '00000000' TO colors. + APPEND '00FFFFFF' TO colors. + + APPEND '00FF0000' TO colors. + APPEND '0000FF00' TO colors. + APPEND '000000FF' TO colors. + APPEND '00FFFF00' TO colors. + APPEND '00FF00FF' TO colors. + APPEND '0000FFFF' TO colors. + APPEND '00800000' TO colors. + APPEND '00008000' TO colors. + APPEND '00000080' TO colors. + APPEND '00808000' TO colors. + + APPEND '00800080' TO colors. + APPEND '00008080' TO colors. + APPEND '00C0C0C0' TO colors. + APPEND '00808080' TO colors. + APPEND '009999FF' TO colors. + APPEND '00993366' TO colors. + APPEND '00FFFFCC' TO colors. + APPEND '00CCFFFF' TO colors. + APPEND '00660066' TO colors. + APPEND '00FF8080' TO colors. + + APPEND '000066CC' TO colors. + APPEND '00CCCCFF' TO colors. + APPEND '00000080' TO colors. + APPEND '00FF00FF' TO colors. + APPEND '00FFFF00' TO colors. + APPEND '0000FFFF' TO colors. + APPEND '00800080' TO colors. + APPEND '00800000' TO colors. + APPEND '00008080' TO colors. + APPEND '000000FF' TO colors. + + APPEND '0000CCFF' TO colors. + APPEND '00CCFFFF' TO colors. + APPEND '00CCFFCC' TO colors. + APPEND '00FFFF99' TO colors. + APPEND '0099CCFF' TO colors. + APPEND '00FF99CC' TO colors. + APPEND '00CC99FF' TO colors. + APPEND '00FFCC99' TO colors. + APPEND '003366FF' TO colors. + APPEND '0033CCCC' TO colors. + + APPEND '0099CC00' TO colors. + APPEND '00FFCC00' TO colors. + APPEND '00FF9900' TO colors. + APPEND '00FF6600' TO colors. + APPEND '00666699' TO colors. + APPEND '00969696' TO colors. + APPEND '00003366' TO colors. + APPEND '00339966' TO colors. + APPEND '00003300' TO colors. + APPEND '00333300' TO colors. + + APPEND '00993300' TO colors. + APPEND '00993366' TO colors. + APPEND '00333399' TO colors. + APPEND '00333333' TO colors. + + endmethod. + + + + + + method GET_COLOR. + DATA: lv_index type i. + + lv_index = ip_index + 1. + READ TABLE colors INTO ep_color INDEX lv_index. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid color index'. + ENDIF. + endmethod. + + + + method GET_COLORS. + ep_colors = colors. + endmethod. + + + + method IS_MODIFIED. + ep_modified = modified. + endmethod. + + + + + method SET_COLOR. + DATA: lv_index TYPE i. + + FIELD-SYMBOLS: <lv_color> LIKE LINE OF colors. + + lv_index = ip_index + 1. + READ TABLE colors ASSIGNING <lv_color> INDEX lv_index. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid color index'. + ENDIF. + + IF <lv_color> <> ip_color. + modified = abap_true. + <lv_color> = ip_color. + ENDIF. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + + DATA: lv_timestamp TYPE timestampl. + + GET TIME STAMP FIELD lv_timestamp. + created = lv_timestamp. + modified = lv_timestamp. + +endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + method constructor. + create object elements. + create object objectdefaults. + create object extclrschemelst. + create object extlst. + endmethod. "class_constructor + + + + method read_theme. + data: lo_node_theme type ref to if_ixml_element. + data: lo_theme_children type ref to if_ixml_node_list. + data: lo_theme_iterator type ref to if_ixml_node_iterator. + data: lo_theme_element type ref to if_ixml_element. + check io_theme_xml is not initial. + + lo_node_theme = io_theme_xml->get_root_element( )." find_from_name( name = c_theme ). + if lo_node_theme is bound. + name = lo_node_theme->get_attribute( name = c_theme_name ). + xmls_a = lo_node_theme->get_attribute( name = c_theme_xmlns ). + lo_theme_children = lo_node_theme->get_children( ). + lo_theme_iterator = lo_theme_children->create_iterator( ). + lo_theme_element ?= lo_theme_iterator->get_next( ). + while lo_theme_element is bound. + case lo_theme_element->get_name( ). + when c_theme_elements. + elements->load( io_elements = lo_theme_element ). + when c_theme_object_def. + objectdefaults->load( io_object_def = lo_theme_element ). + when c_theme_extra_color. + extclrschemelst->load( io_extra_color = lo_theme_element ). + when c_theme_extlst. + extlst->load( io_extlst = lo_theme_element ). + endcase. + lo_theme_element ?= lo_theme_iterator->get_next( ). + endwhile. + endif. + endmethod. "read_theme + + + + + + + method set_color. + elements->color_scheme->set_color( + exporting + iv_type = iv_type + iv_srgb = iv_srgb + iv_syscolorname = iv_syscolorname + iv_syscolorlast = iv_syscolorlast + ). + endmethod. "set_color + + + + method set_color_scheme_name. + elements->color_scheme->set_name( iv_name = iv_name ). + endmethod. "set_color_scheme_name + + + + + + + + method set_cs_font. + elements->font_scheme->modify_cs_font( + exporting + iv_type = iv_type + iv_typeface = iv_typeface + iv_panose = iv_panose + iv_pitchfamily = iv_pitchfamily + iv_charset = iv_charset + ). + endmethod. "set_cs_font + + + + + + + + method set_ea_font. + elements->font_scheme->modify_ea_font( + exporting + iv_type = iv_type + iv_typeface = iv_typeface + iv_panose = iv_panose + iv_pitchfamily = iv_pitchfamily + iv_charset = iv_charset + ). + endmethod. "set_ea_font + + + + + + method set_font. + elements->font_scheme->modify_font( + exporting + iv_type = iv_type + iv_script = iv_script + iv_typeface = iv_typeface + ). + endmethod. "set_font + + + + method set_font_scheme_name. + elements->font_scheme->set_name( iv_name = iv_name ). + endmethod. "set_font_scheme_name + + + + + + + + method set_latin_font. + elements->font_scheme->modify_latin_font( + exporting + iv_type = iv_type + iv_typeface = iv_typeface + iv_panose = iv_panose + iv_pitchfamily = iv_pitchfamily + iv_charset = iv_charset + ). + endmethod. "set_latin_font + + + + method set_theme_name. + name = iv_name. + endmethod. + + + + method write_theme. + data: lo_ixml type ref to if_ixml, + lo_element_root type ref to if_ixml_element, + lo_encoding type ref to if_ixml_encoding. + data: lo_streamfactory TYPE REF TO if_ixml_stream_factory. + data: lo_ostream TYPE REF TO if_ixml_ostream. + data: lo_renderer TYPE REF TO if_ixml_renderer. + data: lo_document type ref to if_ixml_document. + lo_ixml = cl_ixml=>create( ). + + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'UTF-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + lo_document->set_namespace_prefix( prefix = 'a' ). + + lo_element_root = lo_document->create_simple_element_ns( prefix = c_theme_prefix + name = c_theme + parent = lo_document + ). + lo_element_root->set_attribute_ns( name = c_theme_xmlns + value = c_theme_xmlns_val ). + lo_element_root->set_attribute_ns( name = c_theme_name + value = name ). + + elements->build_xml( io_document = lo_document ). + objectdefaults->build_xml( io_document = lo_document ). + extclrschemelst->build_xml( io_document = lo_document ). + extlst->build_xml( io_document = lo_document ). + + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = rv_xstring ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. "write_theme + + + + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method build_xml. + data: lo_scheme_element type ref to if_ixml_element. + data: lo_color type ref to if_ixml_element. + data: lo_syscolor type ref to if_ixml_element. + data: lo_srgb type ref to if_ixml_element. + data: lo_elements type ref to if_ixml_element. + + check io_document is bound. + lo_elements ?= io_document->find_from_name_ns( name = zcl_excel_theme=>c_theme_elements ). + if lo_elements is bound. + lo_scheme_element ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix + name = zcl_excel_theme_elements=>c_color_scheme + parent = lo_elements ). + lo_scheme_element->set_attribute( name = c_name value = name ). + + "! Adding colors to scheme + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix + name = c_dark1 + parent = lo_scheme_element ). + if lo_color is bound. + if dark1-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = dark1-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = dark1-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = dark1-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_light1 + parent = lo_scheme_element ). + if lo_color is bound. + if light1-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = light1-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = light1-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = light1-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_dark2 + parent = lo_scheme_element ). + if lo_color is bound. + if dark2-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = dark2-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = dark2-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = dark2-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_light2 + parent = lo_scheme_element ). + if lo_color is bound. + if light2-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = light2-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = light2-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = light2-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_accent1 + parent = lo_scheme_element ). + if lo_color is bound. + if accent1-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = accent1-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = accent1-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = accent1-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_accent2 + parent = lo_scheme_element ). + if lo_color is bound. + if accent2-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = accent2-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = accent2-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = accent2-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_accent3 + parent = lo_scheme_element ). + if lo_color is bound. + if accent3-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = accent3-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = accent3-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = accent3-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_accent4 + parent = lo_scheme_element ). + if lo_color is bound. + if accent4-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = accent4-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = accent4-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = accent4-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_accent5 + parent = lo_scheme_element ). + if lo_color is bound. + if accent5-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = accent5-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = accent5-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = accent5-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_accent6 + parent = lo_scheme_element ). + if lo_color is bound. + if accent6-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = accent6-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = accent6-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = accent6-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_hlink + parent = lo_scheme_element ). + if lo_color is bound. + if hlink-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = hlink-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = hlink-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = hlink-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + lo_color ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_folhlink + parent = lo_scheme_element ). + if lo_color is bound. + if folhlink-srgb is not initial. + lo_srgb ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_srgbcolor + parent = lo_color ). + lo_srgb->set_attribute( name = c_val value = folhlink-srgb ). + else. + lo_syscolor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_syscolor + parent = lo_color ). + lo_syscolor->set_attribute( name = c_val value = folhlink-syscolor-val ). + lo_syscolor->set_attribute( name = c_lastclr value = folhlink-syscolor-lastclr ). + endif. + clear: lo_color, lo_srgb, lo_syscolor. + endif. + + + endif. + endmethod. "build_xml + + + method constructor. + set_defaults( ). + endmethod. "constructor + + + + + method get_color. + data: lo_color_children type ref to if_ixml_node_list. + data: lo_color_iterator type ref to if_ixml_node_iterator. + data: lo_color_element type ref to if_ixml_element. + check io_object is not initial. + + lo_color_children = io_object->get_children( ). + lo_color_iterator = lo_color_children->create_iterator( ). + lo_color_element ?= lo_color_iterator->get_next( ). + if lo_color_element is bound. + case lo_color_element->get_name( ). + when c_srgbcolor. + rv_color-srgb = lo_color_element->get_attribute( name = c_val ). + when c_syscolor. + rv_color-syscolor-val = lo_color_element->get_attribute( name = c_val ). + rv_color-syscolor-lastclr = lo_color_element->get_attribute( name = c_lastclr ). + endcase. + endif. + endmethod. "get_color + + + + method load. + data: lo_scheme_children type ref to if_ixml_node_list. + data: lo_scheme_iterator type ref to if_ixml_node_iterator. + data: lo_scheme_element type ref to if_ixml_element. + check io_color_scheme is not initial. + + name = io_color_scheme->get_attribute( name = c_name ). + lo_scheme_children = io_color_scheme->get_children( ). + lo_scheme_iterator = lo_scheme_children->create_iterator( ). + lo_scheme_element ?= lo_scheme_iterator->get_next( ). + while lo_scheme_element is bound. + case lo_scheme_element->get_name( ). + when c_dark1. + dark1 = me->get_color( lo_scheme_element ). + when c_dark2. + dark2 = me->get_color( lo_scheme_element ). + when c_light1. + light1 = me->get_color( lo_scheme_element ). + when c_light2. + light2 = me->get_color( lo_scheme_element ). + when c_accent1. + accent1 = me->get_color( lo_scheme_element ). + when c_accent2. + accent2 = me->get_color( lo_scheme_element ). + when c_accent3. + accent3 = me->get_color( lo_scheme_element ). + when c_accent4. + accent4 = me->get_color( lo_scheme_element ). + when c_accent5. + accent5 = me->get_color( lo_scheme_element ). + when c_accent6. + accent6 = me->get_color( lo_scheme_element ). + when c_hlink. + hlink = me->get_color( lo_scheme_element ). + when c_folhlink. + folhlink = me->get_color( lo_scheme_element ). + endcase. + lo_scheme_element ?= lo_scheme_iterator->get_next( ). + endwhile. + endmethod. "load + + + + + + + method set_color. + field-symbols: <color> type t_color. + check iv_type is not initial. + check iv_srgb is not initial or iv_syscolorname is not initial. + case iv_type. + when c_dark1. + assign dark1 to <color>. + when c_dark2. + assign dark2 to <color>. + when c_light1. + assign light1 to <color>. + when c_light2. + assign light2 to <color>. + when c_accent1. + assign accent1 to <color>. + when c_accent2. + assign accent2 to <color>. + when c_accent3. + assign accent3 to <color>. + when c_accent4. + assign accent4 to <color>. + when c_accent5. + assign accent5 to <color>. + when c_accent6. + assign accent6 to <color>. + when c_hlink. + assign hlink to <color>. + when c_folhlink. + assign folhlink to <color>. + endcase. + check <color> is assigned. + clear <color>. + if iv_srgb is not initial. + <color>-srgb = iv_srgb. + else. + <color>-syscolor-val = iv_syscolorname. + if iv_syscolorlast is not initial. + <color>-syscolor-lastclr = iv_syscolorlast. + else. + <color>-syscolor-lastclr = '000000'. + endif. + endif. + endmethod. "set_color + + + method set_defaults. + name = 'Office'. + dark1-syscolor-val = 'windowText'. + dark1-syscolor-lastclr = '000000'. + light1-syscolor-val = 'window'. + light1-syscolor-lastclr = 'FFFFFF'. + dark2-srgb = '44546A'. + light2-srgb = 'E7E6E6'. + accent1-srgb = '5B9BD5'. + accent2-srgb = 'ED7D31'. + accent3-srgb = 'A5A5A5'. + accent4-srgb = 'FFC000'. + accent5-srgb = '4472C4'. + accent6-srgb = '70AD47'. + hlink-srgb = '0563C1'. + folhlink-srgb = '954F72'. + endmethod. "set_defaults + + + + method set_name. + if strlen( iv_name ) > 50. + name = iv_name(50). + else. + name = iv_name. + endif. + endmethod. "set_name + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + method build_xml. + data: lo_theme_element type ref to if_ixml_element. + data: lo_theme type ref to if_ixml_element. + data: lo_theme_objdef type ref to if_ixml_element. + check io_document is bound. + lo_theme ?= io_document->get_root_element( ). + check lo_theme is bound. + if extracolor is initial. + lo_theme_objdef ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix + name = zcl_excel_theme=>c_theme_extra_color + parent = lo_theme ). + + else. + lo_theme->append_child( new_child = extracolor ). + endif. + + endmethod. "build_xml + + + + method load. + "! so far copy only existing values + extracolor ?= io_extra_color. + endmethod. "load + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + + + + + + + method build_xml. + data: lo_theme_element type ref to if_ixml_element. + data: lo_theme type ref to if_ixml_element. + check io_document is bound. + lo_theme ?= io_document->get_root_element( ).. + if lo_theme is bound. + lo_theme_element ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix + name = c_theme_elements + parent = lo_theme ). + + color_scheme->build_xml( io_document = io_document ). + font_scheme->build_xml( io_document = io_document ). + fmt_scheme->build_xml( io_document = io_document ). + endif. + endmethod. + + + method constructor. + create object color_scheme. + create object font_scheme. + create object fmt_scheme. + endmethod. "constructor + + + + method load. + data: lo_elements_children type ref to if_ixml_node_list. + data: lo_elements_iterator type ref to if_ixml_node_iterator. + data: lo_elements_element type ref to if_ixml_element. + check io_elements is not initial. + + lo_elements_children = io_elements->get_children( ). + lo_elements_iterator = lo_elements_children->create_iterator( ). + lo_elements_element ?= lo_elements_iterator->get_next( ). + while lo_elements_element is bound. + case lo_elements_element->get_name( ). + when c_color_scheme. + color_scheme->load( io_color_scheme = lo_elements_element ). + when c_font_scheme. + font_scheme->load( io_font_scheme = lo_elements_element ). + when c_fmt_scheme. + fmt_scheme->load( io_fmt_scheme = lo_elements_element ). + endcase. + lo_elements_element ?= lo_elements_iterator->get_next( ). + endwhile. + endmethod. "load + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + method build_xml. + data: lo_theme_element type ref to if_ixml_element. + data: lo_theme type ref to if_ixml_element. + data: lo_theme_objdef type ref to if_ixml_element. + check io_document is bound. + + lo_theme ?= io_document->get_root_element( ). + check lo_theme is bound. + if extlst is initial. + lo_theme_objdef ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix + name = zcl_excel_theme=>c_theme_extlst + parent = lo_theme ). + + else. + lo_theme->append_child( new_child = extlst ). + endif. + endmethod. "build_xml + + + + method load. + "! so far copy only existing values + extlst ?= io_extlst. + endmethod. "load + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + method build_xml. + data: lo_xml type ref to cl_xml_document. + data: lo_node type ref to if_ixml_node. + data: default_fmt_scheme type string. + data: lo_scheme_element type ref to if_ixml_element. + data: lo_elements type ref to if_ixml_element. + check io_document is bound. + lo_elements ?= io_document->find_from_name_ns( name = zcl_excel_theme=>c_theme_elements ). + if lo_elements is bound. + + if fmt_scheme is initial. + create object lo_xml. + lo_xml->parse_string( get_default_fmt( ) ). + lo_node = lo_xml->get_first_node( ). + lo_elements->append_child( new_child = lo_node ). + else. + lo_elements->append_child( new_child = fmt_scheme ). + endif. + endif. + endmethod. "build_xml + + + + method get_default_fmt. + concatenate '<a:fmtScheme name="Office">' + ' <a:fillStyleLst>' + ' <a:solidFill>' + ' <a:schemeClr val="phClr"/>' + ' </a:solidFill>' + ' <a:gradFill rotWithShape="1">' + ' <a:gsLst>' + ' <a:gs pos="0">' + ' <a:schemeClr val="phClr">' + ' <a:lumMod val="110000"/>' + ' <a:satMod val="105000"/>' + ' <a:tint val="67000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' <a:gs pos="50000">' + ' <a:schemeClr val="phClr">' + ' <a:lumMod val="105000"/>' + ' <a:satMod val="103000"/>' + ' <a:tint val="73000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' <a:gs pos="100000">' + ' <a:schemeClr val="phClr">' + ' <a:lumMod val="105000"/>' + ' <a:satMod val="109000"/>' + ' <a:tint val="81000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' </a:gsLst>' + ' <a:lin ang="5400000" scaled="0"/>' + ' </a:gradFill>' + ' <a:gradFill rotWithShape="1">' + ' <a:gsLst>' + ' <a:gs pos="0">' + ' <a:schemeClr val="phClr">' + ' <a:satMod val="103000"/>' + ' <a:lumMod val="102000"/>' + ' <a:tint val="94000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' <a:gs pos="50000">' + ' <a:schemeClr val="phClr">' + ' <a:satMod val="110000"/>' + ' <a:lumMod val="100000"/>' + ' <a:shade val="100000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' <a:gs pos="100000">' + ' <a:schemeClr val="phClr">' + ' <a:lumMod val="99000"/>' + ' <a:satMod val="120000"/>' + ' <a:shade val="78000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' </a:gsLst>' + ' <a:lin ang="5400000" scaled="0"/>' + ' </a:gradFill>' + ' </a:fillStyleLst>' + ' <a:lnStyleLst>' + ' <a:ln w="6350" cap="flat" cmpd="sng" algn="ctr">' + ' <a:solidFill>' + ' <a:schemeClr val="phClr"/>' + ' </a:solidFill>' + ' <a:prstDash val="solid"/>' + ' <a:miter lim="800000"/>' + ' </a:ln>' + ' <a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">' + ' <a:solidFill>' + ' <a:schemeClr val="phClr"/>' + ' </a:solidFill>' + ' <a:prstDash val="solid"/>' + ' <a:miter lim="800000"/>' + ' </a:ln>' + ' <a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">' + ' <a:solidFill>' + ' <a:schemeClr val="phClr"/>' + ' </a:solidFill>' + ' <a:prstDash val="solid"/>' + ' <a:miter lim="800000"/>' + ' </a:ln>' + ' </a:lnStyleLst>' + ' <a:effectStyleLst>' + ' <a:effectStyle>' + ' <a:effectLst/>' + ' </a:effectStyle>' + ' <a:effectStyle>' + ' <a:effectLst/>' + ' </a:effectStyle>' + ' <a:effectStyle>' + ' <a:effectLst>' + ' <a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">' + ' <a:srgbClr val="000000">' + ' <a:alpha val="63000"/>' + ' </a:srgbClr>' + ' </a:outerShdw>' + ' </a:effectLst>' + ' </a:effectStyle>' + ' </a:effectStyleLst>' + ' <a:bgFillStyleLst>' + ' <a:solidFill>' + ' <a:schemeClr val="phClr"/>' + ' </a:solidFill>' + ' <a:solidFill>' + ' <a:schemeClr val="phClr">' + ' <a:tint val="95000"/>' + ' <a:satMod val="170000"/>' + ' </a:schemeClr>' + ' </a:solidFill>' + ' <a:gradFill rotWithShape="1">' + ' <a:gsLst>' + ' <a:gs pos="0">' + ' <a:schemeClr val="phClr">' + ' <a:tint val="93000"/>' + ' <a:satMod val="150000"/>' + ' <a:shade val="98000"/>' + ' <a:lumMod val="102000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' <a:gs pos="50000">' + ' <a:schemeClr val="phClr">' + ' <a:tint val="98000"/>' + ' <a:satMod val="130000"/>' + ' <a:shade val="90000"/>' + ' <a:lumMod val="103000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' <a:gs pos="100000">' + ' <a:schemeClr val="phClr">' + ' <a:shade val="63000"/>' + ' <a:satMod val="120000"/>' + ' </a:schemeClr>' + ' </a:gs>' + ' </a:gsLst>' + ' <a:lin ang="5400000" scaled="0"/>' + ' </a:gradFill>' + ' </a:bgFillStyleLst>' + ' </a:fmtScheme>' + into rv_string . + endmethod. "get_default_fmt + + + + method load. + "! so far copy only existing values + fmt_scheme ?= io_fmt_scheme. + endmethod. "load + + + + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + + + + + + + + + + + + + + method build_xml. + data: lo_scheme_element type ref to if_ixml_element. + data: lo_font type ref to if_ixml_element. + data: lo_latin type ref to if_ixml_element. + data: lo_ea type ref to if_ixml_element. + data: lo_cs type ref to if_ixml_element. + data: lo_major type ref to if_ixml_element. + data: lo_minor type ref to if_ixml_element. + data: lo_elements type ref to if_ixml_element. + field-symbols: <font> type t_font. + check io_document is bound. + lo_elements ?= io_document->find_from_name_ns( name = zcl_excel_theme=>c_theme_elements ). + if lo_elements is bound. + lo_scheme_element ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = zcl_excel_theme_elements=>c_font_scheme + parent = lo_elements ). + lo_scheme_element->set_attribute( name = c_name value = font_scheme-name ). + + lo_major ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_major + parent = lo_scheme_element ). + if lo_major is bound. + lo_latin ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_latin + parent = lo_major ). + lo_latin->set_attribute( name = c_typeface value = font_scheme-major-latin-typeface ). + if font_scheme-major-latin-panose is not initial. + lo_latin->set_attribute( name = c_panose value = font_scheme-major-latin-panose ). + endif. + if font_scheme-major-latin-pitchfamily is not initial. + lo_latin->set_attribute( name = c_pitchfamily value = font_scheme-major-latin-pitchfamily ). + endif. + if font_scheme-major-latin-charset is not initial. + lo_latin->set_attribute( name = c_charset value = font_scheme-major-latin-charset ). + endif. + + lo_ea ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_ea + parent = lo_major ). + lo_ea->set_attribute( name = c_typeface value = font_scheme-major-ea-typeface ). + if font_scheme-major-ea-panose is not initial. + lo_ea->set_attribute( name = c_panose value = font_scheme-major-ea-panose ). + endif. + if font_scheme-major-ea-pitchfamily is not initial. + lo_ea->set_attribute( name = c_pitchfamily value = font_scheme-major-ea-pitchfamily ). + endif. + if font_scheme-major-ea-charset is not initial. + lo_ea->set_attribute( name = c_charset value = font_scheme-major-ea-charset ). + endif. + + lo_cs ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_cs + parent = lo_major ). + lo_cs->set_attribute( name = c_typeface value = font_scheme-major-cs-typeface ). + if font_scheme-major-cs-panose is not initial. + lo_cs->set_attribute( name = c_panose value = font_scheme-major-cs-panose ). + endif. + if font_scheme-major-cs-pitchfamily is not initial. + lo_cs->set_attribute( name = c_pitchfamily value = font_scheme-major-cs-pitchfamily ). + endif. + if font_scheme-major-cs-charset is not initial. + lo_cs->set_attribute( name = c_charset value = font_scheme-major-cs-charset ). + endif. + + loop at font_scheme-major-fonts assigning <font>. + if <font>-script is not initial and <font>-typeface is not initial. + clear lo_font. + lo_font ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_font + parent = lo_major ). + lo_font->set_attribute( name = c_script value = <font>-script ). + lo_font->set_attribute( name = c_typeface value = <font>-typeface ). + endif. + endloop. + clear: lo_latin, lo_ea, lo_cs, lo_font. + endif. + + lo_minor ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_minor + parent = lo_scheme_element ). + if lo_minor is bound. + lo_latin ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_latin + parent = lo_minor ). + lo_latin->set_attribute( name = c_typeface value = font_scheme-minor-latin-typeface ). + if font_scheme-minor-latin-panose is not initial. + lo_latin->set_attribute( name = c_panose value = font_scheme-minor-latin-panose ). + endif. + if font_scheme-minor-latin-pitchfamily is not initial. + lo_latin->set_attribute( name = c_pitchfamily value = font_scheme-minor-latin-pitchfamily ). + endif. + if font_scheme-minor-latin-charset is not initial. + lo_latin->set_attribute( name = c_charset value = font_scheme-minor-latin-charset ). + endif. + + lo_ea ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_ea + parent = lo_minor ). + lo_ea->set_attribute( name = c_typeface value = font_scheme-minor-ea-typeface ). + if font_scheme-minor-ea-panose is not initial. + lo_ea->set_attribute( name = c_panose value = font_scheme-minor-ea-panose ). + endif. + if font_scheme-minor-ea-pitchfamily is not initial. + lo_ea->set_attribute( name = c_pitchfamily value = font_scheme-minor-ea-pitchfamily ). + endif. + if font_scheme-minor-ea-charset is not initial. + lo_ea->set_attribute( name = c_charset value = font_scheme-minor-ea-charset ). + endif. + + lo_cs ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_cs + parent = lo_minor ). + lo_cs->set_attribute( name = c_typeface value = font_scheme-minor-cs-typeface ). + if font_scheme-minor-cs-panose is not initial. + lo_cs->set_attribute( name = c_panose value = font_scheme-minor-cs-panose ). + endif. + if font_scheme-minor-cs-pitchfamily is not initial. + lo_cs->set_attribute( name = c_pitchfamily value = font_scheme-minor-cs-pitchfamily ). + endif. + if font_scheme-minor-cs-charset is not initial. + lo_cs->set_attribute( name = c_charset value = font_scheme-minor-cs-charset ). + endif. + + loop at font_scheme-minor-fonts assigning <font>. + if <font>-script is not initial and <font>-typeface is not initial. + clear lo_font. + lo_font ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix name = c_font + parent = lo_minor ). + lo_font->set_attribute( name = c_script value = <font>-script ). + lo_font->set_attribute( name = c_typeface value = <font>-typeface ). + endif. + endloop. + clear: lo_latin, lo_ea, lo_cs, lo_font. + endif. + + + endif. + endmethod. "build_xml + + + method constructor. + set_defaults( ). + endmethod. "constructor + + + + method load. + data: lo_scheme_children type ref to if_ixml_node_list. + data: lo_scheme_iterator type ref to if_ixml_node_iterator. + data: lo_scheme_element type ref to if_ixml_element. + data: lo_major_children type ref to if_ixml_node_list. + data: lo_major_iterator type ref to if_ixml_node_iterator. + data: lo_major_element type ref to if_ixml_element. + data: lo_minor_children type ref to if_ixml_node_list. + data: lo_minor_iterator type ref to if_ixml_node_iterator. + data: lo_minor_element type ref to if_ixml_element. + data: ls_font type t_font. + check io_font_scheme is not initial. + clear font_scheme. + font_scheme-name = io_font_scheme->get_attribute( name = c_name ). + lo_scheme_children = io_font_scheme->get_children( ). + lo_scheme_iterator = lo_scheme_children->create_iterator( ). + lo_scheme_element ?= lo_scheme_iterator->get_next( ). + while lo_scheme_element is bound. + case lo_scheme_element->get_name( ). + when c_major. + lo_major_children = lo_scheme_element->get_children( ). + lo_major_iterator = lo_major_children->create_iterator( ). + lo_major_element ?= lo_major_iterator->get_next( ). + while lo_major_element is bound. + case lo_major_element->get_name( ). + when c_latin. + font_scheme-major-latin-typeface = lo_major_element->get_attribute( name = c_typeface ). + font_scheme-major-latin-panose = lo_major_element->get_attribute( name = c_panose ). + font_scheme-major-latin-pitchfamily = lo_major_element->get_attribute( name = c_pitchfamily ). + font_scheme-major-latin-charset = lo_major_element->get_attribute( name = c_charset ). + when c_ea. + font_scheme-major-ea-typeface = lo_major_element->get_attribute( name = c_typeface ). + font_scheme-major-ea-panose = lo_major_element->get_attribute( name = c_panose ). + font_scheme-major-ea-pitchfamily = lo_major_element->get_attribute( name = c_pitchfamily ). + font_scheme-major-ea-charset = lo_major_element->get_attribute( name = c_charset ). + when c_cs. + font_scheme-major-cs-typeface = lo_major_element->get_attribute( name = c_typeface ). + font_scheme-major-cs-panose = lo_major_element->get_attribute( name = c_panose ). + font_scheme-major-cs-pitchfamily = lo_major_element->get_attribute( name = c_pitchfamily ). + font_scheme-major-cs-charset = lo_major_element->get_attribute( name = c_charset ). + when c_font. + clear ls_font. + ls_font-script = lo_major_element->get_attribute( name = c_script ). + ls_font-typeface = lo_major_element->get_attribute( name = c_typeface ). + try. + insert ls_font into table font_scheme-major-fonts. + catch cx_root. "not the best but just to avoid duplicate lines dump + + endtry. + endcase. + lo_major_element ?= lo_major_iterator->get_next( ). + endwhile. + when c_minor. + lo_minor_children = lo_scheme_element->get_children( ). + lo_minor_iterator = lo_minor_children->create_iterator( ). + lo_minor_element ?= lo_minor_iterator->get_next( ). + while lo_minor_element is bound. + case lo_minor_element->get_name( ). + when c_latin. + font_scheme-minor-latin-typeface = lo_minor_element->get_attribute( name = c_typeface ). + font_scheme-minor-latin-panose = lo_minor_element->get_attribute( name = c_panose ). + font_scheme-minor-latin-pitchfamily = lo_minor_element->get_attribute( name = c_pitchfamily ). + font_scheme-minor-latin-charset = lo_minor_element->get_attribute( name = c_charset ). + when c_ea. + font_scheme-minor-ea-typeface = lo_minor_element->get_attribute( name = c_typeface ). + font_scheme-minor-ea-panose = lo_minor_element->get_attribute( name = c_panose ). + font_scheme-minor-ea-pitchfamily = lo_minor_element->get_attribute( name = c_pitchfamily ). + font_scheme-minor-ea-charset = lo_minor_element->get_attribute( name = c_charset ). + when c_cs. + font_scheme-minor-cs-typeface = lo_minor_element->get_attribute( name = c_typeface ). + font_scheme-minor-cs-panose = lo_minor_element->get_attribute( name = c_panose ). + font_scheme-minor-cs-pitchfamily = lo_minor_element->get_attribute( name = c_pitchfamily ). + font_scheme-minor-cs-charset = lo_minor_element->get_attribute( name = c_charset ). + when c_font. + clear ls_font. + ls_font-script = lo_minor_element->get_attribute( name = c_script ). + ls_font-typeface = lo_minor_element->get_attribute( name = c_typeface ). + try. + insert ls_font into table font_scheme-minor-fonts. + catch cx_root. "not the best but just to avoid duplicate lines dump + + endtry. + endcase. + lo_minor_element ?= lo_minor_iterator->get_next( ). + endwhile. + endcase. + lo_scheme_element ?= lo_scheme_iterator->get_next( ). + endwhile. + endmethod. "load + + + + + + + + method modify_cs_font. + modify_lec_fonts( + exporting + iv_type = iv_type + iv_font_type = c_cs + iv_typeface = iv_typeface + iv_panose = iv_panose + iv_pitchfamily = iv_pitchfamily + iv_charset = iv_charset + ). + endmethod. "modify_latin_font + + + + + + + + method modify_ea_font. + modify_lec_fonts( + exporting + iv_type = iv_type + iv_font_type = c_ea + iv_typeface = iv_typeface + iv_panose = iv_panose + iv_pitchfamily = iv_pitchfamily + iv_charset = iv_charset + ). + endmethod. "modify_latin_font + + + + + + method modify_font. + data: ls_font type t_font. + field-symbols: <font> type t_font. + ls_font-script = iv_script. + ls_font-typeface = iv_typeface. + try. + case iv_type. + when c_major. + read table font_scheme-major-fonts with key script = iv_script assigning <font>. + if sy-subrc eq 0. + <font> = ls_font. + else. + insert ls_font into table font_scheme-major-fonts. + endif. + when c_minor. + read table font_scheme-minor-fonts with key script = iv_script assigning <font>. + if sy-subrc eq 0. + <font> = ls_font. + else. + insert ls_font into table font_scheme-minor-fonts. + endif. + endcase. + catch cx_root. "not the best but just to avoid duplicate lines dump + endtry. + endmethod. "add_font + + + + + + + + method modify_latin_font. + modify_lec_fonts( + exporting + iv_type = iv_type + iv_font_type = c_latin + iv_typeface = iv_typeface + iv_panose = iv_panose + iv_pitchfamily = iv_pitchfamily + iv_charset = iv_charset + ). + endmethod. "modify_latin_font + + + + + + + + + method modify_lec_fonts. + field-symbols: <type> type t_fonts, + <font> type t_fonttype. + case iv_type. + when c_minor. + assign font_scheme-minor to <type>. + when c_major. + assign font_scheme-major to <type>. + when others. + return. + endcase. + check <type> is assigned. + case iv_font_type. + when c_latin. + assign <type>-latin to <font>. + when c_ea. + assign <type>-ea to <font>. + when c_cs. + assign <type>-cs to <font>. + when others. + return. + endcase. + check <font> is assigned. + <font>-typeface = iv_typeface. + <font>-panose = iv_panose. + <font>-pitchfamily = iv_pitchfamily. + <font>-charset = iv_charset. + endmethod. "modify_lec_fonts + + + method set_defaults. + clear font_scheme. + font_scheme-name = 'Office'. + font_scheme-major-latin-typeface = 'Calibri Light'. + font_scheme-major-latin-panose = '020F0302020204030204'. + modify_font( iv_type = c_major iv_script = 'Jpan' iv_typeface = 'MS Pゴシック' ). + modify_font( iv_type = c_major iv_script = 'Hang' iv_typeface = '맑은 고딕' ). + modify_font( iv_type = c_major iv_script = 'Hans' iv_typeface = '宋体' ). + modify_font( iv_type = c_major iv_script = 'Hant' iv_typeface = '新細明體' ). + modify_font( iv_type = c_major iv_script = 'Arab' iv_typeface = 'Times New Roman' ). + modify_font( iv_type = c_major iv_script = 'Hebr' iv_typeface = 'Times New Roman' ). + modify_font( iv_type = c_major iv_script = 'Thai' iv_typeface = 'Tahoma' ). + modify_font( iv_type = c_major iv_script = 'Ethi' iv_typeface = 'Nyala' ). + modify_font( iv_type = c_major iv_script = 'Beng' iv_typeface = 'Vrinda' ). + modify_font( iv_type = c_major iv_script = 'Gujr' iv_typeface = 'Shruti' ). + modify_font( iv_type = c_major iv_script = 'Khmr' iv_typeface = 'MoolBoran' ). + modify_font( iv_type = c_major iv_script = 'Knda' iv_typeface = 'Tunga' ). + modify_font( iv_type = c_major iv_script = 'Guru' iv_typeface = 'Raavi' ). + modify_font( iv_type = c_major iv_script = 'Cans' iv_typeface = 'Euphemia' ). + modify_font( iv_type = c_major iv_script = 'Cher' iv_typeface = 'Plantagenet Cherokee' ). + modify_font( iv_type = c_major iv_script = 'Yiii' iv_typeface = 'Microsoft Yi Baiti' ). + modify_font( iv_type = c_major iv_script = 'Tibt' iv_typeface = 'Microsoft Himalaya' ). + modify_font( iv_type = c_major iv_script = 'Thaa' iv_typeface = 'MV Boli' ). + modify_font( iv_type = c_major iv_script = 'Deva' iv_typeface = 'Mangal' ). + modify_font( iv_type = c_major iv_script = 'Telu' iv_typeface = 'Gautami' ). + modify_font( iv_type = c_major iv_script = 'Taml' iv_typeface = 'Latha' ). + modify_font( iv_type = c_major iv_script = 'Syrc' iv_typeface = 'Estrangelo Edessa' ). + modify_font( iv_type = c_major iv_script = 'Orya' iv_typeface = 'Kalinga' ). + modify_font( iv_type = c_major iv_script = 'Mlym' iv_typeface = 'Kartika' ). + modify_font( iv_type = c_major iv_script = 'Laoo' iv_typeface = 'DokChampa' ). + modify_font( iv_type = c_major iv_script = 'Sinh' iv_typeface = 'Iskoola Pota' ). + modify_font( iv_type = c_major iv_script = 'Mong' iv_typeface = 'Mongolian Baiti' ). + modify_font( iv_type = c_major iv_script = 'Viet' iv_typeface = 'Times New Roman' ). + modify_font( iv_type = c_major iv_script = 'Uigh' iv_typeface = 'Microsoft Uighur' ). + modify_font( iv_type = c_major iv_script = 'Geor' iv_typeface = 'Sylfaen' ). + + font_scheme-minor-latin-typeface = 'Calibri'. + font_scheme-minor-latin-panose = '020F0502020204030204'. + modify_font( iv_type = c_minor iv_script = 'Jpan' iv_typeface = 'MS Pゴシック' ). + modify_font( iv_type = c_minor iv_script = 'Hang' iv_typeface = '맑은 고딕' ). + modify_font( iv_type = c_minor iv_script = 'Hans' iv_typeface = '宋体' ). + modify_font( iv_type = c_minor iv_script = 'Hant' iv_typeface = '新細明體' ). + modify_font( iv_type = c_minor iv_script = 'Arab' iv_typeface = 'Arial' ). + modify_font( iv_type = c_minor iv_script = 'Hebr' iv_typeface = 'Arial' ). + modify_font( iv_type = c_minor iv_script = 'Thai' iv_typeface = 'Tahoma' ). + modify_font( iv_type = c_minor iv_script = 'Ethi' iv_typeface = 'Nyala' ). + modify_font( iv_type = c_minor iv_script = 'Beng' iv_typeface = 'Vrinda' ). + modify_font( iv_type = c_minor iv_script = 'Gujr' iv_typeface = 'Shruti' ). + modify_font( iv_type = c_minor iv_script = 'Khmr' iv_typeface = 'DaunPenh' ). + modify_font( iv_type = c_minor iv_script = 'Knda' iv_typeface = 'Tunga' ). + modify_font( iv_type = c_minor iv_script = 'Guru' iv_typeface = 'Raavi' ). + modify_font( iv_type = c_minor iv_script = 'Cans' iv_typeface = 'Euphemia' ). + modify_font( iv_type = c_minor iv_script = 'Cher' iv_typeface = 'Plantagenet Cherokee' ). + modify_font( iv_type = c_minor iv_script = 'Yiii' iv_typeface = 'Microsoft Yi Baiti' ). + modify_font( iv_type = c_minor iv_script = 'Tibt' iv_typeface = 'Microsoft Himalaya' ). + modify_font( iv_type = c_minor iv_script = 'Thaa' iv_typeface = 'MV Boli' ). + modify_font( iv_type = c_minor iv_script = 'Deva' iv_typeface = 'Mangal' ). + modify_font( iv_type = c_minor iv_script = 'Telu' iv_typeface = 'Gautami' ). + modify_font( iv_type = c_minor iv_script = 'Taml' iv_typeface = 'Latha' ). + modify_font( iv_type = c_minor iv_script = 'Syrc' iv_typeface = 'Estrangelo Edessa' ). + modify_font( iv_type = c_minor iv_script = 'Orya' iv_typeface = 'Kalinga' ). + modify_font( iv_type = c_minor iv_script = 'Mlym' iv_typeface = 'Kartika' ). + modify_font( iv_type = c_minor iv_script = 'Laoo' iv_typeface = 'DokChampa' ). + modify_font( iv_type = c_minor iv_script = 'Sinh' iv_typeface = 'Iskoola Pota' ). + modify_font( iv_type = c_minor iv_script = 'Mong' iv_typeface = 'Mongolian Baiti' ). + modify_font( iv_type = c_minor iv_script = 'Viet' iv_typeface = 'Arial' ). + modify_font( iv_type = c_minor iv_script = 'Uigh' iv_typeface = 'Microsoft Uighur' ). + modify_font( iv_type = c_minor iv_script = 'Geor' iv_typeface = 'Sylfaen' ). + + endmethod. "set_defaults + + + + method set_name. + font_scheme-name = iv_name. + endmethod. "set_name + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes + + + + method build_xml. + data: lo_theme_element type ref to if_ixml_element. + data: lo_theme type ref to if_ixml_element. + data: lo_theme_objdef type ref to if_ixml_element. + check io_document is bound. + lo_theme ?= io_document->get_root_element( ). + check lo_theme is bound. + if objectdefaults is initial. + lo_theme_objdef ?= io_document->create_simple_element_ns( prefix = zcl_excel_theme=>c_theme_prefix + name = zcl_excel_theme=>c_theme_object_def + parent = lo_theme ). + else. + lo_theme->append_child( new_child = objectdefaults ). + endif. + endmethod. "build_xml + + + + method load. + "! so far copy only existing values + objectdefaults ?= io_object_def. + endmethod. "load + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + METHOD create_xl_sharedstrings. +* +* Redefinition using simple transformation instead of CL_IXML +* +** Constant node name + + TYPES: + BEGIN OF ts_root, + count TYPE string, + unique_count TYPE string, + END OF ts_root. + + DATA: + lv_last_allowed_char TYPE char1, + lv_invalid TYPE string. + + DATA: + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: + ls_root TYPE ts_root, + lt_cell_data TYPE zexcel_t_cell_data_unsorted, + ls_shared_string TYPE zexcel_s_shared_string, + lv_sytabix TYPE sytabix. + + FIELD-SYMBOLS: + <sheet_content> TYPE zexcel_s_cell_data. + +********************************************************************** +* STEP 0: Build Regex for invalid characters + CASE cl_abap_char_utilities=>charsize. + WHEN 1.lv_last_allowed_char = cl_abap_conv_in_ce=>uccpi( 255 ). " FF in non-Unicode + WHEN 2.lv_last_allowed_char = cl_abap_conv_in_ce=>uccpi( 65533 )." FFFD in Unicode + ENDCASE. + CONCATENATE '[^\n\t\r -' lv_last_allowed_char ']' INTO lv_invalid. + +********************************************************************** +* STEP 1: Collect strings from each worksheet + + lo_iterator = excel->get_worksheets_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + APPEND LINES OF lo_worksheet->sheet_content TO lt_cell_data. + ENDWHILE. + + DELETE lt_cell_data WHERE cell_formula IS NOT INITIAL " delete formula content + OR data_type NE 's'. " MvC: Only shared strings + + ls_root-count = lines( lt_cell_data ). + CONDENSE ls_root-count. + + SORT lt_cell_data BY cell_value. + DELETE ADJACENT DUPLICATES FROM lt_cell_data COMPARING cell_value. + + ls_root-unique_count = lines( lt_cell_data ). + CONDENSE ls_root-unique_count. + + LOOP AT lt_cell_data ASSIGNING <sheet_content>. + + lv_sytabix = sy-tabix - 1. + MOVE lv_sytabix TO ls_shared_string-string_no. + MOVE <sheet_content>-cell_value TO ls_shared_string-string_value. + REPLACE ALL OCCURRENCES OF REGEX lv_invalid + IN ls_shared_string-string_value WITH ` `. + APPEND ls_shared_string TO shared_strings. + + ENDLOOP. + +********************************************************************** +* STEP 2: Create XML + + CALL TRANSFORMATION zexcel_tr_shared_strings + SOURCE root = ls_root + shared_strings = shared_strings + OPTIONS xml_header = 'full' + RESULT XML ep_content. + + +ENDMETHOD. + + + METHOD create_xl_sheet. +* +* Build Sheet#.xml with Simple Transformation ZEXCEL_TR_SHEET +* +* This is an adaption of ZCL_EXCEL_WRITER_2007. +* Not all features are supported, notably the autofilter settings, +* conditional formatting and sheet protection. +* +* Bug reports to marcus.voncube AT deutschebahn.com +* + TYPES: + lty_bool TYPE c LENGTH 5. + + CONSTANTS: + lc_false TYPE lty_bool VALUE 'false', "#EC NEEDED + lc_true TYPE lty_bool VALUE 'true', + lc_zero TYPE c LENGTH 1 VALUE '0', + lc_one TYPE c LENGTH 1 VALUE '1', + lc_default_col_width TYPE float VALUE '9.10'. + + TYPES: + BEGIN OF lty_column, + min TYPE i, + max TYPE i, + width TYPE float, + hidden TYPE lty_bool, + customwidth TYPE lty_bool, + bestfit TYPE lty_bool, + collapsed TYPE lty_bool, + outlinelevel TYPE i, + style TYPE i, + END OF lty_column, + + BEGIN OF lty_row, + row TYPE i, + index TYPE i, + spans TYPE c LENGTH 11, "12345:12345" + hidden TYPE lty_bool, + customheight TYPE lty_bool, + height TYPE float, + collapsed TYPE lty_bool, + outlinelevel TYPE i, + customformat TYPE lty_bool, + style TYPE i, + END OF lty_row, + + BEGIN OF lty_mergecell, + ref TYPE c LENGTH 21, "AAA1234567:BBB1234567" + END OF lty_mergecell, + + BEGIN OF lty_hyperlink, + ref TYPE string, + location TYPE string, + r_id TYPE string, + END OF lty_hyperlink, + + BEGIN OF lty_table, + r_id TYPE string, + END OF lty_table, + + BEGIN OF lty_table_area, + left TYPE i, + right TYPE i, + top TYPE i, + bottom TYPE i, + END OF lty_table_area, + + BEGIN OF ty_missing_columns, + first_column TYPE zexcel_cell_column, + last_column TYPE zexcel_cell_column, + END OF ty_missing_columns. + +* +* Root node for transformation +* + DATA: + BEGIN OF l_worksheet, + dimension TYPE string, + tabcolor TYPE string, + summarybelow TYPE c, + summaryright TYPE c, + fittopage TYPE c, + showzeros TYPE c, + tabselected TYPE c, + zoomscale TYPE i, + zoomscalenormal TYPE i, + zoomscalepageview TYPE i, + zoomscalesheetview TYPE i, + workbookviewid TYPE c, + showgridlines TYPE c, + showrowcolheaders TYPE c, + activepane TYPE string, + state TYPE string, + ysplit TYPE i, + xsplit TYPE i, + topleftcell TYPE c LENGTH 10, + activecell TYPE c LENGTH 10, + customheight TYPE lty_bool, + defaultrowheight TYPE float, + defaultcolwidth TYPE float, + outlinelevelrow TYPE i, + outlinelevelcol TYPE i, + cols TYPE STANDARD TABLE OF lty_column, + rows TYPE STANDARD TABLE OF lty_row, + mergecells_count TYPE i, + mergecells TYPE STANDARD TABLE OF lty_mergecell, + hyperlinks_count TYPE i, + hyperlinks TYPE STANDARD TABLE OF lty_hyperlink, + BEGIN OF printoptions, + gridlines TYPE lty_bool, + horizontalcentered TYPE lty_bool, + verticalcentered TYPE lty_bool, + END OF printoptions, + BEGIN OF pagemargins, + left TYPE zexcel_dec_8_2, + right TYPE zexcel_dec_8_2, + top TYPE zexcel_dec_8_2, + bottom TYPE zexcel_dec_8_2, + header TYPE zexcel_dec_8_2, + footer TYPE zexcel_dec_8_2, + END OF pagemargins, + BEGIN OF pagesetup, + blackandwhite TYPE c, + cellcomments TYPE string, + copies TYPE i, + draft TYPE c, + errors TYPE string, + firstpagenumber TYPE i, + fittopage TYPE c, + fittoheight TYPE i, + fittowidth TYPE i, + horizontaldpi TYPE i, + orientation TYPE string, + pageorder TYPE string, + paperheight TYPE string, + papersize TYPE i, + paperwidth TYPE string, + scale TYPE i, + usefirstpagenumber TYPE c, + useprinterdefaults TYPE c, + verticaldpi TYPE i, + END OF pagesetup, + BEGIN OF headerfooter, + differentoddeven TYPE c, + oddheader TYPE string, + oddfooter TYPE string, + evenheader TYPE string, + evenfooter TYPE string, + END OF headerfooter, + drawings TYPE string, + tables_count TYPE i, + tables TYPE STANDARD TABLE OF lty_table, + END OF l_worksheet. + +* +* Local data +* + DATA: + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + default_col_dimension TYPE REF TO zcl_excel_worksheet_columndime, + default_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + lv_value TYPE string, + lv_index TYPE i, + lv_spans TYPE string, + lt_range_merge TYPE string_table, + lv_column TYPE zexcel_cell_column, + lv_style_guid TYPE zexcel_cell_style, + ls_last_row TYPE zexcel_s_cell_data, + lv_freeze_cell_row TYPE zexcel_cell_row, + lv_freeze_cell_column TYPE zexcel_cell_column, + lv_freeze_cell_column_alpha TYPE zexcel_cell_column_alpha, + column_dimensions TYPE zexcel_t_worksheet_columndime, + row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + lv_relation_id TYPE i VALUE 0, + outline_level_row TYPE i VALUE 0, + outline_level_col TYPE i VALUE 0, + col_count TYPE int4, + lt_table_areas TYPE SORTED TABLE OF lty_table_area + WITH NON-UNIQUE KEY left right top bottom, + ls_table_area LIKE LINE OF lt_table_areas, + lts_sorted_columns TYPE SORTED TABLE OF zexcel_cell_column + WITH UNIQUE KEY table_line, + t_missing_columns TYPE STANDARD TABLE OF ty_missing_columns + WITH NON-UNIQUE DEFAULT KEY, + missing_column LIKE LINE OF t_missing_columns, + lo_link TYPE REF TO zcl_excel_hyperlink, + lo_drawings TYPE REF TO zcl_excel_drawings. + + FIELD-SYMBOLS: + <sheet_content> TYPE zexcel_s_cell_data, + <range_merge> LIKE LINE OF lt_range_merge, + <column_dimension> TYPE zexcel_s_worksheet_columndime, + <row_dimension> TYPE zexcel_s_worksheet_rowdimensio, + <col> TYPE lty_column, + <row> TYPE lty_row, + <hyperlink> TYPE lty_hyperlink, + <mergecell> TYPE lty_mergecell, + <table> TYPE lty_table. + +********************************************************************** +* STEP 1: Fill root node +* + l_worksheet-tabcolor = io_worksheet->tabcolor-rgb. + l_worksheet-summarybelow = io_worksheet->zif_excel_sheet_properties~summarybelow. + l_worksheet-summaryright = io_worksheet->zif_excel_sheet_properties~summaryright. + + IF io_worksheet->sheet_setup->fit_to_page IS NOT INITIAL. + l_worksheet-fittopage = lc_one. + ENDIF. + + l_worksheet-dimension = io_worksheet->get_dimension_range( ). + + IF io_worksheet->zif_excel_sheet_properties~show_zeros EQ abap_true. + l_worksheet-showzeros = lc_one. + ELSE. + l_worksheet-showzeros = lc_zero. + ENDIF. + + IF iv_active = abap_true + OR io_worksheet->zif_excel_sheet_properties~selected EQ abap_true. + l_worksheet-tabselected = lc_one. + ELSE. + l_worksheet-tabselected = lc_zero. + ENDIF. + + IF io_worksheet->zif_excel_sheet_properties~zoomscale GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale = 10. + ENDIF. + l_worksheet-zoomscale = io_worksheet->zif_excel_sheet_properties~zoomscale. + + IF io_worksheet->zif_excel_sheet_properties~zoomscale_normal NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_normal GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_normal = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_normal LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_normal = 10. + ENDIF. + l_worksheet-zoomscalenormal = io_worksheet->zif_excel_sheet_properties~zoomscale_normal. + ENDIF. + + IF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview = 10. + ENDIF. + l_worksheet-zoomscalepageview = io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview. + ENDIF. + + IF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview = 10. + ENDIF. + l_worksheet-zoomscalesheetview = io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview. + ENDIF. + + l_worksheet-workbookviewid = lc_zero. + + IF io_worksheet->show_gridlines = abap_true. + l_worksheet-showgridlines = lc_one. + ELSE. + l_worksheet-showgridlines = lc_zero. + ENDIF. + + IF io_worksheet->show_rowcolheaders = abap_true. + l_worksheet-showrowcolheaders = lc_one. + ELSE. + l_worksheet-showrowcolheaders = lc_zero. + ENDIF. + +* +* Freeze +* + io_worksheet->get_freeze_cell( + IMPORTING ep_row = lv_freeze_cell_row + ep_column = lv_freeze_cell_column ). + + IF lv_freeze_cell_row IS NOT INITIAL AND lv_freeze_cell_column IS NOT INITIAL. + IF lv_freeze_cell_row > 1. + l_worksheet-ysplit = lv_freeze_cell_row - 1. + ENDIF. + + IF lv_freeze_cell_column > 1. + lv_value = lv_freeze_cell_column - 1. + l_worksheet-xsplit = lv_freeze_cell_row - 1. + ENDIF. + + lv_freeze_cell_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column = lv_freeze_cell_column ). + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_freeze_cell_row ). + CONCATENATE lv_freeze_cell_column_alpha lv_value INTO lv_value. + l_worksheet-topleftcell = lv_value. + + l_worksheet-activepane = 'bottomRight'. + l_worksheet-state = 'frozen'. + ENDIF. + + l_worksheet-activecell = io_worksheet->get_active_cell( ). + +* +* Row and column info +* + column_dimensions[] = io_worksheet->get_column_dimensions( ). + row_dimensions[] = io_worksheet->get_row_dimensions( ). + + IF NOT column_dimensions IS INITIAL. + io_worksheet->calculate_column_widths( ). + column_dimensions[] = io_worksheet->get_column_dimensions( ). + ENDIF. + + default_row_dimension = io_worksheet->get_default_row_dimension( ). + IF default_row_dimension IS BOUND. + IF default_row_dimension->get_row_height( ) >= 0. + l_worksheet-customheight = lc_true. + lv_value = default_row_dimension->get_row_height( ). + ELSE. + lv_value = '12.75'. + ENDIF. + ELSE. + lv_value = '12.75'. + ENDIF. + CONDENSE lv_value. + l_worksheet-defaultrowheight = lv_value. + + default_col_dimension = io_worksheet->get_default_column_dimension( ). + IF default_col_dimension IS BOUND. + IF default_col_dimension->get_width( ) >= 0. + l_worksheet-defaultcolwidth = default_col_dimension->get_width( ). + ENDIF. + ENDIF. + + LOOP AT row_dimensions ASSIGNING <row_dimension>. + IF <row_dimension>-row_dimension->get_outline_level( ) > outline_level_row. + l_worksheet-outlinelevelrow = <row_dimension>-row_dimension->get_outline_level( ). + ENDIF. + ENDLOOP. + + LOOP AT column_dimensions ASSIGNING <column_dimension>. + IF <column_dimension>-column_dimension->get_outline_level( ) > outline_level_col. + l_worksheet-outlinelevelcol = <column_dimension>-column_dimension->get_outline_level( ). + ENDIF. + ENDLOOP. + +* +* Set column information (width, style, ...) +* + LOOP AT column_dimensions ASSIGNING <column_dimension>. + APPEND INITIAL LINE TO l_worksheet-cols ASSIGNING <col>. + <col>-min = <col>-max = <column_dimension>-column_dimension->get_column_index( ). + <col>-width = <column_dimension>-column_dimension->get_width( ). + IF <col>-width < 0. + <col>-width = lc_default_col_width. + ENDIF. + IF <column_dimension>-column_dimension->get_visible( ) = abap_false. + <col>-hidden = lc_true. + ENDIF. + IF <column_dimension>-column_dimension->get_auto_size( ) = abap_true. + <col>-bestfit = lc_true. + ENDIF. + IF default_col_dimension IS BOUND. + IF <column_dimension>-column_dimension->get_width( ) + <> default_col_dimension->get_width( ). + <col>-customwidth = lc_true. + ENDIF. + ELSE. + <col>-customwidth = lc_true. + ENDIF. + IF <column_dimension>-column_dimension->get_collapsed( ) = abap_true. + <col>-collapsed = lc_true. + ENDIF. + <col>-outlinelevel = <column_dimension>-column_dimension->get_outline_level( ). + lv_style_guid = <column_dimension>-column_dimension->get_column_style_guid( ). + <col>-style = me->excel->get_style_index_in_styles( lv_style_guid ) - 1. + ENDLOOP. + +* +* Missing columns +* +* First collect columns that were already handled before. +* The rest has to be inserted now. +* + LOOP AT column_dimensions ASSIGNING <column_dimension>. + lv_column = zcl_excel_common=>convert_column2int( <column_dimension>-column ). + INSERT lv_column INTO TABLE lts_sorted_columns. + ENDLOOP. + +* +* Now find all columns that were missing so far +* + missing_column-first_column = 1. + + LOOP AT lts_sorted_columns INTO lv_column. + IF lv_column > missing_column-first_column. + missing_column-last_column = lv_column - 1. + APPEND missing_column TO t_missing_columns. + ENDIF. + missing_column-first_column = lv_column + 1. + ENDLOOP. + + missing_column-last_column = zcl_excel_common=>c_excel_sheet_max_col. + APPEND missing_column TO t_missing_columns. + +* +* Now apply stylesetting and other defaults +* + LOOP AT t_missing_columns INTO missing_column. + APPEND INITIAL LINE TO l_worksheet-cols ASSIGNING <col>. + <col>-min = missing_column-first_column. + <col>-max = missing_column-last_column. + IF default_col_dimension IS BOUND AND default_col_dimension->get_width( ) >= 0. + <col>-width = default_col_dimension->get_width( ). + ELSE. + <col>-width = lc_default_col_width. + ENDIF. + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + <col>-style = me->excel->get_style_index_in_styles( lv_style_guid ) - 1. + ENDLOOP. + +* +* Build table to hold all table-areas attached to this sheet +* + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ls_table_area-left = zcl_excel_common=>convert_column2int( lo_table->settings-top_left_column ). + ls_table_area-right = lo_table->get_right_column_integer( ). + ls_table_area-top = lo_table->settings-top_left_row. + ls_table_area-bottom = lo_table->get_bottom_row_integer( ). + INSERT ls_table_area INTO TABLE lt_table_areas. + ENDWHILE. + +* +* Build sheet data node +* +* Spans is constant amongst all rows +* + col_count = io_worksheet->get_highest_column( ). + lv_spans = col_count. + CONCATENATE '1:' lv_spans INTO lv_spans. + CONDENSE lv_spans. + + LOOP AT io_worksheet->sheet_content ASSIGNING <sheet_content>. + + IF ls_last_row-cell_row NE <sheet_content>-cell_row. +* +* Fill row information. +* Cell data is filled in by callback GET_CELLS called from transformation +* + lv_index = sy-tabix. + APPEND INITIAL LINE TO l_worksheet-rows ASSIGNING <row>. + <row>-row = <sheet_content>-cell_row. + <row>-index = lv_index. + <row>-spans = lv_spans. + +* +* Row dimension attributes +* + row_dimension = io_worksheet->get_row_dimension( <sheet_content>-cell_row ). + IF row_dimension->get_visible( ) = abap_false. + <row>-hidden = lc_true. + ENDIF. + + IF row_dimension->get_row_height( ) >= 0. + <row>-customheight = lc_one. + <row>-height = row_dimension->get_row_height( ). + ENDIF. + +* +* Collapsed +* + IF row_dimension->get_collapsed( ) = abap_true. + <row>-collapsed = lc_true. + ENDIF. + +* +* Outline level +* + <row>-outlinelevel = row_dimension->get_outline_level( ). + +* +* Style +* + <row>-style = row_dimension->get_xf_index( ). + IF <row>-style <> 0. + <row>-customformat = lc_one. + ENDIF. + ENDIF. + + ls_last_row = <sheet_content>. + ENDLOOP. + +* +* Merged cells +* + lt_range_merge = io_worksheet->get_merge( ). + IF lt_range_merge IS NOT INITIAL. + l_worksheet-mergecells_count = lines( lt_range_merge ). + + LOOP AT lt_range_merge ASSIGNING <range_merge>. + APPEND INITIAL LINE TO l_worksheet-mergecells ASSIGNING <mergecell>. + <mergecell>-ref = <range_merge>. + io_worksheet->delete_merge( ). + ENDLOOP. + ENDIF. + +* +* Hyperlinks +* + l_worksheet-hyperlinks_count = io_worksheet->get_hyperlinks_size( ). + IF l_worksheet-hyperlinks_count > 0. + lo_iterator = io_worksheet->get_hyperlinks_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_link ?= lo_iterator->if_object_collection_iterator~get_next( ). + + APPEND INITIAL LINE TO l_worksheet-hyperlinks ASSIGNING <hyperlink>. + <hyperlink>-ref = lo_link->get_ref( ). + IF lo_link->is_internal( ) = abap_true. + <hyperlink>-location = lo_link->get_url( ). + ELSE. + ADD 1 TO lv_relation_id. + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + <hyperlink>-r_id = lv_value. + ENDIF. + ENDWHILE. + ENDIF. + +* +* Print options +* + IF io_worksheet->print_gridlines = abap_true. + l_worksheet-printoptions-gridlines = lc_true. + ENDIF. + + IF io_worksheet->sheet_setup->horizontal_centered = abap_true. + l_worksheet-printoptions-horizontalcentered = lc_true. + ENDIF. + + IF io_worksheet->sheet_setup->vertical_centered = abap_true. + l_worksheet-printoptions-verticalcentered = lc_true. + ENDIF. + +* +* Page margins +* + l_worksheet-pagemargins-left = io_worksheet->sheet_setup->margin_left. + l_worksheet-pagemargins-right = io_worksheet->sheet_setup->margin_right. + l_worksheet-pagemargins-top = io_worksheet->sheet_setup->margin_top. + l_worksheet-pagemargins-bottom = io_worksheet->sheet_setup->margin_bottom. + l_worksheet-pagemargins-header = io_worksheet->sheet_setup->margin_header. + l_worksheet-pagemargins-footer = io_worksheet->sheet_setup->margin_footer. + +* +* Page setup +* + l_worksheet-pagesetup-cellcomments = io_worksheet->sheet_setup->cell_comments. + l_worksheet-pagesetup-copies = io_worksheet->sheet_setup->copies. + l_worksheet-pagesetup-firstpagenumber = io_worksheet->sheet_setup->first_page_number. + l_worksheet-pagesetup-fittopage = io_worksheet->sheet_setup->fit_to_page. + l_worksheet-pagesetup-fittoheight = io_worksheet->sheet_setup->fit_to_height. + l_worksheet-pagesetup-fittowidth = io_worksheet->sheet_setup->fit_to_width. + l_worksheet-pagesetup-horizontaldpi = io_worksheet->sheet_setup->horizontal_dpi. + l_worksheet-pagesetup-orientation = io_worksheet->sheet_setup->orientation. + l_worksheet-pagesetup-pageorder = io_worksheet->sheet_setup->page_order. + l_worksheet-pagesetup-paperheight = io_worksheet->sheet_setup->paper_height. + l_worksheet-pagesetup-papersize = io_worksheet->sheet_setup->paper_size. + l_worksheet-pagesetup-paperwidth = io_worksheet->sheet_setup->paper_width. + l_worksheet-pagesetup-scale = io_worksheet->sheet_setup->scale. + l_worksheet-pagesetup-usefirstpagenumber = io_worksheet->sheet_setup->use_first_page_num. + l_worksheet-pagesetup-verticaldpi = io_worksheet->sheet_setup->vertical_dpi. + + IF io_worksheet->sheet_setup->black_and_white IS NOT INITIAL. + l_worksheet-pagesetup-blackandwhite = lc_one. + ENDIF. + + IF io_worksheet->sheet_setup->draft IS NOT INITIAL. + l_worksheet-pagesetup-draft = lc_one. + ENDIF. + + IF io_worksheet->sheet_setup->errors IS NOT INITIAL. + l_worksheet-pagesetup-errors = io_worksheet->sheet_setup->errors. + ENDIF. + + IF io_worksheet->sheet_setup->use_printer_defaults IS NOT INITIAL. + l_worksheet-pagesetup-useprinterdefaults = lc_one. + ENDIF. + +* +* Header and footer +* + IF io_worksheet->sheet_setup->diff_oddeven_headerfooter = abap_true. + l_worksheet-headerfooter-differentoddeven = lc_one. + ENDIF. + + io_worksheet->sheet_setup->get_header_footer_string( + IMPORTING + ep_odd_header = l_worksheet-headerfooter-oddheader + ep_odd_footer = l_worksheet-headerfooter-oddfooter + ep_even_header = l_worksheet-headerfooter-evenheader + ep_even_footer = l_worksheet-headerfooter-evenfooter ). + +* +* Drawings +* + lo_drawings = io_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + ADD 1 TO lv_relation_id. + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO l_worksheet-drawings. + ENDIF. + +* +* Tables +* + l_worksheet-tables_count = io_worksheet->get_tables_size( ). + IF l_worksheet-tables_count > 0. + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + APPEND INITIAL LINE TO l_worksheet-tables ASSIGNING <table>. + ADD 1 TO lv_relation_id. + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO <table>-r_id. + ENDWHILE. + ENDIF. + +********************************************************************** +* STEP 2: Create XML + + me->worksheet = io_worksheet. "Neccessary for callback GET_CELL + + CALL TRANSFORMATION zexcel_tr_sheet + SOURCE worksheet = l_worksheet + cells = me->cells + writer = me + OPTIONS xml_header = 'full' + RESULT XML ep_content. + +ENDMETHOD. "CREATE_XL_SHEET + + + + + METHOD get_cells. +* +* Callback method from transformation ZEXCEL_TR_SHEET +* +* The method fills the data cells for each row. +* This saves memory if there are many rows. +* + DATA: + lv_cell_style TYPE zexcel_cell_style. + + FIELD-SYMBOLS: + <cell> TYPE ty_cell, + <content> TYPE zexcel_s_cell_data, + <style> TYPE zexcel_s_styles_mapping. + + CLEAR cells. + + LOOP AT worksheet->sheet_content FROM i_index ASSIGNING <content>. + IF <content>-cell_row <> i_row. +* +* End of row +* + EXIT. + ENDIF. + +* +* Determine style index +* + IF lv_cell_style <> <content>-cell_style. + lv_cell_style = <content>-cell_style. + UNASSIGN <style>. + IF lv_cell_style IS NOT INITIAL. + READ TABLE styles_mapping ASSIGNING <style> WITH KEY guid = lv_cell_style. + ENDIF. + ENDIF. +* +* Add a new cell +* + APPEND INITIAL LINE TO cells ASSIGNING <cell>. + <cell>-name = <content>-cell_coords. + <cell>-formula = <content>-cell_formula. + <cell>-type = <content>-data_type. + IF <cell>-type = 's'. + <cell>-value = me->get_shared_string_index( <content>-cell_value ). + ELSE. + <cell>-value = <content>-cell_value. + ENDIF. + IF <style> IS ASSIGNED. + <cell>-style = <style>-style. + ELSE. + <cell>-style = -1. + ENDIF. + + ENDLOOP. + +ENDMETHOD. + + + + + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + METHOD constructor. + worksheet = io_sheet. +ENDMETHOD. + + + + + METHOD get_column_filter. + + DATA: ls_filter LIKE LINE OF me->mt_filters. + + READ TABLE me->mt_filters REFERENCE INTO rr_filter WITH TABLE KEY column = i_column. + IF sy-subrc <> 0. + ls_filter-column = i_column. + INSERT ls_filter INTO TABLE me->mt_filters REFERENCE INTO rr_filter. + ENDIF. + +ENDMETHOD. + + + + METHOD get_filter_area. + + validate_area( ). + + rs_area = filter_area. + +ENDMETHOD. + + + + METHOD get_filter_range. + DATA: l_row_start_c TYPE string, + l_row_end_c TYPE string, + l_col_start_c TYPE string, + l_col_end_c TYPE string, + l_value TYPE string. + + validate_area( ). + + l_row_end_c = filter_area-row_end. + CONDENSE l_row_end_c NO-GAPS. + + l_row_start_c = filter_area-row_start. + CONDENSE l_row_start_c NO-GAPS. + + l_col_start_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_start ) . + l_col_end_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_end ) . + + CONCATENATE l_col_start_c l_row_start_c ':' l_col_end_c l_row_end_c INTO r_range. + +ENDMETHOD. + + + + METHOD get_filter_reference. + DATA: l_row_start_c TYPE string, + l_row_end_c TYPE string, + l_col_start_c TYPE string, + l_col_end_c TYPE string, + l_value TYPE string. + + validate_area( ). + + l_row_end_c = filter_area-row_end. + CONDENSE l_row_end_c NO-GAPS. + + l_row_start_c = filter_area-row_start. + CONDENSE l_row_start_c NO-GAPS. + + l_col_start_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_start ) . + l_col_end_c = zcl_excel_common=>convert_column2alpha( ip_column = filter_area-col_end ) . + l_value = worksheet->get_title( ) . + + r_ref = zcl_excel_common=>escape_string( ip_value = l_value ). + + CONCATENATE r_ref '!$' l_col_start_c '$' l_row_start_c ':$' l_col_end_c '$' l_row_end_c INTO r_ref. + +ENDMETHOD. + + + + METHOD get_values. + + FIELD-SYMBOLS: <ls_filter> LIKE LINE OF me->mt_filters, + <ls_value> LIKE LINE OF <ls_filter>-t_values. + + DATA: ls_filter LIKE LINE OF rt_filter. + + LOOP AT me->mt_filters ASSIGNING <ls_filter> WHERE rule = mc_filter_rule_single_values. + + ls_filter-column = <ls_filter>-column. + LOOP AT <ls_filter>-t_values ASSIGNING <ls_value>. + ls_filter-value = <ls_value>. + APPEND ls_filter TO rt_filter. + ENDLOOP. + + ENDLOOP. + +ENDMETHOD. + + + + + METHOD is_row_hidden. + + + DATA: lr_filter TYPE REF TO ts_filter, + lv_col TYPE i, + ls_value TYPE zexcel_s_autofilter_values. + + FIELD-SYMBOLS: <ls_filter> TYPE ts_filter. + + rv_is_hidden = abap_false. + +*--------------------------------------------------------------------* +* 1st row of filter area is never hidden, because here the filter +* symbol is being shown +*--------------------------------------------------------------------* + IF iv_row = me->filter_area-row_start. + RETURN. + ENDIF. + + + lv_col = me->filter_area-col_start. + + + WHILE lv_col <= me->filter_area-col_end. + + lr_filter = me->get_column_filter( lv_col ). + ASSIGN lr_filter->* TO <ls_filter>. + + CASE <ls_filter>-rule. + + WHEN mc_filter_rule_single_values. + rv_is_hidden = me->is_row_hidden_single_values( iv_row = iv_row + iv_col = lv_col + is_filter = <ls_filter> ). + + WHEN mc_filter_rule_text_pattern. + rv_is_hidden = me->is_row_hidden_text_pattern( iv_row = iv_row + iv_col = lv_col + is_filter = <ls_filter> ). + + ENDCASE. + + IF rv_is_hidden = abap_true. + RETURN. + ENDIF. + + + ADD 1 TO lv_col. + + ENDWHILE. + + +ENDMETHOD. + + + + + + + METHOD is_row_hidden_single_values. + + + DATA: lv_value TYPE string. + + FIELD-SYMBOLS: <ls_sheet_content> LIKE LINE OF me->worksheet->sheet_content. + + rv_is_hidden = abap_false. " Default setting is NOT HIDDEN = is in filter range + +*--------------------------------------------------------------------* +* No filter values --> only symbol should be shown but nothing is being hidden +*--------------------------------------------------------------------* + IF is_filter-t_values IS INITIAL. + RETURN. + ENDIF. + +*--------------------------------------------------------------------* +* Get value of cell +*--------------------------------------------------------------------* + READ TABLE me->worksheet->sheet_content ASSIGNING <ls_sheet_content> WITH TABLE KEY cell_row = iv_row + cell_column = iv_col. + IF sy-subrc = 0. + lv_value = <ls_sheet_content>-cell_value. + ELSE. + CLEAR lv_value. + ENDIF. + +*--------------------------------------------------------------------* +* Check whether it is affected by filter +* this needs to be extended if we support other filtertypes +* other than single values +*--------------------------------------------------------------------* + READ TABLE is_filter-t_values TRANSPORTING NO FIELDS WITH TABLE KEY table_line = lv_value. + IF sy-subrc <> 0. + rv_is_hidden = abap_true. + RETURN. + ENDIF. + +ENDMETHOD. + + + + + + + METHOD is_row_hidden_text_pattern. + + + + DATA: lv_value TYPE string. + + FIELD-SYMBOLS: <ls_sheet_content> LIKE LINE OF me->worksheet->sheet_content. + + rv_is_hidden = abap_false. " Default setting is NOT HIDDEN = is in filter range + +*--------------------------------------------------------------------* +* Get value of cell +*--------------------------------------------------------------------* + READ TABLE me->worksheet->sheet_content ASSIGNING <ls_sheet_content> WITH TABLE KEY cell_row = iv_row + cell_column = iv_col. + IF sy-subrc = 0. + lv_value = <ls_sheet_content>-cell_value. + ELSE. + CLEAR lv_value. + ENDIF. + +*--------------------------------------------------------------------* +* Check whether it is affected by filter +* this needs to be extended if we support other filtertypes +* other than single values +*--------------------------------------------------------------------* + IF lv_value NOT IN is_filter-tr_textfilter1. + rv_is_hidden = abap_true. + RETURN. + ENDIF. + +ENDMETHOD. + + + + METHOD set_filter_area. + + filter_area = is_area. + +ENDMETHOD. + + + + + + + METHOD set_text_filter. +* see method documentation how to use this + + DATA: lr_filter TYPE REF TO ts_filter, + ls_value1 TYPE LINE OF ts_filter-tr_textfilter1. + + FIELD-SYMBOLS: <ls_filter> TYPE ts_filter. + + + lr_filter = me->get_column_filter( i_column ). + ASSIGN lr_filter->* TO <ls_filter>. + + <ls_filter>-rule = mc_filter_rule_text_pattern. + CLEAR <ls_filter>-tr_textfilter1. + + IF iv_textfilter1 CA '*+'. " Pattern + ls_value1-sign = 'I'. + ls_value1-option = 'CP'. + ls_value1-low = iv_textfilter1. + ELSE. + ls_value1-sign = 'I'. + ls_value1-option = 'EQ'. + ls_value1-low = iv_textfilter1. + ENDIF. + APPEND ls_value1 TO <ls_filter>-tr_textfilter1. + +ENDMETHOD. + + + + + + + + + + + + + + + + + + + + + + + + METHOD set_value. + + DATA: lr_filter TYPE REF TO ts_filter, + ls_value TYPE zexcel_s_autofilter_values. + + FIELD-SYMBOLS: <ls_filter> TYPE ts_filter. + + + lr_filter = me->get_column_filter( i_column ). + ASSIGN lr_filter->* TO <ls_filter>. + + <ls_filter>-rule = mc_filter_rule_single_values. + + INSERT i_value INTO TABLE <ls_filter>-t_values. + +ENDMETHOD. + + + + METHOD set_values. + + FIELD-SYMBOLS: <ls_value> LIKE LINE OF it_values. + + LOOP AT it_values ASSIGNING <ls_value>. + + me->set_value( i_column = <ls_value>-column + i_value = <ls_value>-value ). + + ENDLOOP. + +ENDMETHOD. + + + METHOD validate_area. + DATA: l_col TYPE zexcel_cell_column, + l_row TYPE zexcel_cell_row. + + l_row = worksheet->get_highest_row( ) . + l_col = worksheet->get_highest_column( ) . + + IF filter_area IS INITIAL. + filter_area-row_start = 1. + filter_area-col_start = 1. + filter_area-row_end = l_row . + filter_area-col_end = l_col . + ENDIF. + + IF filter_area-row_start < 1. + filter_area-row_start = 1. + ENDIF. + IF filter_area-col_start < 1. + filter_area-col_start = 1. + ENDIF. + IF filter_area-row_end > l_row OR + filter_area-row_end < 1. + filter_area-row_end = l_row. + ENDIF. + IF filter_area-col_end > l_col OR + filter_area-col_end < 1. + filter_area-col_end = l_col. + ENDIF. + IF filter_area-row_start >= filter_area-row_end. + filter_area-row_start = filter_area-row_end - 1. + IF filter_area-row_start < 1. + filter_area-row_start = 1. + filter_area-row_end = 2. + ENDIF. + ENDIF. + IF filter_area-col_start > filter_area-col_end. + filter_area-col_start = filter_area-col_end. + ENDIF. +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + ranges->add( ip_range ). + endmethod. + + + method CLEAR. + ranges->clear( ). + endmethod. + + + method CONSTRUCTOR. + + + CREATE OBJECT ranges. + + endmethod. + + + + + method GET. + eo_range ?= ranges->if_object_collection~get( ip_index ). + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= ranges->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = ranges->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + ranges->remove( ip_range ). + endmethod. + + + + method SIZE. + ep_size = ranges->if_object_collection~size( ). + endmethod. + + + + + + + + + + + + + + + + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + TYPES: BEGIN OF t_relationship, + id TYPE string, + type TYPE string, + target TYPE string, + END OF t_relationship. + +* + CLASS lcl_abap_zip_archive DEFINITION + INHERITING FROM lcl_zip_archive + CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS create + IMPORTING i_data TYPE xstring + RETURNING value(r_zip) TYPE REF TO lcl_zip_archive + RAISING zcx_excel. + METHODS read REDEFINITION. + PRIVATE SECTION. + DATA: abap_zip TYPE REF TO cl_abap_zip. + METHODS constructor IMPORTING i_data TYPE xstring + RAISING zcx_excel. + ENDCLASS. "lcl_abap_zip_archive DEFINITION + +* + CLASS lcl_alternate_zip_archive DEFINITION + INHERITING FROM lcl_zip_archive + CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS create + IMPORTING i_data TYPE xstring + i_alternate_zip_class TYPE seoclsname + RETURNING value(r_zip) TYPE REF TO lcl_zip_archive + RAISING zcx_excel. + METHODS read REDEFINITION. + PRIVATE SECTION. + DATA: alternate_zip TYPE REF TO object. + METHODS constructor + IMPORTING i_data TYPE xstring + i_alternate_zip_class TYPE seoclsname + RAISING zcx_excel. + ENDCLASS. "lcl_alternate_zip_archive DEFINITION + +* + CLASS lcl_abap_zip_archive IMPLEMENTATION. + METHOD create. + CREATE OBJECT r_zip TYPE lcl_abap_zip_archive + EXPORTING + i_data = i_data. + ENDMETHOD. "create + METHOD constructor. + DATA: lv_errormessage TYPE string. + super->constructor( ). + CREATE OBJECT abap_zip. + abap_zip->load( + EXPORTING + zip = i_data + EXCEPTIONS + zip_parse_error = 1 + OTHERS = 2 ). + IF sy-subrc <> 0. + lv_errormessage = 'ZIP parse error'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "constructor + METHOD read. + DATA: lv_errormessage TYPE string. + CALL METHOD abap_zip->get + EXPORTING + name = i_filename + IMPORTING + content = r_content + EXCEPTIONS + zip_index_error = 1 + zip_decompression_error = 2 + OTHERS = 3. + IF sy-subrc <> 0. + lv_errormessage = 'File not found in zip-archive'(003). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "read + ENDCLASS. "lcl_abap_zip_archive IMPLEMENTATION + +* + CLASS lcl_alternate_zip_archive IMPLEMENTATION. + METHOD create. + CREATE OBJECT r_zip TYPE lcl_alternate_zip_archive + EXPORTING + i_alternate_zip_class = i_alternate_zip_class + i_data = i_data. + ENDMETHOD. "create + METHOD constructor. + DATA: lv_errormessage TYPE string. + super->constructor( ). + CREATE OBJECT alternate_zip TYPE (i_alternate_zip_class). + TRY. + CALL METHOD alternate_zip->('LOAD') + EXPORTING + zip = i_data + EXCEPTIONS + zip_parse_error = 1 + OTHERS = 2. + CATCH cx_sy_dyn_call_illegal_method. + lv_errormessage = 'Method LOAD missing in alternative zipclass'. "#EC NOTEXT This is a workaround until class CL_ABAP_ZIP is fixed + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDTRY. + + IF sy-subrc <> 0. + lv_errormessage = 'ZIP parse error'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "constructor + METHOD read. + DATA: lv_errormessage TYPE string. + TRY. + CALL METHOD alternate_zip->('GET') + EXPORTING + name = i_filename + IMPORTING + content = r_content " Contents + EXCEPTIONS + zip_index_error = 1 + zip_decompression_error = 2 + OTHERS = 3. + CATCH cx_sy_dyn_call_illegal_method. + lv_errormessage = 'Method GET missing in alternative zipclass'. "#EC NOTEXT This is a workaround until class CL_ABAP_ZIP is fixed + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDTRY. + IF sy-subrc <> 0. + lv_errormessage = 'File not found in zip-archive'(003). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDMETHOD. "read + ENDCLASS. "lcl_alternate_zip_archive IMPLEMENTATION + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature + +* +class lcl_zip_archive definition abstract. + public section. + methods read abstract + importing i_filename type csequence + returning value(r_content) type xstring " Remember copy-on-write! + raising zcx_excel. +endclass. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + IXML + + + + + + + METHOD zif_excel_reader~load. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Map Document Properties to ZCL_EXCEL +*--------------------------------------------------------------------* + + CONSTANTS: lcv_core_properties TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + lcv_office_document TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument'. + + DATA: lo_rels TYPE REF TO if_ixml_document, + lo_node TYPE REF TO if_ixml_element, + ls_relationship TYPE t_relationship. + +*--------------------------------------------------------------------* +* §1 Create EXCEL-Object we want to return to caller + +* §2 We need to read the the file "\\_rels\.rels" because it tells +* us where in this folder structure the data for the workbook +* is located in the xlsx zip-archive +* +* The xlsx Zip-archive has generally the following folder structure: +* <root> | +* |--> _rels +* |--> doc_Props +* |--> xl | +* |--> _rels +* |--> theme +* |--> worksheets + +* §3 Extracting from this the path&file where the workbook is located +* Following is an example how this file could be set up +* <?xml version="1.0" encoding="UTF-8" standalone="true"?> +* <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> +* <Relationship Target="docProps/app.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Id="rId3"/> +* <Relationship Target="docProps/core.xml" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Id="rId2"/> +* <Relationship Target="xl/workbook.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Id="rId1"/> +* </Relationships> +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* §1 Create EXCEL-Object we want to return to caller +*--------------------------------------------------------------------* + IF iv_zcl_excel_classname IS INITIAL. + CREATE OBJECT r_excel. + ELSE. + CREATE OBJECT r_excel TYPE (iv_zcl_excel_classname). + ENDIF. + + zip = create_zip_archive( i_xlsx_binary = i_excel2007 + i_use_alternate_zip = i_use_alternate_zip ). + +*--------------------------------------------------------------------* +* §2 Get file in folderstructure +*--------------------------------------------------------------------* + lo_rels = get_ixml_from_zip_archive( '_rels/.rels' ). + +*--------------------------------------------------------------------* +* §3 Cycle through the Relationship Tags and use the ones we need +*--------------------------------------------------------------------* + lo_node ?= lo_rels->find_from_name( 'Relationship' ). "#EC NOTEXT + WHILE lo_node IS BOUND. + + fill_struct_from_attributes( EXPORTING + ip_element = lo_node + CHANGING + cp_structure = ls_relationship ). + CASE ls_relationship-type. + + WHEN lcv_office_document. +*--------------------------------------------------------------------* +* Parse workbook - main part here +*--------------------------------------------------------------------* + load_workbook( iv_workbook_full_filename = ls_relationship-target + io_excel = r_excel ). + + WHEN lcv_core_properties. + " 2do§1 Map Document Properties to ZCL_EXCEL + + WHEN OTHERS. + + ENDCASE. + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + METHOD zif_excel_reader~load_file. + + DATA: lv_excel_data TYPE xstring. + +*--------------------------------------------------------------------* +* Read file into binary string +*--------------------------------------------------------------------* + IF i_from_applserver = abap_true. + lv_excel_data = read_from_applserver( i_filename ). + ELSE. + lv_excel_data = read_from_local_file( i_filename ). + ENDIF. + +*--------------------------------------------------------------------* +* Parse Excel data into ZCL_EXCEL object from binary string +*--------------------------------------------------------------------* + r_excel = zif_excel_reader~load( i_excel2007 = lv_excel_data + i_use_alternate_zip = i_use_alternate_zip + iv_zcl_excel_classname = iv_zcl_excel_classname ). + +ENDMETHOD. + + + + + + + METHOD create_zip_archive. + CASE i_use_alternate_zip. + WHEN space. + e_zip = lcl_abap_zip_archive=>create( i_xlsx_binary ). + WHEN OTHERS. + e_zip = lcl_alternate_zip_archive=>create( i_data = i_xlsx_binary + i_alternate_zip_class = i_use_alternate_zip ). + ENDCASE. +ENDMETHOD. + + + + + METHOD fill_row_outlines. + + TYPES: BEGIN OF lts_row_data, + row TYPE i, + outline_level TYPE i, + END OF lts_row_data, + ltt_row_data TYPE SORTED TABLE OF lts_row_data WITH UNIQUE KEY row. + + DATA: lt_row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + + lt_row_data TYPE ltt_row_data, + ls_row_data LIKE LINE OF lt_row_data, + lt_collapse_rows TYPE HASHED TABLE OF i WITH UNIQUE KEY table_line, + + lv_collapsed TYPE abap_bool, + + lv_outline_level TYPE i, + lv_next_consecutive_row TYPE i, + lt_outline_rows TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + ls_outline_row LIKE LINE OF lt_outline_rows, + + lv_row_offset TYPE i, + lv_row_collapse_flag TYPE i. + + + FIELD-SYMBOLS: <ls_row_dimension> LIKE LINE OF lt_row_dimensions, + <ls_row_data> LIKE LINE OF lt_row_data. + +* First collect information about outlines ( outline leven and collapsed state ) + lt_row_dimensions = io_worksheet->get_row_dimensions( ). + LOOP AT lt_row_dimensions ASSIGNING <ls_row_dimension>. + + ls_row_data-row = <ls_row_dimension>-row. + ls_row_data-outline_level = <ls_row_dimension>-row_dimension->get_outline_level( ). + IF ls_row_data-outline_level IS NOT INITIAL. + INSERT ls_row_data INTO TABLE lt_row_data. + ENDIF. + + lv_collapsed = <ls_row_dimension>-row_dimension->get_collapsed( ). + IF lv_collapsed = abap_true. + INSERT <ls_row_dimension>-row INTO TABLE lt_collapse_rows. + ENDIF. + + ENDLOOP. + +* Now parse this information - we need consecutive rows - any gap will create a new outline + DO 7 TIMES. " max number of outlines allowed + lv_outline_level = sy-index. + CLEAR lv_next_consecutive_row. + CLEAR ls_outline_row. + LOOP AT lt_row_data ASSIGNING <ls_row_data> WHERE outline_level >= lv_outline_level. + + IF lv_next_consecutive_row <> <ls_row_data>-row " A gap --> close all open outlines + AND lv_next_consecutive_row IS NOT INITIAL. " First time in loop. + INSERT ls_outline_row INTO TABLE lt_outline_rows. + CLEAR: ls_outline_row. + ENDIF. + + IF ls_outline_row-row_from IS INITIAL. + ls_outline_row-row_from = <ls_row_data>-row. + ENDIF. + ls_outline_row-row_to = <ls_row_data>-row. + + lv_next_consecutive_row = <ls_row_data>-row + 1. + + ENDLOOP. + IF ls_outline_row-row_from IS NOT INITIAL. + INSERT ls_outline_row INTO TABLE lt_outline_rows. + ENDIF. + ENDDO. + +* lt_outline_rows holds all outline information +* we now need to determine whether the outline is collapsed or not + LOOP AT lt_outline_rows INTO ls_outline_row. + + IF io_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_off. + lv_row_collapse_flag = ls_outline_row-row_from - 1. + ELSE. + lv_row_collapse_flag = ls_outline_row-row_to + 1. + ENDIF. + READ TABLE lt_collapse_rows TRANSPORTING NO FIELDS WITH TABLE KEY table_line = lv_row_collapse_flag. + IF sy-subrc = 0. + ls_outline_row-collapsed = abap_true. + ENDIF. + io_worksheet->set_row_outline( iv_row_from = ls_outline_row-row_from + iv_row_to = ls_outline_row-row_to + iv_collapsed = ls_outline_row-collapsed ). + + ENDLOOP. + +* Finally purge outline information ( collapsed state, outline leve) from row_dimensions, since we want to keep these in the outline-table + LOOP AT lt_row_dimensions ASSIGNING <ls_row_dimension>. + + <ls_row_dimension>-row_dimension->set_outline_level( 0 ). + <ls_row_dimension>-row_dimension->set_collapsed( abap_false ). + + ENDLOOP. + +ENDMETHOD. + + + + + method fill_struct_from_attributes. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-07 +* - ... +* changes: renaming variables to naming conventions +* aligning code +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + + data: lv_name type string, + lo_attributes type ref to if_ixml_named_node_map, + lo_attribute type ref to if_ixml_attribute, + lo_iterator type ref to if_ixml_node_iterator. + + field-symbols: <component> type any. + +*--------------------------------------------------------------------* +* The values of named attributes of a tag are being read and moved into corresponding +* fields of given structure +* Behaves like move-corresonding tag to structure + +* Example: +* <Relationship Target="docProps/app.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Id="rId3"/> +* Here the attributes are Target, Type and Id. Thus if the passed +* structure has fieldnames Id and Target these would be filled with +* "rId3" and "docProps/app.xml" respectively +*--------------------------------------------------------------------* + clear cp_structure. + + lo_attributes = ip_element->get_attributes( ). + lo_iterator = lo_attributes->create_iterator( ). + lo_attribute ?= lo_iterator->get_next( ). + while lo_attribute is bound. + + lv_name = lo_attribute->get_name( ). + translate lv_name to upper case. + assign component lv_name of structure cp_structure to <component>. + if sy-subrc = 0. + <component> = lo_attribute->get_value( ). + endif. + lo_attribute ?= lo_iterator->get_next( ). + + endwhile. + + +endmethod. + + + + + + METHOD get_dxf_style_guid. + DATA: lo_ixml_dxf_children TYPE REF TO if_ixml_node_list, + lo_ixml_iterator_dxf_children TYPE REF TO if_ixml_node_iterator, + lo_ixml_dxf_child TYPE REF TO if_ixml_element, + + lv_dxf_child_type TYPE string, + + lo_ixml_element TYPE REF TO if_ixml_element, + lo_ixml_element2 TYPE REF TO if_ixml_element, + lv_val TYPE string. + + DATA: ls_cstyle TYPE zexcel_s_cstyle_complete, + ls_cstylex TYPE zexcel_s_cstylex_complete. + + + + lo_ixml_dxf_children = io_ixml_dxf->get_children( ). + lo_ixml_iterator_dxf_children = lo_ixml_dxf_children->create_iterator( ). + lo_ixml_dxf_child ?= lo_ixml_iterator_dxf_children->get_next( ). + WHILE lo_ixml_dxf_child IS BOUND. + + lv_dxf_child_type = lo_ixml_dxf_child->get_name( ). + CASE lv_dxf_child_type. + + WHEN 'font'. +*--------------------------------------------------------------------* +* italic +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'i' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'val' ). + IF lv_val <> '0'. + ls_cstyle-font-italic = 'X'. + ls_cstylex-font-italic = 'X'. + ENDIF. + + ENDIF. +*--------------------------------------------------------------------* +* bold +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'b' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'val' ). + IF lv_val <> '0'. + ls_cstyle-font-bold = 'X'. + ls_cstylex-font-bold = 'X'. + ENDIF. + + ENDIF. +*--------------------------------------------------------------------* +* strikethrough +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'strike' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'val' ). + IF lv_val <> '0'. + ls_cstyle-font-strikethrough = 'X'. + ls_cstylex-font-strikethrough = 'X'. + ENDIF. + + ENDIF. +*--------------------------------------------------------------------* +* color +*--------------------------------------------------------------------* + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'color' ). + IF lo_ixml_element IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element->get_attribute_ns( 'rgb' ). + ls_cstyle-font-color-rgb = lv_val. + ls_cstylex-font-color-rgb = 'X'. + ENDIF. + + WHEN 'fill'. + lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'patternFill' ). + IF lo_ixml_element IS BOUND. + lo_ixml_element2 = lo_ixml_element->find_from_name( 'bgColor' ). + IF lo_ixml_element2 IS BOUND. + CLEAR lv_val. + lv_val = lo_ixml_element2->get_attribute_ns( 'rgb' ). + IF lv_val IS NOT INITIAL. + ls_cstyle-fill-filltype = zcl_excel_style_fill=>c_fill_solid. + ls_cstyle-fill-bgcolor-rgb = lv_val. + ls_cstylex-fill-filltype = 'X'. + ls_cstylex-fill-bgcolor-rgb = 'X'. + ENDIF. + ENDIF. + CLEAR lv_val. + lv_val = lo_ixml_element2->get_attribute_ns( 'theme' ). + IF lv_val IS NOT INITIAL. + ls_cstyle-fill-filltype = zcl_excel_style_fill=>c_fill_solid. + ls_cstyle-fill-bgcolor-theme = lv_val. + ls_cstylex-fill-filltype = 'X'. + ls_cstylex-fill-bgcolor-theme = 'X'. + ENDIF. + ENDIF. + +* 2do - borders into dxf-styles. Here and in writerclass +* WHEN 'border'. +* lo_ixml_element = lo_ixml_dxf_child->find_from_name( 'left' ). +* IF lo_ixml_element IS BOUND. +* CLEAR lv_val. +* lv_val = lo_ixml_element2->get_attribute_ns( 'style' ). +* IF lv_val IS NOT INITIAL. +* ls_cstyle-borders-left-border_style = lv_val. +* ls_cstylex-borders-left-border_style = 'X'. +* ENDIF. +* ENDIF. + + ENDCASE. + + lo_ixml_dxf_child ?= lo_ixml_iterator_dxf_children->get_next( ). + + ENDWHILE. + + + + + rv_style_guid = io_excel->get_static_cellstyle_guid( ip_cstyle_complete = ls_cstyle + ip_cstylex_complete = ls_cstylex ). + + +ENDMETHOD. + + + + + + METHOD get_from_zip_archive. + + ASSERT zip IS BOUND. " zip object has to exist at this point + + r_content = zip->read( i_filename ). + +ENDMETHOD. + + + + + + + METHOD get_ixml_from_zip_archive. + + DATA: lv_content TYPE xstring, + lo_ixml TYPE REF TO if_ixml, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_istream TYPE REF TO if_ixml_istream, + lo_parser TYPE REF TO if_ixml_parser. + +*--------------------------------------------------------------------* +* Load XML file from archive into an input stream, +* and parse that stream into an ixml object +*--------------------------------------------------------------------* + lv_content = me->get_from_zip_archive( i_filename ). + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_istream = lo_streamfactory->create_istream_xstring( lv_content ). + r_ixml = lo_ixml->create_document( ). + lo_parser = lo_ixml->create_parser( stream_factory = lo_streamfactory + istream = lo_istream + document = r_ixml ). + lo_parser->set_normalizing( is_normalizing ). + lo_parser->set_validating( mode = if_ixml_parser=>co_no_validation ). + lo_parser->parse( ). + +ENDMETHOD. + + + + + + METHOD load_drawing_anchor. + + TYPES: BEGIN OF t_c_nv_pr, + name TYPE string, + id TYPE string, + END OF t_c_nv_pr. + + TYPES: BEGIN OF t_blip, + cstate TYPE string, + embed TYPE string, + END OF t_blip. + + TYPES: BEGIN OF t_chart, + id TYPE string, + END OF t_chart. + + TYPES: BEGIN OF t_ext, + cx TYPE string, + cy TYPE string, + END OF t_ext. + + CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_true_int TYPE string VALUE '1'. + CONSTANTS: lc_rel_chart TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', + lc_rel_image TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'. + + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + node TYPE REF TO if_ixml_element, + node2 TYPE REF TO if_ixml_element, + node3 TYPE REF TO if_ixml_element, + node4 TYPE REF TO if_ixml_element, + + ls_upper TYPE zexcel_drawing_location, + ls_lower TYPE zexcel_drawing_location, + ls_size TYPE zexcel_drawing_size, + ext TYPE t_ext, + lv_content TYPE xstring, + lv_relation_id TYPE string, + lv_title TYPE string, + + 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. + TRY. + ls_size-width = zcl_excel_drawing=>emu2pixel( ls_size-width ). + CATCH cx_root. + ENDTRY. + TRY. + ls_size-height = zcl_excel_drawing=>emu2pixel( ls_size-height ). + CATCH cx_root. + ENDTRY. + ENDIF. + + node ?= io_anchor_element->find_from_name( name = 'to' namespace = 'xdr' ). + IF node IS INITIAL. + CLEAR ls_lower. + ELSE. + node2 ?= node->find_from_name( name = 'col' namespace = 'xdr' ). + ls_lower-col = node2->get_value( ). + node2 ?= node->find_from_name( name = 'row' namespace = 'xdr' ). + ls_lower-row = node2->get_value( ). + node2 ?= node->find_from_name( name = 'colOff' namespace = 'xdr' ). + ls_lower-col_offset = node2->get_value( ). + node2 ?= node->find_from_name( name = 'rowOff' namespace = 'xdr' ). + ls_lower-row_offset = node2->get_value( ). + ENDIF. + + node ?= io_anchor_element->find_from_name( name = 'pic' namespace = 'xdr' ). + IF node IS NOT INITIAL. + node2 ?= node->find_from_name( name = 'nvPicPr' namespace = 'xdr' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'cNvPr' namespace = 'xdr' ). + CHECK node3 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = cnvpr ). + lv_title = cnvpr-name. + + node2 ?= node->find_from_name( name = 'blipFill' namespace = 'xdr' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'blip' namespace = 'a' ). + CHECK node3 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = blip ). + lv_relation_id = blip-embed. + + drawing_type = zcl_excel_drawing=>type_image. + ENDIF. + + node ?= io_anchor_element->find_from_name( name = 'graphicFrame' namespace = 'xdr' ). + IF node IS NOT INITIAL. + node2 ?= node->find_from_name( name = 'nvGraphicFramePr' namespace = 'xdr' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'cNvPr' namespace = 'xdr' ). + CHECK node3 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node3 CHANGING cp_structure = cnvpr ). + lv_title = cnvpr-name. + + node2 ?= node->find_from_name( name = 'graphic' namespace = 'a' ). + CHECK node2 IS NOT INITIAL. + node3 ?= node2->find_from_name( name = 'graphicData' namespace = 'a' ). + CHECK node3 IS NOT INITIAL. + node4 ?= node2->find_from_name( name = 'chart' namespace = 'c' ). + CHECK node4 IS NOT INITIAL. + me->fill_struct_from_attributes( EXPORTING ip_element = node4 CHANGING cp_structure = chart ). + lv_relation_id = chart-id. + + drawing_type = zcl_excel_drawing=>type_chart. + ENDIF. + + lo_drawing = io_worksheet->excel->add_new_drawing( + ip_type = drawing_type + ip_title = lv_title ). + io_worksheet->add_drawing( lo_drawing ). + + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + READ TABLE it_related_drawings INTO rel_drawing + WITH KEY id = lv_relation_id. + + lo_drawing->set_media( + EXPORTING + ip_media = rel_drawing-content + ip_media_type = rel_drawing-file_ext + ip_width = ls_size-width + ip_height = ls_size-height ). + + IF drawing_type = zcl_excel_drawing=>type_chart. + "-------------Added by Alessandro Iannacci - Should load chart attributes + lo_drawing->load_chart_attributes( rel_drawing-content_xml ). + ENDIF. + +ENDMETHOD. + + + + + + METHOD load_dxf_styles. + + DATA: lo_styles_xml TYPE REF TO if_ixml_document, + lo_node_dxfs TYPE REF TO if_ixml_element, + + lo_nodes_dxf TYPE REF TO if_ixml_node_collection, + lo_iterator_dxf TYPE REF TO if_ixml_node_iterator, + lo_node_dxf TYPE REF TO if_ixml_element, + + lv_dxf_count TYPE i. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF mt_dxf_styles. + +*--------------------------------------------------------------------* +* Look for dxfs-node +*--------------------------------------------------------------------* + lo_styles_xml = me->get_ixml_from_zip_archive( iv_path ). + lo_node_dxfs = lo_styles_xml->find_from_name( 'dxfs' ). + CHECK lo_node_dxfs IS BOUND. + + +*--------------------------------------------------------------------* +* loop through all dxf-nodes and create style for each +*--------------------------------------------------------------------* + lo_nodes_dxf ?= lo_node_dxfs->get_elements_by_tag_name( 'dxf' ). + lo_iterator_dxf = lo_nodes_dxf->create_iterator( ). + lo_node_dxf ?= lo_iterator_dxf->get_next( ). + WHILE lo_node_dxf IS BOUND. + + APPEND INITIAL LINE TO mt_dxf_styles ASSIGNING <ls_dxf_style>. + <ls_dxf_style>-dxf = lv_dxf_count. " We start counting at 0 + ADD 1 TO lv_dxf_count. " prepare next entry + + <ls_dxf_style>-guid = get_dxf_style_guid( io_ixml_dxf = lo_node_dxf + io_excel = io_excel ). + lo_node_dxf ?= lo_iterator_dxf->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + method LOAD_SHARED_STRINGS. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Support partial formatting of strings in cells +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-11 +* - ... +* changes: renaming variables to naming conventions +* renaming variables to indicate what they are used for +* aligning code +* adding comments to explain what we are trying to achieve +* rewriting code for better readibility +*--------------------------------------------------------------------* + + + + DATA: + lo_shared_strings_xml TYPE REF TO if_ixml_document, + lo_node_si TYPE REF TO if_ixml_element, + lo_node_si_child TYPE REF TO if_ixml_element, + lo_node_r_child_t TYPE REF TO if_ixml_element, + lv_tag_name TYPE string, + lv_node_value TYPE string. + + FIELD-SYMBOLS: <lv_shared_string> LIKE LINE OF me->shared_strings. + +*--------------------------------------------------------------------* + +* §1 Parse shared strings file and get into internal table +* So far I have encountered 2 ways how a string can be represented in the shared strings file +* §1.1 - "simple" strings +* §1.2 - rich text formatted strings + +* Following is an example how this file could be set up; 2 strings in simple formatting, 3rd string rich textformatted + + +* <?xml version="1.0" encoding="UTF-8" standalone="true"?> +* <sst uniqueCount="6" count="6" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> +* <si> +* <t>This is a teststring 1</t> +* </si> +* <si> +* <t>This is a teststring 2</t> +* </si> +* <si> +* <r> +* <t>T</t> +* </r> +* <r> +* <rPr> +* <sz val="11"/> +* <color rgb="FFFF0000"/> +* <rFont val="Calibri"/> +* <family val="2"/> +* <scheme val="minor"/> +* </rPr> +* <t xml:space="preserve">his is a </t> +* </r> +* <r> +* <rPr> +* <sz val="11"/> +* <color theme="1"/> +* <rFont val="Calibri"/> +* <family val="2"/> +* <scheme val="minor"/> +* </rPr> +* <t>teststring 3</t> +* </r> +* </si> +* </sst> +*--------------------------------------------------------------------* + + lo_shared_strings_xml = me->get_ixml_from_zip_archive( i_filename = ip_path + is_normalizing = space ). " NO!!! normalizing - otherwise leading blanks will be omitted and that is not really desired for the stringtable + lo_node_si ?= lo_shared_strings_xml->find_from_name( 'si' ). + WHILE lo_node_si IS BOUND. + + APPEND INITIAL LINE TO me->shared_strings ASSIGNING <lv_shared_string>. " Each <si>-entry in the xml-file must lead to an entry in our stringtable + lo_node_si_child ?= lo_node_si->get_first_child( ). + IF lo_node_si_child IS BOUND. + lv_tag_name = lo_node_si_child->get_name( ). + IF lv_tag_name = 't'. +*--------------------------------------------------------------------* +* §1.1 - "simple" strings +* Example: see above +*--------------------------------------------------------------------* + <lv_shared_string> = lo_node_si_child->get_value( ). + ELSE. +*--------------------------------------------------------------------* +* §1.2 - rich text formatted strings +* it is sufficient to strip the <t>...</t> tag from each <r>-tag and concatenate these +* as long as rich text formatting is not supported (2do§1) ignore all info about formatting +* Example: see above +*--------------------------------------------------------------------* + WHILE lo_node_si_child IS BOUND. " actually these children of <si> are <r>-tags + + lo_node_r_child_t ?= lo_node_si_child->find_from_name( 't' ). " extract the <t>...</t> part of each <r>-tag + IF lo_node_r_child_t IS BOUND. + lv_node_value = lo_node_r_child_t->get_value( ). + CONCATENATE <lv_shared_string> lv_node_value INTO <lv_shared_string> RESPECTING BLANKS. + ENDIF. + + lo_node_si_child ?= lo_node_si_child->get_next( ). + + ENDWHILE. + ENDIF. + ENDIF. + + lo_node_si ?= lo_node_si->get_next( ). + ENDWHILE. + + endmethod. + + + + + + METHOD load_styles. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (wip ) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + TYPES: BEGIN OF lty_xf, + applyalignment TYPE string, + applyborder TYPE string, + applyfill TYPE string, + applyfont TYPE string, + applynumberformat TYPE string, + applyprotection TYPE string, + borderid TYPE string, + fillid TYPE string, + fontid TYPE string, + numfmtid TYPE string, + pivotbutton TYPE string, + quoteprefix TYPE string, + xfid TYPE string, + END OF lty_xf. + + TYPES: BEGIN OF lty_alignment, + horizontal TYPE string, + indent TYPE string, + justifylastline TYPE string, + readingorder TYPE string, + relativeindent TYPE string, + shrinktofit TYPE string, + textrotation TYPE string, + vertical TYPE string, + wraptext TYPE string, + END OF lty_alignment. + + TYPES: BEGIN OF lty_protection, + hidden TYPE string, + locked TYPE string, + END OF lty_protection. + + DATA: lo_styles_xml TYPE REF TO if_ixml_document, + lo_style TYPE REF TO zcl_excel_style, + + lt_num_formats TYPE zcl_excel_style_number_format=>t_num_formats, + lt_fills TYPE t_fills, + lt_borders TYPE t_borders, + lt_fonts TYPE t_fonts, + + ls_num_format TYPE zcl_excel_style_number_format=>t_num_format , + ls_fill TYPE REF TO zcl_excel_style_fill, + ls_cell_border TYPE REF TO zcl_excel_style_borders, + ls_font TYPE REF TO zcl_excel_style_font, + + lo_node_cellxfs TYPE REF TO if_ixml_element, + lo_node_cellxfs_xf TYPE REF TO if_ixml_element, + lo_node_cellxfs_xf_alignment TYPE REF TO if_ixml_element, + lo_node_cellxfs_xf_protection TYPE REF TO if_ixml_element, + + lo_nodes_xf TYPE REF TO if_ixml_node_collection, + lo_iterator_cellxfs TYPE REF TO if_ixml_node_iterator, + + ls_xf TYPE lty_xf, + ls_alignment TYPE lty_alignment, + ls_protection TYPE lty_protection, + lv_index TYPE i. + +*--------------------------------------------------------------------* +* To build a complete style that fully describes how a cell looks like +* we need the various parts +* §1 - Numberformat +* §2 - Fillstyle +* §3 - Borders +* §4 - Font +* §5 - Alignment +* §6 - Protection + +* Following is an example how this part of a file could be set up +* ... +* parts with various formatinformation - see §1,§2,§3,§4 +* ... +* <cellXfs count="26"> +* <xf numFmtId="0" borderId="0" fillId="0" fontId="0" xfId="0"/> +* <xf numFmtId="0" borderId="0" fillId="2" fontId="0" xfId="0" applyFill="1"/> +* <xf numFmtId="0" borderId="1" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="2" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="3" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="4" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* <xf numFmtId="0" borderId="0" fillId="3" fontId="0" xfId="0" applyFill="1" applyBorder="1"/> +* ... +* </cellXfs> +*--------------------------------------------------------------------* + + lo_styles_xml = me->get_ixml_from_zip_archive( ip_path ). + +*--------------------------------------------------------------------* +* The styles are build up from +* §1 number formats +* §2 fill styles +* §3 border styles +* §4 fonts +* These need to be read before we can try to build up a complete +* style that describes the look of a cell +*--------------------------------------------------------------------* + lt_num_formats = load_style_num_formats( lo_styles_xml ). " §1 + lt_fills = load_style_fills( lo_styles_xml ). " §2 + lt_borders = load_style_borders( lo_styles_xml ). " §3 + lt_fonts = load_style_fonts( lo_styles_xml ). " §4 + +*--------------------------------------------------------------------* +* Now everything is prepared to build a "full" style +*--------------------------------------------------------------------* + lo_node_cellxfs = lo_styles_xml->find_from_name( name = 'cellXfs' ). + IF lo_node_cellxfs IS BOUND. + lo_nodes_xf = lo_node_cellxfs->get_elements_by_tag_name( name = 'xf' ). + lo_iterator_cellxfs = lo_nodes_xf->create_iterator( ). + lo_node_cellxfs_xf ?= lo_iterator_cellxfs->get_next( ). + WHILE lo_node_cellxfs_xf IS BOUND. + + lo_style = ip_excel->add_new_style( ). + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_cellxfs_xf + CHANGING + cp_structure = ls_xf ). +*--------------------------------------------------------------------* +* §2 fill style +*--------------------------------------------------------------------* + IF ls_xf-applyfill = '1' AND ls_xf-fillid IS NOT INITIAL. + lv_index = ls_xf-fillid + 1. + READ TABLE lt_fills INTO ls_fill INDEX lv_index. + IF sy-subrc = 0. + lo_style->fill = ls_fill. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §1 number format +*--------------------------------------------------------------------* + IF ls_xf-numfmtid IS NOT INITIAL. + READ TABLE lt_num_formats INTO ls_num_format WITH TABLE KEY id = ls_xf-numfmtid. + IF sy-subrc = 0. + lo_style->number_format = ls_num_format-format. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §3 border style +*--------------------------------------------------------------------* + IF ls_xf-applyborder = '1' AND ls_xf-borderid IS NOT INITIAL. + lv_index = ls_xf-borderid + 1. + READ TABLE lt_borders INTO ls_cell_border INDEX lv_index. + IF sy-subrc = 0. + lo_style->borders = ls_cell_border. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §4 font +*--------------------------------------------------------------------* + IF ls_xf-applyfont = '1' AND ls_xf-fontid IS NOT INITIAL. + lv_index = ls_xf-fontid + 1. + READ TABLE lt_fonts INTO ls_font INDEX lv_index. + IF sy-subrc = 0. + lo_style->font = ls_font. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §5 - Alignment +*--------------------------------------------------------------------* + lo_node_cellxfs_xf_alignment ?= lo_node_cellxfs_xf->find_from_name( 'alignment' ). + IF lo_node_cellxfs_xf_alignment IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_cellxfs_xf_alignment + CHANGING + cp_structure = ls_alignment ). + IF ls_alignment-horizontal IS NOT INITIAL. + lo_style->alignment->horizontal = ls_alignment-horizontal. + ENDIF. + + IF ls_alignment-vertical IS NOT INITIAL. + lo_style->alignment->vertical = ls_alignment-vertical. + ENDIF. + + IF ls_alignment-textrotation IS NOT INITIAL. + lo_style->alignment->textrotation = ls_alignment-textrotation. + ENDIF. + + IF ls_alignment-wraptext = '1' OR ls_alignment-wraptext = 'true'. + lo_style->alignment->wraptext = abap_true. + ENDIF. + + IF ls_alignment-shrinktofit = '1' OR ls_alignment-shrinktofit = 'true'. + lo_style->alignment->shrinktofit = abap_true. + ENDIF. + + IF ls_alignment-indent IS NOT INITIAL. + lo_style->alignment->indent = ls_alignment-indent. + ENDIF. + ENDIF. + +*--------------------------------------------------------------------* +* §6 - Protection +*--------------------------------------------------------------------* + lo_node_cellxfs_xf_protection ?= lo_node_cellxfs_xf->find_from_name( 'protection' ). + IF lo_node_cellxfs_xf_protection IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_cellxfs_xf_protection + CHANGING + cp_structure = ls_protection ). + IF ls_protection-locked = '1' OR ls_protection-locked = 'true'. + lo_style->protection->locked = zcl_excel_style_protection=>c_protection_locked. + ELSE. + lo_style->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. + ENDIF. + + IF ls_protection-hidden = '1' OR ls_protection-hidden = 'true'. + lo_style->protection->hidden = zcl_excel_style_protection=>c_protection_hidden. + ELSE. + lo_style->protection->hidden = zcl_excel_style_protection=>c_protection_unhidden. + ENDIF. + + ENDIF. + + INSERT lo_style INTO TABLE me->styles. + + lo_node_cellxfs_xf ?= lo_iterator_cellxfs->get_next( ). + + ENDWHILE. + ENDIF. + +ENDMETHOD. + + + + + method LOAD_STYLE_BORDERS. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* renaming variables to indicate what they are used for +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + DATA: lo_node_border TYPE REF TO if_ixml_element, + lo_node_bordertype TYPE REF TO if_ixml_element, + lo_node_bordercolor TYPE REF TO if_ixml_element, + lo_cell_border TYPE REF TO zcl_excel_style_borders, + lo_border TYPE REF TO zcl_excel_style_border, + ls_color TYPE t_color. + +*--------------------------------------------------------------------* +* We need a table of used borderformats to build up our styles +* §1 A cell has 4 outer borders and 2 diagonal "borders" +* These borders can be formatted separately but the diagonal borders +* are always being formatted the same +* We'll parse through the <border>-tag for each of the bordertypes +* §2 and read the corresponding formatting information + +* Following is an example how this part of a file could be set up +* <border diagonalDown="1"> +* <left style="mediumDashDotDot"> +* <color rgb="FFFF0000"/> +* </left> +* <right/> +* <top style="thick"> +* <color rgb="FFFF0000"/> +* </top> +* <bottom style="thick"> +* <color rgb="FFFF0000"/> +* </bottom> +* <diagonal style="thick"> +* <color rgb="FFFF0000"/> +* </diagonal> +* </border> +*--------------------------------------------------------------------* + lo_node_border ?= ip_xml->find_from_name( 'border' ). + WHILE lo_node_border IS BOUND. + + CREATE OBJECT lo_cell_border. + +*--------------------------------------------------------------------* +* Diagonal borderlines are formatted the equally. Determine what kind of diagonal borders are present if any +*--------------------------------------------------------------------* +* DiagonalNone = 0 +* DiagonalUp = 1 +* DiagonalDown = 2 +* DiagonalBoth = 3 +*--------------------------------------------------------------------* + IF lo_node_border->get_attribute( 'diagonalDown' ) IS NOT INITIAL. + add zcl_excel_style_borders=>c_diagonal_down to lo_cell_border->diagonal_mode. + ENDIF. + + IF lo_node_border->get_attribute( 'diagonalUp' ) IS NOT INITIAL. + add zcl_excel_style_borders=>c_diagonal_up to lo_cell_border->diagonal_mode. + ENDIF. + + lo_node_bordertype ?= lo_node_border->get_first_child( ). + WHILE lo_node_bordertype IS BOUND. +*--------------------------------------------------------------------* +* §1 Determine what kind of border we are talking about +*--------------------------------------------------------------------* +* Up, down, left, right, diagonal +*--------------------------------------------------------------------* + CREATE OBJECT lo_border. + + CASE lo_node_bordertype->get_name( ). + + WHEN 'left'. + lo_cell_border->left = lo_border. + + WHEN 'right'. + lo_cell_border->right = lo_border. + + WHEN 'top'. + lo_cell_border->top = lo_border. + + WHEN 'bottom'. + lo_cell_border->down = lo_border. + + WHEN 'diagonal'. + lo_cell_border->diagonal = lo_border. + + ENDCASE. + +*--------------------------------------------------------------------* +* §2 Read the border-formatting +*--------------------------------------------------------------------* + lo_border->border_style = lo_node_bordertype->get_attribute( 'style' ). + lo_node_bordercolor ?= lo_node_bordertype->find_from_name( 'color' ). + IF lo_node_bordercolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_bordercolor + CHANGING + cp_structure = ls_color ). + + lo_border->border_color-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_border->border_color-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_border->border_color-theme = ls_color-theme. + ENDIF. + lo_border->border_color-tint = ls_color-tint. + ENDIF. + + lo_node_bordertype ?= lo_node_bordertype->get_next( ). + + ENDWHILE. + + INSERT lo_cell_border INTO TABLE ep_borders. + + lo_node_border ?= lo_node_border->get_next( ). + + ENDWHILE. + + + endmethod. + + + + + method LOAD_STYLE_FILLS. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Support gradientFill +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* commenting on problems/future enhancements/todos we already know of or should decide upon +* adding comments to explain what we are trying to achieve +* renaming variables to indicate what they are used for +*--------------------------------------------------------------------* + DATA: lv_value TYPE string, + lo_node_fill TYPE REF TO if_ixml_element, + lo_node_fill_child TYPE REF TO if_ixml_element, + lo_node_bgcolor TYPE REF TO if_ixml_element, + lo_node_fgcolor TYPE REF TO if_ixml_element, + lo_node_stop TYPE REF TO if_ixml_element, + lo_fill TYPE REF TO zcl_excel_style_fill, + ls_color TYPE t_color. + +*--------------------------------------------------------------------* +* We need a table of used fillformats to build up our styles + +* Following is an example how this part of a file could be set up +* <fill> +* <patternFill patternType="gray125"/> +* </fill> +* <fill> +* <patternFill patternType="solid"> +* <fgColor rgb="FFFFFF00"/> +* <bgColor indexed="64"/> +* </patternFill> +* </fill> +*--------------------------------------------------------------------* + + lo_node_fill ?= ip_xml->find_from_name( 'fill' ). + WHILE lo_node_fill IS BOUND. + + CREATE OBJECT lo_fill. + lo_node_fill_child ?= lo_node_fill->get_first_child( ). + lv_value = lo_node_fill_child->get_name( ). + CASE lv_value. + +*--------------------------------------------------------------------* +* Patternfill +*--------------------------------------------------------------------* + WHEN 'patternFill'. + lo_fill->filltype = lo_node_fill_child->get_attribute( 'patternType' ). +*--------------------------------------------------------------------* +* Patternfill - background color +*--------------------------------------------------------------------* + lo_node_bgcolor = lo_node_fill_child->find_from_name( 'bgColor' ). + IF lo_node_bgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_bgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->bgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->bgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->bgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->bgcolor-tint = ls_color-tint. + ENDIF. + +*--------------------------------------------------------------------* +* Patternfill - foreground color +*--------------------------------------------------------------------* + lo_node_fgcolor = lo_node_fill->find_from_name( 'fgColor' ). + IF lo_node_fgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_fgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->fgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->fgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->fgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->fgcolor-tint = ls_color-tint. + ENDIF. + + +*--------------------------------------------------------------------* +* gradientFill +*--------------------------------------------------------------------* + WHEN 'gradientFill'. + lo_fill->gradtype-type = lo_node_fill_child->get_attribute( 'type' ). + lo_fill->gradtype-top = lo_node_fill_child->get_attribute( 'top' ). + lo_fill->gradtype-left = lo_node_fill_child->get_attribute( 'left' ). + lo_fill->gradtype-right = lo_node_fill_child->get_attribute( 'right' ). + lo_fill->gradtype-bottom = lo_node_fill_child->get_attribute( 'bottom' ). + lo_fill->gradtype-degree = lo_node_fill_child->get_attribute( 'degree' ). + free lo_node_stop. + lo_node_stop ?= lo_node_fill_child->find_from_name( 'stop' ). + while lo_node_stop is bound. + if lo_fill->gradtype-position1 is initial. + lo_fill->gradtype-position1 = lo_node_stop->get_attribute( 'position' ). + lo_node_bgcolor = lo_node_stop->find_from_name( 'color' ). + IF lo_node_bgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_bgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->bgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->bgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->bgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->bgcolor-tint = ls_color-tint. + ENDIF. + elseif lo_fill->gradtype-position2 is initial. + lo_fill->gradtype-position2 = lo_node_stop->get_attribute( 'position' ). + lo_node_fgcolor = lo_node_stop->find_from_name( 'color' ). + IF lo_node_fgcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node_fgcolor + CHANGING + cp_structure = ls_color ). + + lo_fill->fgcolor-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_fill->fgcolor-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_fill->fgcolor-theme = ls_color-theme. + ENDIF. + lo_fill->fgcolor-tint = ls_color-tint. + ENDIF. + elseif lo_fill->gradtype-position3 is initial. + lo_fill->gradtype-position3 = lo_node_stop->get_attribute( 'position' ). + "BGColor is filled already with position 1 no need to check again + endif. + + lo_node_stop ?= lo_node_stop->get_next( ). + ENDWHILE. + + WHEN OTHERS. + + ENDCASE. + + + INSERT lo_fill INTO TABLE ep_fills. + + lo_node_fill ?= lo_node_fill->get_next( ). + + ENDWHILE. + + + endmethod. + + + + + METHOD load_style_fonts. + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* aligning code +* removing unused variables +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + DATA: lo_node_font TYPE REF TO if_ixml_element, + lo_node2 TYPE REF TO if_ixml_element, + lo_font TYPE REF TO zcl_excel_style_font, + ls_color TYPE t_color. + +*--------------------------------------------------------------------* +* We need a table of used fonts to build up our styles + +* Following is an example how this part of a file could be set up +* <font> +* <sz val="11"/> +* <color theme="1"/> +* <name val="Calibri"/> +* <family val="2"/> +* <scheme val="minor"/> +* </font> +*--------------------------------------------------------------------* + lo_node_font ?= ip_xml->find_from_name( 'font' ). + WHILE lo_node_font IS BOUND. + + CREATE OBJECT lo_font. +*--------------------------------------------------------------------* +* Bold +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'b' ) IS BOUND. + lo_font->bold = abap_true. + ENDIF. + +*--------------------------------------------------------------------* +* Italic +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'i' ) IS BOUND. + lo_font->italic = abap_true. + ENDIF. + +*--------------------------------------------------------------------* +* Underline +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'u' ). + IF lo_node2 IS BOUND. + lo_font->underline = abap_true. + lo_font->underline_mode = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* StrikeThrough +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'strike' ) IS BOUND. + lo_font->strikethrough = abap_true. + ENDIF. + +*--------------------------------------------------------------------* +* Fontsize +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'sz' ). + IF lo_node2 IS BOUND. + lo_font->size = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* Fontname +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'name' ). + IF lo_node2 IS BOUND. + lo_font->name = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* Fontfamily +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'family' ). + IF lo_node2 IS BOUND. + lo_font->family = lo_node2->get_attribute( 'val' ). + ENDIF. + +*--------------------------------------------------------------------* +* Fontscheme +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'scheme' ). + IF lo_node2 IS BOUND. + lo_font->scheme = lo_node2->get_attribute( 'val' ). + ELSE. + CLEAR lo_font->scheme. + ENDIF. + +*--------------------------------------------------------------------* +* Fontcolor +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'color' ). + IF lo_node2 IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_node2 + CHANGING + cp_structure = ls_color ). + lo_font->color-rgb = ls_color-rgb. + IF ls_color-indexed IS NOT INITIAL. + lo_font->color-indexed = ls_color-indexed. + ENDIF. + + IF ls_color-theme IS NOT INITIAL. + lo_font->color-theme = ls_color-theme. + ENDIF. + lo_font->color-tint = ls_color-tint. + ENDIF. + + INSERT lo_font INTO TABLE ep_fonts. + + lo_node_font ?= lo_node_font->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_style_num_formats. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Explain gaps in predefined formats +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-25 +* - ... +* changes: renaming variables and types to naming conventions +* adding comments to explain what we are trying to achieve +* aligning code +*--------------------------------------------------------------------* + DATA: lo_node_numfmt TYPE REF TO if_ixml_element, + ls_num_format TYPE ZCL_EXCEL_STYLE_NUMBER_FORMAT=>T_NUM_FORMAT . + +*--------------------------------------------------------------------* +* We need a table of used numberformats to build up our styles +* there are two kinds of numberformats +* §1 built-in numberformats +* §2 and those that have been explicitly added by the createor of the excel-file +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* §1 built-in numberformats +*--------------------------------------------------------------------* + ep_num_formats = ZCL_EXCEL_STYLE_NUMBER_FORMAT=>mt_built_in_num_formats. + +*--------------------------------------------------------------------* +* §2 Get non-internal numberformats that are found in the file explicitly + +* Following is an example how this part of a file could be set up +* <numFmts count="1"> +* <numFmt formatCode="#,###,###,###,##0.00" numFmtId="164"/> +* </numFmts> +*--------------------------------------------------------------------* + lo_node_numfmt ?= ip_xml->find_from_name( 'numFmt' ). + WHILE lo_node_numfmt IS BOUND. + + CLEAR ls_num_format. + + CREATE OBJECT ls_num_format-format. + ls_num_format-format->format_code = lo_node_numfmt->get_attribute( 'formatCode' ). + ls_num_format-id = lo_node_numfmt->get_attribute( 'numFmtId' ). + INSERT ls_num_format INTO TABLE ep_num_formats. + + lo_node_numfmt ?= lo_node_numfmt->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + method load_theme. + data theme type ref to zcl_excel_theme. + data: lo_theme_xml type ref to if_ixml_document. + create object theme. + lo_theme_xml = me->get_ixml_from_zip_archive( iv_path ). + theme->read_theme( io_theme_xml = lo_theme_xml ). + ip_excel->set_theme( io_theme = theme ). +endmethod. + + + + + + method LOAD_WORKBOOK. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Move macro-reading from zcl_excel_reader_xlsm to this class +* autodetect existance of macro/vba content +* Allow inputparameter to explicitly tell reader to ignore vba-content +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-10 +* - ... +* changes: renaming variables to naming conventions +* aligning code +* removing unused variables +* adding me-> where possible +* renaming variables to indicate what they are used for +* adding comments to explain what we are trying to achieve +* renaming i/o parameters: previous input-parameter ip_path holds a (full) filename and not a path --> rename to iv_workbook_full_filename +* ip_excel renamed while being at it --> rename to io_excel +*--------------------------------------------------------------------* +* issue #232 - Read worksheetstate hidden/veryHidden +* - Stefan Schmoecker, 2012-11-11 +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmoecker, 2012-12-02 +* changes: correction in named ranges to correctly attach +* sheetlocal names/ranges to the correct sheet +*--------------------------------------------------------------------* +* issue#284 - Copied formulae ignored when reading excelfile +* - Stefan Schmoecker, 2013-08-02 +* changes: initialize area to hold referenced formulaedata +* after all worksheets have been read resolve formuae +*--------------------------------------------------------------------* + + CONSTANTS: lcv_shared_strings TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', + lcv_worksheet TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', + lcv_styles TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + lcv_vba_project TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', "#EC NEEDED for future incorporation of XLSM-reader + lcv_theme TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', +*--------------------------------------------------------------------* +* #232: Read worksheetstate hidden/veryHidden - begin data declarations +*--------------------------------------------------------------------* + lcv_worksheet_state_hidden TYPE string VALUE 'hidden', + lcv_worksheet_state_veryhidden TYPE string VALUE 'veryHidden'. +*--------------------------------------------------------------------* +* #232: Read worksheetstate hidden/veryHidden - end data declarations +*--------------------------------------------------------------------* + + DATA: + lv_path TYPE string, + lv_filename TYPE chkfile, + lv_full_filename TYPE string, + + lo_rels_workbook TYPE REF TO if_ixml_document, + lt_worksheets TYPE STANDARD TABLE OF t_relationship WITH NON-UNIQUE DEFAULT KEY, + lo_workbook TYPE REF TO if_ixml_document, + lv_workbook_index TYPE i, + lv_worksheet_path TYPE string, + ls_sheet TYPE t_sheet, + + lo_node TYPE REF TO if_ixml_element, + ls_relationship TYPE t_relationship, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lv_worksheet_title TYPE zexcel_sheet_title, + lv_tabix TYPE sytabix, " #235 - repeat rows/cols. Needed to link defined name to correct worksheet + + ls_range TYPE t_range, + lv_range_value TYPE zexcel_range_value, +*--------------------------------------------------------------------* +* #229: Set active worksheet - begin data declarations +*--------------------------------------------------------------------* + lv_active_sheet_string TYPE string, + lv_zexcel_active_worksheet TYPE zexcel_active_worksheet, +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns - added autofilter support while changing this section + lo_autofilter TYPE REF TO zcl_excel_autofilter, + ls_area TYPE zexcel_s_autofilter_area, + lv_col_start_alpha TYPE zexcel_cell_column_alpha, + lv_col_end_alpha TYPE zexcel_cell_column_alpha, + lv_row_start TYPE zexcel_cell_row, + lv_row_end TYPE zexcel_cell_row , + lv_regex TYPE string, + lv_range_value_1 TYPE zexcel_range_value, + lv_range_value_2 TYPE zexcel_range_value. +*--------------------------------------------------------------------* +* #229: Set active worksheet - end data declarations +*--------------------------------------------------------------------* + FIELD-SYMBOLS: <worksheet> TYPE t_relationship. + + +*--------------------------------------------------------------------* + +* §1 Get the position of files related to this workbook +* Usually this will be <root>/xl/workbook.xml +* Thus the workbookroot will be <root>/xl/ +* The position of all related files will be given in file +* <workbookroot>/_rels/<workbookfilename>.rels and their positions +* be be given relative to the workbookroot + +* Following is an example how this file could be set up + +* <?xml version="1.0" encoding="UTF-8" standalone="true"?> +* <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> +* <Relationship Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Id="rId6"/> +* <Relationship Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Id="rId5"/> +* <Relationship Target="worksheets/sheet1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId1"/> +* <Relationship Target="worksheets/sheet2.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId2"/> +* <Relationship Target="worksheets/sheet3.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId3"/> +* <Relationship Target="worksheets/sheet4.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId4"/> +* <Relationship Target="sharedStrings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Id="rId7"/> +* </Relationships> +* +* §2 Load data that is relevant to the complete workbook +* Currently supported is: +* §2.1 Shared strings - This holds all strings that are used in all worksheets +* §2.2 Styles - This holds all styles that are used in all worksheets +* §2.3 Worksheets - For each worksheet in the workbook one entry appears here to point to the file that holds the content of this worksheet +* §2.4 [Themes] - not supported +* §2.5 [VBA (Macro)] - supported in class zcl_excel_reader_xlsm but should be moved here and autodetect +* ... +* +* §3 Some information is held in the workbookfile as well +* §3.1 Names and order of of worksheets +* §3.2 Active worksheet +* §3.3 Defined names +* ... +* Following is an example how this file could be set up + +* <?xml version="1.0" encoding="UTF-8" standalone="true"?> +* <workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> +* <fileVersion rupBuild="4506" lowestEdited="4" lastEdited="4" appName="xl"/> +* <workbookPr defaultThemeVersion="124226"/> +* <bookViews> +* <workbookView activeTab="1" windowHeight="8445" windowWidth="19035" yWindow="120" xWindow="120"/> +* </bookViews> +* <sheets> +* <sheet r:id="rId1" sheetId="1" name="Sheet1"/> +* <sheet r:id="rId2" sheetId="2" name="Sheet2"/> +* <sheet r:id="rId3" sheetId="3" name="Sheet3" state="hidden"/> +* <sheet r:id="rId4" sheetId="4" name="Sheet4"/> +* </sheets> +* <definedNames/> +* <calcPr calcId="125725"/> +* </workbook> +*--------------------------------------------------------------------* + + CLEAR me->mt_ref_formulae. " ins issue#284 + +*--------------------------------------------------------------------* +* §1 Get the position of files related to this workbook +* Entry into this method is with the filename of the workbook +*--------------------------------------------------------------------* + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = iv_workbook_full_filename + IMPORTING + stripped_name = lv_filename + file_path = lv_path. + + CONCATENATE lv_path '_rels/' lv_filename '.rels' + INTO lv_full_filename. + lo_rels_workbook = me->get_ixml_from_zip_archive( lv_full_filename ). + + lo_node ?= lo_rels_workbook->find_from_name( 'Relationship' ). "#EC NOTEXT + WHILE lo_node IS BOUND. + + me->fill_struct_from_attributes( EXPORTING ip_element = lo_node CHANGING cp_structure = ls_relationship ). + + CASE ls_relationship-type. + +*--------------------------------------------------------------------* +* §2.1 Shared strings - This holds all strings that are used in all worksheets +*--------------------------------------------------------------------* + WHEN lcv_shared_strings. + CONCATENATE lv_path ls_relationship-target + INTO lv_full_filename. + me->load_shared_strings( lv_full_filename ). + +*--------------------------------------------------------------------* +* §2.3 Worksheets +* For each worksheet in the workbook one entry appears here to point to the file that holds the content of this worksheet +* Shared strings and styles have to be present before we can start with creating the worksheets +* thus we only store this information for use when parsing the workbookfile for sheetinformations +*--------------------------------------------------------------------* + WHEN lcv_worksheet. + APPEND ls_relationship TO lt_worksheets. + +*--------------------------------------------------------------------* +* §2.2 Styles - This holds the styles that are used in all worksheets +*--------------------------------------------------------------------* + WHEN lcv_styles. + CONCATENATE lv_path ls_relationship-target + INTO lv_full_filename. + me->load_styles( ip_path = lv_full_filename + ip_excel = io_excel ). + me->load_dxf_styles( iv_path = lv_full_filename + io_excel = io_excel ). + when lcv_theme. + CONCATENATE lv_path ls_relationship-target + INTO lv_full_filename. + me->load_theme( + exporting + iv_path = lv_full_filename + ip_excel = io_excel " Excel creator + ). + WHEN OTHERS. + + ENDCASE. + + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + +*--------------------------------------------------------------------* +* §3 Some information held in the workbookfile +*--------------------------------------------------------------------* + lo_workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). + +*--------------------------------------------------------------------* +* §3.1 Names and order of of worksheets +*--------------------------------------------------------------------* + lo_node ?= lo_workbook->find_from_name( 'sheet' ). + lv_workbook_index = 1. + WHILE lo_node IS BOUND. + + me->fill_struct_from_attributes( EXPORTING + ip_element = lo_node + CHANGING + cp_structure = ls_sheet ). +*--------------------------------------------------------------------* +* Create new worksheet in workbook with correct name +*--------------------------------------------------------------------* + lv_worksheet_title = ls_sheet-name. + IF lv_workbook_index = 1. " First sheet has been added automatically by creating io_excel + lo_worksheet = io_excel->get_active_worksheet( ). + lo_worksheet->set_title( lv_worksheet_title ). + ELSE. + lo_worksheet = io_excel->add_new_worksheet( lv_worksheet_title ). + ENDIF. +*--------------------------------------------------------------------* +* #232 - Read worksheetstate hidden/veryHidden - begin of coding +* Set status hidden if necessary +*--------------------------------------------------------------------* + CASE ls_sheet-state. + + WHEN lcv_worksheet_state_hidden. + lo_worksheet->zif_excel_sheet_properties~hidden = zif_excel_sheet_properties=>c_hidden. + + WHEN lcv_worksheet_state_veryhidden. + lo_worksheet->zif_excel_sheet_properties~hidden = zif_excel_sheet_properties=>c_veryhidden. + + ENDCASE. +*--------------------------------------------------------------------* +* #232 - Read worksheetstate hidden/veryHidden - end of coding +*--------------------------------------------------------------------* +*--------------------------------------------------------------------* +* Load worksheetdata +*--------------------------------------------------------------------* + READ TABLE lt_worksheets ASSIGNING <worksheet> WITH KEY id = ls_sheet-id. + IF sy-subrc = 0. + <worksheet>-sheetid = ls_sheet-sheetid. "ins #235 - repeat rows/cols - needed to identify correct sheet + CONCATENATE lv_path <worksheet>-target + INTO lv_worksheet_path. + me->load_worksheet( ip_path = lv_worksheet_path + io_worksheet = lo_worksheet ). + <worksheet>-worksheet = lo_worksheet. + ENDIF. + + lo_node ?= lo_node->get_next( ). + ADD 1 TO lv_workbook_index. + + ENDWHILE. + SORT lt_worksheets BY sheetid. " needed for localSheetid -referencing + +*--------------------------------------------------------------------* +* #284: Set active worksheet - Resolve referenced formulae to +* explicit formulae those cells +*--------------------------------------------------------------------* + me->resolve_referenced_formulae( ). + " ins issue#284 +*--------------------------------------------------------------------* +* #229: Set active worksheet - begin coding +* §3.2 Active worksheet +*--------------------------------------------------------------------* + lv_zexcel_active_worksheet = 1. " First sheet = active sheet if nothing else specified. + lo_node ?= lo_workbook->find_from_name( 'workbookView' ). + IF lo_node IS BOUND. + lv_active_sheet_string = lo_node->get_attribute( 'activeTab' ). + TRY. + lv_zexcel_active_worksheet = lv_active_sheet_string + 1. " EXCEL numbers the sheets from 0 onwards --> index into worksheettable is increased by one + CATCH cx_sy_conversion_error. "#EC NO_HANDLER - error here --> just use the default 1st sheet + ENDTRY. + ENDIF. + io_excel->set_active_sheet_index( lv_zexcel_active_worksheet ). +*--------------------------------------------------------------------* +* #229: Set active worksheet - end coding +*--------------------------------------------------------------------* + + +*--------------------------------------------------------------------* +* §3.3 Defined names +* So far I have encountered these +* - named ranges - sheetlocal +* - named ranges - workbookglobal +* - autofilters - sheetlocal ( special range ) +* - repeat rows/cols - sheetlocal ( special range ) +* +*--------------------------------------------------------------------* + lo_node ?= lo_workbook->find_from_name( 'definedName' ). + WHILE lo_node IS BOUND. + + CLEAR lo_range. "ins issue #235 - repeat rows/cols + me->fill_struct_from_attributes( EXPORTING + ip_element = lo_node + CHANGING + cp_structure = ls_range ). + lv_range_value = lo_node->get_value( ). + + IF ls_range-localsheetid IS NOT INITIAL. " issue #163+ +* READ TABLE lt_worksheets ASSIGNING <worksheet> WITH KEY id = ls_range-localsheetid. "del issue #235 - repeat rows/cols " issue #163+ +* lo_range = <worksheet>-worksheet->add_new_range( ). "del issue #235 - repeat rows/cols " issue #163+ +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns - begin +*--------------------------------------------------------------------* + lv_tabix = ls_range-localsheetid + 1. + READ TABLE lt_worksheets ASSIGNING <worksheet> INDEX lv_tabix. + IF sy-subrc = 0. + CASE ls_range-name. + +*--------------------------------------------------------------------* +* insert autofilters +*--------------------------------------------------------------------* + WHEN zcl_excel_autofilters=>c_autofilter. + lo_autofilter = io_excel->add_new_autofilter( io_sheet = <worksheet>-worksheet ) . + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range_value + IMPORTING e_column_start = lv_col_start_alpha + e_column_end = lv_col_end_alpha + e_row_start = ls_area-row_start + e_row_end = ls_area-row_end ). + ls_area-col_start = zcl_excel_common=>convert_column2int( lv_col_start_alpha ). + ls_area-col_end = zcl_excel_common=>convert_column2int( lv_col_end_alpha ). + lo_autofilter->set_filter_area( is_area = ls_area ). + +*--------------------------------------------------------------------* +* repeat print rows/columns +*--------------------------------------------------------------------* + WHEN zif_excel_sheet_printsettings=>gcv_print_title_name. + lo_range = <worksheet>-worksheet->add_new_range( ). +*--------------------------------------------------------------------* +* This might be a temporary solution. Maybe ranges get be reworked +* to support areas consisting of multiple rectangles +* But for now just split the range into row and columnpart +*--------------------------------------------------------------------* + CLEAR:lv_range_value_1, + lv_range_value_2. + IF lv_range_value IS INITIAL. +* Empty --> nothing to do + ELSE. + IF lv_range_value(1) = `'`. " Escaped + lv_regex = `^('[^']*')+![^,]*,`. + ELSE. + lv_regex = `^[^!]*![^,]*,`. + ENDIF. +* Split into two ranges if necessary + FIND REGEX lv_regex IN lv_range_value MATCH LENGTH sy-fdpos. + IF sy-subrc = 0 AND sy-fdpos > 0. + lv_range_value_2 = lv_range_value+sy-fdpos. + SUBTRACT 1 FROM sy-fdpos. + lv_range_value_1 = lv_range_value(sy-fdpos). + ELSE. + lv_range_value_1 = lv_range_value. + ENDIF. + ENDIF. +* 1st range + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range_value_1 + IMPORTING e_column_start = lv_col_start_alpha + e_column_end = lv_col_end_alpha + e_row_start = lv_row_start + e_row_end = lv_row_end ). + IF lv_col_start_alpha IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_columns( iv_columns_from = lv_col_start_alpha + iv_columns_to = lv_col_end_alpha ). + ENDIF. + IF lv_row_start IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_rows( iv_rows_from = lv_row_start + iv_rows_to = lv_row_end ). + ENDIF. + +* 2nd range + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = lv_range_value_2 + IMPORTING e_column_start = lv_col_start_alpha + e_column_end = lv_col_end_alpha + e_row_start = lv_row_start + e_row_end = lv_row_end ). + IF lv_col_start_alpha IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_columns( iv_columns_from = lv_col_start_alpha + iv_columns_to = lv_col_end_alpha ). + ENDIF. + IF lv_row_start IS NOT INITIAL. + <worksheet>-worksheet->zif_excel_sheet_printsettings~set_print_repeat_rows( iv_rows_from = lv_row_start + iv_rows_to = lv_row_end ). + ENDIF. + + WHEN OTHERS. + + ENDCASE. + ENDIF. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns - end +*--------------------------------------------------------------------* + ELSE. " issue #163+ + lo_range = io_excel->add_new_range( ). " issue #163+ + ENDIF. " issue #163+ +* lo_range = ip_excel->add_new_range( ). " issue #163- + IF lo_range IS BOUND. "ins issue #235 - repeat rows/cols + lo_range->name = ls_range-name. + lo_range->set_range_value( lv_range_value ). + ENDIF. "ins issue #235 - repeat rows/cols + lo_node ?= lo_node->get_next( ). + + ENDWHILE. + + endmethod. + + + + + + METHOD load_worksheet. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Header/footer +* +* Please don't just delete these ToDos if they are not +* needed but leave a comment that states this +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, +* - ... +* changes: renaming variables to naming conventions +* aligning code (started) +* add a list of open ToDos here +* adding comments to explain what we are trying to achieve (started) +*--------------------------------------------------------------------* +* issue #345 - Dump on small pagemargins +* Took the chance to modularize this very long method +* by extracting the code that needed correction into +* own method ( load_worksheet_pagemargins ) +*--------------------------------------------------------------------* + TYPES: BEGIN OF lty_cell, + r TYPE string, + t TYPE string, + s TYPE string, + END OF lty_cell. + + TYPES: BEGIN OF lty_column, + min TYPE string, + max TYPE string, + width TYPE float, + customwidth TYPE string, + style TYPE string, + bestfit TYPE string, + collapsed TYPE string, + hidden TYPE string, + outlinelevel TYPE string, + END OF lty_column. + + TYPES: BEGIN OF lty_sheetview, + showgridlines TYPE zexcel_show_gridlines, + tabselected TYPE string, + zoomscalenormal TYPE string, + workbookviewid TYPE string, + showrowcolheaders TYPE string, + END OF lty_sheetview. + + TYPES: BEGIN OF lty_mergecell, + ref TYPE string, + END OF lty_mergecell. + + TYPES: BEGIN OF lty_row, + r TYPE string, + customheight TYPE string, + ht TYPE float, + spans TYPE string, + thickbot TYPE string, + customformat TYPE string, + thicktop TYPE string, + collapsed TYPE string, + hidden TYPE string, + outlinelevel TYPE string, + END OF lty_row. + + TYPES: BEGIN OF lty_page_setup, + id TYPE string, + orientation TYPE string, + scale TYPE string, + fittoheight TYPE string, + fittowidth TYPE string, + END OF lty_page_setup. + + TYPES: BEGIN OF lty_sheetformatpr, + customheight TYPE string, + defaultrowheight TYPE string, + customwidth TYPE string, + defaultcolwidth TYPE string, + END OF lty_sheetformatpr. + + TYPES: BEGIN OF lty_headerfooter, + alignwithmargins TYPE string, + differentoddeven TYPE string, + END OF lty_headerfooter. + + TYPES: BEGIN OF lty_tabcolor, + rgb TYPE string, + theme TYPE string, + END OF lty_tabcolor. + + TYPES: BEGIN OF lty_datavalidation, + type TYPE zexcel_data_val_type, + allowblank TYPE flag, + showinputmessage TYPE flag, + showerrormessage TYPE flag, + showdropdown TYPE flag, + operator TYPE zexcel_data_val_operator, + formula1 TYPE zexcel_validation_formula1, + formula2 TYPE zexcel_validation_formula1, + sqref TYPE string, + cell_column TYPE zexcel_cell_column_alpha, + cell_column_to TYPE zexcel_cell_column_alpha, + cell_row TYPE zexcel_cell_row, + cell_row_to TYPE zexcel_cell_row, + error TYPE string, + errortitle TYPE string, + prompt TYPE string, + prompttitle TYPE string, + errorstyle TYPE zexcel_data_val_error_style, + END OF lty_datavalidation. + + + + CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_true_int TYPE string VALUE '1', + lc_rel_drawing TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', + lc_rel_hyperlink TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', + lc_rel_printer TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings'. + + DATA: lo_ixml_worksheet TYPE REF TO if_ixml_document, + lo_ixml_cells TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml_iterator2 TYPE REF TO if_ixml_node_iterator, + lo_ixml_row_elem TYPE REF TO if_ixml_element, + lo_ixml_cell_elem TYPE REF TO if_ixml_element, + ls_cell TYPE lty_cell, + lv_index TYPE i, + lo_ixml_value_elem TYPE REF TO if_ixml_element, + lo_ixml_formula_elem TYPE REF TO if_ixml_element, + lv_cell_value TYPE zexcel_cell_value, + lv_cell_formula TYPE zexcel_cell_formula, + lv_cell_column TYPE zexcel_cell_column_alpha, + lv_cell_row TYPE zexcel_cell_row, + lo_excel_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style, + + lo_ixml_imension_elem TYPE REF TO if_ixml_element, "#+234 + lv_dimension_range TYPE string, "#+234 + + lo_ixml_sheetview_elem TYPE REF TO if_ixml_element, + ls_sheetview TYPE lty_sheetview, + lo_ixml_pane_elem TYPE REF TO if_ixml_element, + ls_excel_pane TYPE zexcel_pane, + lv_pane_cell_row TYPE zexcel_cell_row, + lv_pane_cell_col_a TYPE zexcel_cell_column_alpha, + lv_pane_cell_col TYPE zexcel_cell_column, + + lo_ixml_mergecells TYPE REF TO if_ixml_node_collection, + lo_ixml_mergecell_elem TYPE REF TO if_ixml_element, + ls_mergecell TYPE lty_mergecell, + lv_merge_column_start TYPE zexcel_cell_column_alpha, + lv_merge_column_end TYPE zexcel_cell_column_alpha, + lv_merge_row_start TYPE zexcel_cell_row, + lv_merge_row_end TYPE zexcel_cell_row, + + lo_ixml_sheetformatpr_elem TYPE REF TO if_ixml_element, + ls_sheetformatpr TYPE lty_sheetformatpr, + lv_height TYPE float, + + lo_ixml_headerfooter_elem TYPE REF TO if_ixml_element, + ls_headerfooter TYPE lty_headerfooter, + ls_odd_header TYPE zexcel_s_worksheet_head_foot, + ls_odd_footer TYPE zexcel_s_worksheet_head_foot, + ls_even_header TYPE zexcel_s_worksheet_head_foot, + ls_even_footer TYPE zexcel_s_worksheet_head_foot, + lo_ixml_hf_value_elem TYPE REF TO if_ixml_element, + + lo_ixml_pagesetup_elem TYPE REF TO if_ixml_element, + lo_ixml_sheetpr TYPE REF TO if_ixml_element, + lv_fit_to_page TYPE string, + ls_pagesetup TYPE lty_page_setup, + + lo_ixml_columns TYPE REF TO if_ixml_node_collection, + lo_ixml_column_elem TYPE REF TO if_ixml_element, + ls_column TYPE lty_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lv_outline_level TYPE int4, + + lo_ixml_tabcolor TYPE REF TO if_ixml_element, + ls_tabcolor TYPE lty_tabcolor, + ls_excel_s_tabcolor TYPE zexcel_s_tabcolor, + + lo_ixml_rows TYPE REF TO if_ixml_node_collection, + ls_row TYPE lty_row, + lv_max_col TYPE i, "for use with SPANS element +* lv_min_col TYPE i, "for use with SPANS element " not in use currently + lv_max_col_s TYPE char10, "for use with SPANS element + lv_min_col_s TYPE char10, "for use with SPANS element + lo_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, +*--- End of current code aligning ------------------------------------------------------------------- + + lv_path TYPE string, + lo_ixml_node TYPE REF TO if_ixml_element, + ls_relationship TYPE t_relationship, + lo_ixml_rels_worksheet TYPE REF TO if_ixml_document, + lv_rels_worksheet_path TYPE string, + lv_stripped_name TYPE chkfile, + lv_dirname TYPE string, + + lt_external_hyperlinks TYPE gtt_external_hyperlinks, + ls_external_hyperlink LIKE LINE OF lt_external_hyperlinks, + + lo_ixml_datavalidations TYPE REF TO if_ixml_node_collection, + lo_ixml_datavalidation_elem TYPE REF TO if_ixml_element, + ls_datavalidation TYPE lty_datavalidation, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lv_datavalidation_range TYPE string, + lt_datavalidation_range TYPE TABLE OF string. + +*--------------------------------------------------------------------* +* §2 We need to read the the file "\\_rels\.rels" because it tells +* us where in this folder structure the data for the workbook +* is located in the xlsx zip-archive +* +* The xlsx Zip-archive has generally the following folder structure: +* <root> | +* |--> _rels +* |--> doc_Props +* |--> xl | +* |--> _rels +* |--> theme +* |--> worksheets +*--------------------------------------------------------------------* + + " Read Workbook Relationships + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = ip_path + IMPORTING + stripped_name = lv_stripped_name + file_path = lv_dirname. + CONCATENATE lv_dirname '_rels/' lv_stripped_name '.rels' + INTO lv_rels_worksheet_path. + TRY. " +#222 _rels/xxx.rels might not be present. If not found there can be no drawings --> just ignore this section + lo_ixml_rels_worksheet = me->get_ixml_from_zip_archive( lv_rels_worksheet_path ). + lo_ixml_node ?= lo_ixml_rels_worksheet->find_from_name( 'Relationship' ). + CATCH zcx_excel. "#EC NO_HANDLER +#222 + " +#222 No errorhandling necessary - node will be unbound if error occurs + ENDTRY. " +#222 + WHILE lo_ixml_node IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_node + CHANGING + cp_structure = ls_relationship ). + CONCATENATE lv_dirname ls_relationship-target INTO lv_path. + lv_path = resolve_path( lv_path ). + + CASE ls_relationship-type. + WHEN lc_rel_drawing. + " Read Drawings +* Issue # 339 Not all drawings are in the path mentioned below. +* Some Excel elements like textfields (which we don't support ) have a drawing-part in the relationsships +* but no "xl/drawings/_rels/drawing____.xml.rels" part. +* Since we don't support these there is no need to read them. Catching exceptions thrown +* in the "load_worksheet_drawing" shouldn't lead to an abortion of the reading + TRY. + me->load_worksheet_drawing( ip_path = lv_path + io_worksheet = io_worksheet ). + CATCH zcx_excel. "--> then ignore it + ENDTRY. + + WHEN lc_rel_printer. + " Read Printer settings + + WHEN lc_rel_hyperlink. + MOVE-CORRESPONDING ls_relationship TO ls_external_hyperlink. + INSERT ls_external_hyperlink INTO TABLE lt_external_hyperlinks. + + WHEN OTHERS. + ENDCASE. + + lo_ixml_node ?= lo_ixml_node->get_next( ). + ENDWHILE. + + + lo_ixml_worksheet = me->get_ixml_from_zip_archive( ip_path ). + + + lo_ixml_tabcolor ?= lo_ixml_worksheet->find_from_name( 'tabColor' ). + IF lo_ixml_tabcolor IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_tabcolor + CHANGING + cp_structure = ls_tabcolor ). +* Theme not supported yet + IF ls_tabcolor-rgb IS NOT INITIAL. + ls_excel_s_tabcolor-rgb = ls_tabcolor-rgb. + io_worksheet->set_tabcolor( ls_excel_s_tabcolor ). + ENDIF. + ENDIF. + + lo_ixml_rows = lo_ixml_worksheet->get_elements_by_tag_name( name = 'row' ). + lo_ixml_iterator = lo_ixml_rows->create_iterator( ). + lo_ixml_row_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_row_elem IS BOUND. + + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_row_elem + CHANGING + cp_structure = ls_row ). + SPLIT ls_row-spans AT ':' INTO lv_min_col_s lv_max_col_s. + lv_index = lv_max_col_s. + IF lv_index > lv_max_col. + lv_max_col = lv_index. + ENDIF. + lv_cell_row = ls_row-r. + IF ls_row-customheight = '1' + OR ls_row-collapsed = lc_xml_attr_true + OR ls_row-collapsed = lc_xml_attr_true_int + OR ls_row-hidden = lc_xml_attr_true + OR ls_row-hidden = lc_xml_attr_true_int + OR ls_row-outlinelevel > '0'. + lo_row_dimension = io_worksheet->get_row_dimension( lv_cell_row ). + IF ls_row-customheight = '1'. + lo_row_dimension->set_row_height( ls_row-ht ). + ENDIF. + + IF ls_row-collapsed = lc_xml_attr_true + OR ls_row-collapsed = lc_xml_attr_true_int. + lo_row_dimension->set_collapsed( abap_true ). + ENDIF. + + IF ls_row-hidden = lc_xml_attr_true + OR ls_row-hidden = lc_xml_attr_true_int. + lo_row_dimension->set_visible( abap_false ). + ENDIF. + + IF ls_row-outlinelevel > ''. +* outline_level = condense( row-outlineLevel ). "For basis 7.02 and higher + CONDENSE ls_row-outlinelevel. + lv_outline_level = ls_row-outlinelevel. + IF lv_outline_level > 0. + lo_row_dimension->set_outline_level( lv_outline_level ). + ENDIF. + ENDIF. + ENDIF. + + lo_ixml_cells = lo_ixml_row_elem->get_elements_by_tag_name( name = 'c' ). + lo_ixml_iterator2 = lo_ixml_cells->create_iterator( ). + lo_ixml_cell_elem ?= lo_ixml_iterator2->get_next( ). + WHILE lo_ixml_cell_elem IS BOUND. + CLEAR: lv_cell_value, + lv_cell_formula, + lv_style_guid. + + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_cell_elem CHANGING cp_structure = ls_cell ). + + lo_ixml_value_elem = lo_ixml_cell_elem->find_from_name( name = 'v' ). + + CASE ls_cell-t. + WHEN 's'. " String values are stored as index in shared string table + lv_index = lo_ixml_value_elem->get_value( ) + 1. + READ TABLE shared_strings INTO lv_cell_value INDEX lv_index. + WHEN 'inlineStr'. " inlineStr values are kept in special node + lo_ixml_value_elem = lo_ixml_cell_elem->find_from_name( name = 'is' ). + IF lo_ixml_value_elem IS BOUND. + lv_cell_value = lo_ixml_value_elem->get_value( ). + ENDIF. + WHEN OTHERS. "other types are stored directly + IF lo_ixml_value_elem IS BOUND. + lv_cell_value = lo_ixml_value_elem->get_value( ). + ENDIF. + ENDCASE. + + CLEAR lv_style_guid. + "read style based on index + IF ls_cell-s IS NOT INITIAL. + lv_index = ls_cell-s + 1. + READ TABLE styles INTO lo_excel_style INDEX lv_index. + IF sy-subrc = 0. + lv_style_guid = lo_excel_style->get_guid( ). + ENDIF. + ENDIF. + + lo_ixml_formula_elem = lo_ixml_cell_elem->find_from_name( name = 'f' ). + IF lo_ixml_formula_elem IS BOUND. + lv_cell_formula = lo_ixml_formula_elem->get_value( ). +*--------------------------------------------------------------------* +* Begin of insertion issue#284 - Copied formulae not +*--------------------------------------------------------------------* + DATA: BEGIN OF ls_formula_attributes, + ref TYPE string, + si TYPE i, + t TYPE string, + END OF ls_formula_attributes, + ls_ref_formula TYPE ty_ref_formulae. + + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_formula_elem CHANGING cp_structure = ls_formula_attributes ). + IF ls_formula_attributes-t = 'shared'. + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_cell-r + IMPORTING + e_column = lv_cell_column + e_row = lv_cell_row ). + + TRY. + CLEAR ls_ref_formula. + ls_ref_formula-sheet = io_worksheet. + ls_ref_formula-row = lv_cell_row. + ls_ref_formula-column = zcl_excel_common=>convert_column2int( lv_cell_column ). + ls_ref_formula-si = ls_formula_attributes-si. + ls_ref_formula-ref = ls_formula_attributes-ref. + ls_ref_formula-formula = lv_cell_formula. + INSERT ls_ref_formula INTO TABLE me->mt_ref_formulae. + CATCH cx_root. + BREAK-POINT. + ENDTRY. + ENDIF. +*--------------------------------------------------------------------* +* End of insertion issue#284 - Copied formulae not +*--------------------------------------------------------------------* + ENDIF. + + IF lv_cell_value IS NOT INITIAL + OR lv_cell_formula IS NOT INITIAL + OR lv_style_guid IS NOT INITIAL. + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_cell-r + IMPORTING + e_column = lv_cell_column + e_row = lv_cell_row ). + io_worksheet->set_cell( ip_column = lv_cell_column " cell_elem Column + ip_row = lv_cell_row " cell_elem row_elem + ip_value = lv_cell_value " cell_elem Value + ip_formula = lv_cell_formula + ip_data_type = ls_cell-t + ip_style = lv_style_guid ). + ENDIF. + lo_ixml_cell_elem ?= lo_ixml_iterator2->get_next( ). + ENDWHILE. + lo_ixml_row_elem ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + +*--------------------------------------------------------------------* +*#234 - column width not read correctly - begin of coding +* reason - libre office doesn't use SPAN in row - definitions +*--------------------------------------------------------------------* + IF lv_max_col = 0. + lo_ixml_imension_elem = lo_ixml_worksheet->find_from_name( name = 'dimension' ). + IF lo_ixml_imension_elem IS BOUND. + lv_dimension_range = lo_ixml_imension_elem->get_attribute( 'ref' ). + IF lv_dimension_range CS ':'. + REPLACE REGEX '\D+\d+:(\D+)\d+' IN lv_dimension_range WITH '$1'. " Get max column + ELSE. + REPLACE REGEX '(\D+)\d+' IN lv_dimension_range WITH '$1'. " Get max column + ENDIF. + lv_max_col = zcl_excel_common=>convert_column2int( lv_dimension_range ). + ENDIF. + ENDIF. +*--------------------------------------------------------------------* +*#234 - column width not read correctly - end of coding +*--------------------------------------------------------------------* + + "Get the customized column width + lo_ixml_columns = lo_ixml_worksheet->get_elements_by_tag_name( name = 'col' ). + lo_ixml_iterator = lo_ixml_columns->create_iterator( ). + lo_ixml_column_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_column_elem IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_column_elem + CHANGING + cp_structure = ls_column ). + lo_ixml_column_elem ?= lo_ixml_iterator->get_next( ). + IF ls_column-customwidth = lc_xml_attr_true + OR ls_column-customwidth = lc_xml_attr_true_int + OR ls_column-bestfit = lc_xml_attr_true + OR ls_column-bestfit = lc_xml_attr_true_int + OR ls_column-collapsed = lc_xml_attr_true + OR ls_column-collapsed = lc_xml_attr_true_int + OR ls_column-hidden = lc_xml_attr_true + OR ls_column-hidden = lc_xml_attr_true_int + OR ls_column-outlinelevel > '' + OR ls_column-style > ''. + lv_index = ls_column-min. + WHILE lv_index <= ls_column-max AND lv_index <= lv_max_col. + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_index ). + lo_column_dimension = io_worksheet->get_column_dimension( lv_column_alpha ). + + IF ls_column-customwidth = lc_xml_attr_true + OR ls_column-customwidth = lc_xml_attr_true_int + OR ls_column-width IS NOT INITIAL. "+#234 + lo_column_dimension->set_width( ls_column-width ). + ENDIF. + + IF ls_column-bestfit = lc_xml_attr_true + OR ls_column-bestfit = lc_xml_attr_true_int. + lo_column_dimension->set_auto_size( abap_true ). + ENDIF. + + IF ls_column-collapsed = lc_xml_attr_true + OR ls_column-collapsed = lc_xml_attr_true_int. + lo_column_dimension->set_collapsed( abap_true ). + ENDIF. + + IF ls_column-hidden = lc_xml_attr_true + OR ls_column-hidden = lc_xml_attr_true_int. + lo_column_dimension->set_visible( abap_false ). + ENDIF. + + IF ls_column-outlinelevel > ''. +* outline_level = condense( column-outlineLevel ). + CONDENSE ls_column-outlinelevel. + lv_outline_level = ls_column-outlinelevel. + IF lv_outline_level > 0. + lo_column_dimension->set_outline_level( lv_outline_level ). + ENDIF. + ENDIF. + + IF ls_column-style > ''. + sy-index = ls_column-style + 1. + READ TABLE styles INTO lo_excel_style INDEX sy-index. + DATA: dummy_zexcel_cell_style TYPE zexcel_cell_style. + dummy_zexcel_cell_style = lo_excel_style->get_guid( ). + lo_column_dimension->set_column_style_by_guid( dummy_zexcel_cell_style ). + ENDIF. + + ADD 1 TO lv_index. + ENDWHILE. + ENDIF. + +* issue #367 - hide columns from + IF ls_column-max = zcl_excel_common=>c_excel_sheet_max_col. " Max = very right column + IF ls_column-hidden = 1 " all hidden + AND ls_column-min > 0. + io_worksheet->zif_excel_sheet_properties~hide_columns_from = zcl_excel_common=>convert_column2alpha( ls_column-min ). + ELSEIF ls_column-style > ''. + sy-index = ls_column-style + 1. + READ TABLE styles INTO lo_excel_style INDEX sy-index. + dummy_zexcel_cell_style = lo_excel_style->get_guid( ). +* Set style for remaining columns + io_worksheet->zif_excel_sheet_properties~set_style( dummy_zexcel_cell_style ). + ENDIF. + ENDIF. + + + ENDWHILE. + + "Now we need to get information from the sheetView node + lo_ixml_sheetview_elem = lo_ixml_worksheet->find_from_name( name = 'sheetView' ). + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_sheetview_elem CHANGING cp_structure = ls_sheetview ). + IF ls_sheetview-showgridlines IS INITIAL OR + ls_sheetview-showgridlines = lc_xml_attr_true OR + ls_sheetview-showgridlines = lc_xml_attr_true_int. + "If the attribute is not specified or set to true, we will show grid lines + ls_sheetview-showgridlines = abap_true. + ELSE. + ls_sheetview-showgridlines = abap_false. + ENDIF. + io_worksheet->set_show_gridlines( ls_sheetview-showgridlines ). + + + "Add merge cell information + lo_ixml_mergecells = lo_ixml_worksheet->get_elements_by_tag_name( name = 'mergeCell' ). + lo_ixml_iterator = lo_ixml_mergecells->create_iterator( ). + lo_ixml_mergecell_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_mergecell_elem IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_mergecell_elem + CHANGING + cp_structure = ls_mergecell ). + zcl_excel_common=>convert_range2column_a_row( EXPORTING + i_range = ls_mergecell-ref + IMPORTING + e_column_start = lv_merge_column_start + e_column_end = lv_merge_column_end + e_row_start = lv_merge_row_start + e_row_end = lv_merge_row_end ). + lo_ixml_mergecell_elem ?= lo_ixml_iterator->get_next( ). + io_worksheet->set_merge( EXPORTING + ip_column_start = lv_merge_column_start + ip_column_end = lv_merge_column_end + ip_row = lv_merge_row_start + ip_row_to = lv_merge_row_end ). + ENDWHILE. + + " read sheet format properties + lo_ixml_sheetformatpr_elem = lo_ixml_worksheet->find_from_name( 'sheetFormatPr' ). + IF lo_ixml_sheetformatpr_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_sheetformatpr_elem CHANGING cp_structure = ls_sheetformatpr ). + IF ls_sheetformatpr-customheight = '1'. + lv_height = ls_sheetformatpr-defaultrowheight. + lo_row_dimension = io_worksheet->get_default_row_dimension( ). + lo_row_dimension->set_row_height( lv_height ). + ENDIF. + + " TODO... column + ENDIF. + + " Read in page margins + me->load_worksheet_pagemargins( EXPORTING + io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet ). + +* FitToPage + lo_ixml_sheetpr ?= lo_ixml_worksheet->find_from_name( 'pageSetUpPr' ). + IF lo_ixml_sheetpr IS BOUND. + + lv_fit_to_page = lo_ixml_sheetpr->get_attribute_ns( 'fitToPage' ). + IF lv_fit_to_page IS NOT INITIAL. + io_worksheet->sheet_setup->fit_to_page = 'X'. + ENDIF. + ENDIF. + " Read in page setup + lo_ixml_pagesetup_elem = lo_ixml_worksheet->find_from_name( 'pageSetup' ). + IF lo_ixml_pagesetup_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_pagesetup_elem + CHANGING + cp_structure = ls_pagesetup ). + io_worksheet->sheet_setup->orientation = ls_pagesetup-orientation. + io_worksheet->sheet_setup->scale = ls_pagesetup-scale. + IF io_worksheet->sheet_setup->fit_to_page = 'X'. + IF ls_pagesetup-fittowidth IS NOT INITIAL. + io_worksheet->sheet_setup->fit_to_width = ls_pagesetup-fittowidth. + ELSE. + io_worksheet->sheet_setup->fit_to_width = 1. " Default if not given - Excel doesn't write this to xml + ENDIF. + IF ls_pagesetup-fittoheight IS NOT INITIAL. + io_worksheet->sheet_setup->fit_to_height = ls_pagesetup-fittoheight. + ELSE. + io_worksheet->sheet_setup->fit_to_height = 1. " Default if not given - Excel doesn't write this to xml + ENDIF. + ENDIF. + ENDIF. + + + + " Read header footer + lo_ixml_headerfooter_elem = lo_ixml_worksheet->find_from_name( 'headerFooter' ). + IF lo_ixml_headerfooter_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_headerfooter_elem CHANGING cp_structure = ls_headerfooter ). + io_worksheet->sheet_setup->diff_oddeven_headerfooter = ls_headerfooter-differentoddeven. + + lo_ixml_hf_value_elem = lo_ixml_headerfooter_elem->find_from_name( 'oddFooter' ). + IF lo_ixml_hf_value_elem IS NOT INITIAL. + ls_odd_footer-left_value = lo_ixml_hf_value_elem->get_value( ). + ENDIF. + +* 2do§1 Header/footer + " TODO.. get the rest. + + io_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_odd_header + ip_odd_footer = ls_odd_footer + ip_even_header = ls_even_header + ip_even_footer = ls_even_footer ). + + ENDIF. + + " Start fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 + " Read pane + lo_ixml_pane_elem = lo_ixml_sheetview_elem->find_from_name( name = 'pane' ). + IF lo_ixml_pane_elem IS BOUND. + fill_struct_from_attributes( EXPORTING ip_element = lo_ixml_pane_elem CHANGING cp_structure = ls_excel_pane ). + " Issue #194 + " Replace REGEX with method from the common class + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_excel_pane-topleftcell + IMPORTING + e_column = lv_pane_cell_col_a " Cell Column + e_row = lv_pane_cell_row ). " Natural number + lv_pane_cell_col = zcl_excel_common=>convert_column2int( lv_pane_cell_col_a ). + SUBTRACT 1 FROM: lv_pane_cell_col, + lv_pane_cell_row. + IF lv_pane_cell_col > 0 + AND lv_pane_cell_row > 0. + io_worksheet->freeze_panes( ip_num_rows = lv_pane_cell_row + ip_num_columns = lv_pane_cell_col ). + ELSEIF lv_pane_cell_row > 0. + io_worksheet->freeze_panes( ip_num_rows = lv_pane_cell_row ). + ELSE. + io_worksheet->freeze_panes( ip_num_columns = lv_pane_cell_col ). + ENDIF. + ENDIF. + " End fix 194 Read attributes HIDDEN, OUTLINELEVEL, COLLAPSED in ZCL_EXCEL_READER_2007 + + " Start fix 276 Read data validations + lo_ixml_datavalidations = lo_ixml_worksheet->get_elements_by_tag_name( name = 'dataValidation' ). + lo_ixml_iterator = lo_ixml_datavalidations->create_iterator( ). + lo_ixml_datavalidation_elem ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_datavalidation_elem IS BOUND. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_datavalidation_elem + CHANGING + cp_structure = ls_datavalidation ). + CLEAR lo_ixml_formula_elem. + lo_ixml_formula_elem = lo_ixml_datavalidation_elem->find_from_name( name = 'formula1' ). + IF lo_ixml_formula_elem IS BOUND. + ls_datavalidation-formula1 = lo_ixml_formula_elem->get_value( ). + ENDIF. + CLEAR lo_ixml_formula_elem. + lo_ixml_formula_elem = lo_ixml_datavalidation_elem->find_from_name( name = 'formula2' ). + IF lo_ixml_formula_elem IS BOUND. + ls_datavalidation-formula2 = lo_ixml_formula_elem->get_value( ). + ENDIF. + SPLIT ls_datavalidation-sqref AT space INTO TABLE lt_datavalidation_range. + LOOP AT lt_datavalidation_range INTO lv_datavalidation_range. + zcl_excel_common=>convert_range2column_a_row( EXPORTING + i_range = lv_datavalidation_range + IMPORTING + e_column_start = ls_datavalidation-cell_column + e_column_end = ls_datavalidation-cell_column_to + e_row_start = ls_datavalidation-cell_row + e_row_end = ls_datavalidation-cell_row_to ). + lo_data_validation = io_worksheet->add_new_data_validation( ). + lo_data_validation->type = ls_datavalidation-type. + lo_data_validation->allowblank = ls_datavalidation-allowblank. + IF ls_datavalidation-showinputmessage IS INITIAL. + lo_data_validation->showinputmessage = abap_false. + ELSE. + lo_data_validation->showinputmessage = abap_true. + ENDIF. + IF ls_datavalidation-showerrormessage IS INITIAL. + lo_data_validation->showerrormessage = abap_false. + ELSE. + lo_data_validation->showerrormessage = abap_true. + ENDIF. + IF ls_datavalidation-showdropdown IS INITIAL. + lo_data_validation->showdropdown = abap_false. + ELSE. + lo_data_validation->showdropdown = abap_true. + ENDIF. + lo_data_validation->operator = ls_datavalidation-operator. + lo_data_validation->formula1 = ls_datavalidation-formula1. + lo_data_validation->formula2 = ls_datavalidation-formula2. + lo_data_validation->prompttitle = ls_datavalidation-prompttitle. + lo_data_validation->prompt = ls_datavalidation-prompt. + lo_data_validation->errortitle = ls_datavalidation-errortitle. + lo_data_validation->error = ls_datavalidation-error. + lo_data_validation->errorstyle = ls_datavalidation-errorstyle. + lo_data_validation->cell_row = ls_datavalidation-cell_row. + lo_data_validation->cell_row_to = ls_datavalidation-cell_row_to. + lo_data_validation->cell_column = ls_datavalidation-cell_column. + lo_data_validation->cell_column_to = ls_datavalidation-cell_column_to. + ENDLOOP. + lo_ixml_datavalidation_elem ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + " End fix 276 Read data validations + + " Read hyperlinks + TRY. + me->load_worksheet_hyperlinks( io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet + it_external_hyperlinks = lt_external_hyperlinks ). + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + + TRY. + me->fill_row_outlines( io_worksheet = io_worksheet ). + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + + " Issue #366 - conditional formatting + TRY. + me->load_worksheet_cond_format( io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet ). + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + + " Issue #377 - pagebreaks + TRY. + me->load_worksheet_pagebreaks( io_ixml_worksheet = lo_ixml_worksheet + io_worksheet = io_worksheet ). + CATCH zcx_excel. " Ignore pagebreak reading errors - pass everything we were able to identify + ENDTRY. + + +ENDMETHOD. + + + + + + METHOD load_worksheet_cond_format. + + DATA: lo_ixml_cond_formats TYPE REF TO if_ixml_node_collection, + lo_ixml_cond_format TYPE REF TO if_ixml_element, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml_rules TYPE REF TO if_ixml_node_collection, + lo_ixml_rule TYPE REF TO if_ixml_element, + lo_ixml_iterator2 TYPE REF TO if_ixml_node_iterator, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_style_conditional2 TYPE REF TO zcl_excel_style_conditional. + + + DATA: lv_area TYPE string, + lt_areas TYPE STANDARD TABLE OF string WITH NON-UNIQUE DEFAULT KEY, + lv_area_start_row TYPE zexcel_cell_row, + lv_area_end_row TYPE zexcel_cell_row, + lv_area_start_col TYPE zexcel_cell_column_alpha, + lv_area_end_col TYPE zexcel_cell_column_alpha, + lv_rule TYPE zexcel_condition_rule. + + +* FIELD-SYMBOLS: <ls_external_hyperlink> LIKE LINE OF it_external_hyperlinks. + + lo_ixml_cond_formats = io_ixml_worksheet->get_elements_by_tag_name( name = 'conditionalFormatting' ). + lo_ixml_iterator = lo_ixml_cond_formats->create_iterator( ). + lo_ixml_cond_format ?= lo_ixml_iterator->get_next( ). + + WHILE lo_ixml_cond_format IS BOUND. + + CLEAR: lv_area, + lo_ixml_rule, + lo_style_conditional. + + +*--------------------------------------------------------------------* +* Get type of rule +*--------------------------------------------------------------------* + lo_ixml_rules = io_ixml_worksheet->get_elements_by_tag_name( name = 'cfRule' ). + lo_ixml_iterator2 = lo_ixml_rules->create_iterator( ). + lo_ixml_rule ?= lo_ixml_iterator2->get_next( ). +* IF lo_ixml_rule IS BOUND. + WHILE lo_ixml_rule IS BOUND. + lv_rule = lo_ixml_rule->get_attribute_ns( 'type' ). + CLEAR lo_style_conditional. + +*--------------------------------------------------------------------* +* Depending on ruletype get additional information +*--------------------------------------------------------------------* + CASE lv_rule. + + WHEN zcl_excel_style_conditional=>c_rule_cellis. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_ci( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + +* WHEN zcl_excel_style_conditional=>c_rule_containstext. +* + WHEN zcl_excel_style_conditional=>c_rule_databar. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_db( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_expression. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_ex( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_is( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_colorscale. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_cs( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_top10. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_t10( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + + WHEN zcl_excel_style_conditional=>c_rule_above_average. + lo_style_conditional = io_worksheet->add_new_conditional_style( ). + load_worksheet_cond_format_aa( io_ixml_rule = lo_ixml_rule + io_style_conditional = lo_style_conditional ). + +* WHEN zcl_excel_style_conditional=>c_rule_none. +* + + WHEN OTHERS. + ENDCASE. +* ENDIF. + + IF lo_style_conditional IS BOUND. + lo_style_conditional->rule = lv_rule. + lo_style_conditional->priority = lo_ixml_rule->get_attribute_ns( 'priority' ). +*--------------------------------------------------------------------* +* Set area to which conditional formatting belongs +*--------------------------------------------------------------------* + lv_area = lo_ixml_cond_format->get_attribute_ns( 'sqref' ). + SPLIT lv_area AT space INTO TABLE lt_areas. + DELETE lt_areas WHERE table_line IS INITIAL. + LOOP AT lt_areas INTO lv_area. +* IF sy-tabix = 1. " Add futher style for next area +* lo_style_conditional2 = lo_style_conditional. +* ELSE. +* lo_style_conditional2 = io_worksheet->add_new_conditional_style( ). +* lo_style_conditional2->mode_cellis = lo_style_conditional->mode_cellis . +* lo_style_conditional2->mode_colorscale = lo_style_conditional->mode_colorscale . +* lo_style_conditional2->mode_databar = lo_style_conditional->mode_databar . +* lo_style_conditional2->mode_expression = lo_style_conditional->mode_expression . +* lo_style_conditional2->mode_iconset = lo_style_conditional->mode_iconset . +* lo_style_conditional2->mode_top10 = lo_style_conditional->mode_top10 . +* lo_style_conditional2->mode_above_average = lo_style_conditional->mode_above_average. +* lo_style_conditional2->priority = lo_style_conditional->priority . +* lo_style_conditional2->rule = lo_style_conditional->rule . +* ENDIF. + + zcl_excel_common=>convert_range2column_a_row( EXPORTING + i_range = lv_area + IMPORTING + e_column_start = lv_area_start_col + e_column_end = lv_area_end_col + e_row_start = lv_area_start_row + e_row_end = lv_area_end_row ). +* lo_style_conditional2->set_range( ip_start_column = lv_area_start_col +* ip_stop_column = lv_area_end_col +* ip_start_row = lv_area_start_row +* ip_stop_row = lv_area_end_row ). + lo_style_conditional->add_range( ip_start_column = lv_area_start_col + ip_stop_column = lv_area_end_col + ip_start_row = lv_area_start_row + ip_stop_row = lv_area_end_row ). + ENDLOOP. + + ENDIF. + lo_ixml_rule ?= lo_ixml_iterator2->get_next( ). + ENDWHILE. + + + lo_ixml_cond_format ?= lo_ixml_iterator->get_next( ). + + ENDWHILE. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_aa. + DATA: lv_dxf_style_index TYPE i, + val TYPE string. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + +*--------------------------------------------------------------------* +* above or below average +*--------------------------------------------------------------------* + val = io_ixml_rule->get_attribute_ns( 'aboveAverage' ). + IF val = '0'. " 0 = below average + io_style_conditional->mode_above_average-above_average = space. + ELSE. + io_style_conditional->mode_above_average-above_average = 'X'. " Not present or <> 0 --> we use above average + ENDIF. + +*--------------------------------------------------------------------* +* Equal average also? +*--------------------------------------------------------------------* + CLEAR val. + val = io_ixml_rule->get_attribute_ns( 'equalAverage' ). + IF val = '1'. " 0 = below average + io_style_conditional->mode_above_average-equal_average = 'X'. + ELSE. + io_style_conditional->mode_above_average-equal_average = ' '. " Not present or <> 1 --> we use not equal average + ENDIF. + +*--------------------------------------------------------------------* +* Standard deviation instead of value ( 2nd stddev, 3rd stdev ) +*--------------------------------------------------------------------* + CLEAR val. + val = io_ixml_rule->get_attribute_ns( 'stdDev' ). + CASE val. + WHEN 1 + OR 2 + OR 3. " These seem to be supported by excel - don't try anything more + io_style_conditional->mode_above_average-standard_deviation = val. + ENDCASE. + +*--------------------------------------------------------------------* +* Cell formatting for top10 +*--------------------------------------------------------------------* + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_above_average-cell_style = <ls_dxf_style>-guid. + ENDIF. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_ci. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element, + lv_dxf_style_index TYPE i, + lo_excel_style LIKE LINE OF me->styles. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + + io_style_conditional->mode_cellis-operator = io_ixml_rule->get_attribute_ns( 'operator' ). + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_cellis-cell_style = <ls_dxf_style>-guid. + ENDIF. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'formula' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_cellis-formula = lo_ixml->get_value( ). + + WHEN 2. + io_style_conditional->mode_cellis-formula2 = lo_ixml->get_value( ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_cs. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element. + + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'cfvo' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_colorscale-cfvo1_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_colorscale-cfvo1_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 2. + io_style_conditional->mode_colorscale-cfvo2_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_colorscale-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 3. + io_style_conditional->mode_colorscale-cfvo3_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_colorscale-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'color' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_colorscale-colorrgb1 = lo_ixml->get_attribute_ns( 'rgb' ). + + WHEN 2. + io_style_conditional->mode_colorscale-colorrgb2 = lo_ixml->get_attribute_ns( 'rgb' ). + + WHEN 3. + io_style_conditional->mode_colorscale-colorrgb3 = lo_ixml->get_attribute_ns( 'rgb' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_db. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element. + + lo_ixml ?= io_ixml_rule->find_from_name( 'color' ). + IF lo_ixml IS BOUND. + io_style_conditional->mode_databar-colorrgb = lo_ixml->get_attribute_ns( 'rgb' ). + ENDIF. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'cfvo' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_databar-cfvo1_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_databar-cfvo1_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 2. + io_style_conditional->mode_databar-cfvo2_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_databar-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_ex. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element, + lv_dxf_style_index TYPE i, + lo_excel_style LIKE LINE OF me->styles. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_expression-cell_style = <ls_dxf_style>-guid. + ENDIF. + + lo_ixml_nodes ?= io_ixml_rule->get_elements_by_tag_name( 'formula' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_expression-formula = lo_ixml->get_value( ). + + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_is. + DATA: lo_ixml_nodes TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml TYPE REF TO if_ixml_element, + lo_ixml_rule_iconset TYPE REF TO if_ixml_element. + + lo_ixml_rule_iconset ?= io_ixml_rule->get_first_child( ). + io_style_conditional->mode_iconset-iconset = lo_ixml_rule_iconset->get_attribute_ns( 'iconSet' ). + io_style_conditional->mode_iconset-showvalue = lo_ixml_rule_iconset->get_attribute_ns( 'showValue' ). + lo_ixml_nodes ?= lo_ixml_rule_iconset->get_elements_by_tag_name( 'cfvo' ). + lo_ixml_iterator = lo_ixml_nodes->create_iterator( ). + lo_ixml ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml IS BOUND. + + CASE sy-index. + WHEN 1. + io_style_conditional->mode_iconset-cfvo1_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo1_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 2. + io_style_conditional->mode_iconset-cfvo2_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo2_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 3. + io_style_conditional->mode_iconset-cfvo3_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo3_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 4. + io_style_conditional->mode_iconset-cfvo4_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo4_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN 5. + io_style_conditional->mode_iconset-cfvo5_type = lo_ixml->get_attribute_ns( 'type' ). + io_style_conditional->mode_iconset-cfvo5_value = lo_ixml->get_attribute_ns( 'val' ). + + WHEN OTHERS. + EXIT. + ENDCASE. + + lo_ixml ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + +ENDMETHOD. + + + + + METHOD load_worksheet_cond_format_t10. + DATA: lv_dxf_style_index TYPE i. + + FIELD-SYMBOLS: <ls_dxf_style> LIKE LINE OF me->mt_dxf_styles. + + io_style_conditional->mode_top10-topxx_count = io_ixml_rule->get_attribute_ns( 'rank' ). " Top10, Top20, Top 50... + + io_style_conditional->mode_top10-percent = io_ixml_rule->get_attribute_ns( 'percent' ). " Top10 percent instead of Top10 values + if io_style_conditional->mode_top10-percent = '1'. + io_style_conditional->mode_top10-percent = 'X'. + else. + io_style_conditional->mode_top10-percent = ' '. + endif. + + io_style_conditional->mode_top10-bottom = io_ixml_rule->get_attribute_ns( 'bottom' ). " Bottom10 instead of Top10 + if io_style_conditional->mode_top10-bottom = '1'. + io_style_conditional->mode_top10-bottom = 'X'. + else. + io_style_conditional->mode_top10-bottom = ' '. + endif. +*--------------------------------------------------------------------* +* Cell formatting for top10 +*--------------------------------------------------------------------* + lv_dxf_style_index = io_ixml_rule->get_attribute_ns( 'dxfId' ). + READ TABLE me->mt_dxf_styles ASSIGNING <ls_dxf_style> WITH KEY dxf = lv_dxf_style_index. + IF sy-subrc = 0. + io_style_conditional->mode_top10-cell_style = <ls_dxf_style>-guid. + ENDIF. + +ENDMETHOD. + + + + + + method LOAD_WORKSHEET_DRAWING. + + TYPES: BEGIN OF t_c_nv_pr, + name TYPE string, + id TYPE string, + END OF t_c_nv_pr. + + TYPES: BEGIN OF t_blip, + cstate TYPE string, + embed TYPE string, + END OF t_blip. + + TYPES: BEGIN OF t_chart, + id TYPE string, + END OF t_chart. + + CONSTANTS: lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_true_int TYPE string VALUE '1'. + CONSTANTS: lc_rel_chart TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', + lc_rel_image TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'. + + DATA: drawing TYPE REF TO if_ixml_document, + anchors TYPE REF TO if_ixml_node_collection, + node TYPE REF TO if_ixml_element, + coll_length TYPE i, + iterator TYPE REF TO if_ixml_node_iterator, + anchor_elem TYPE REF TO if_ixml_element, + + relationship TYPE t_relationship, + rel_drawings TYPE t_rel_drawings, + rel_drawing TYPE t_rel_drawing, + rels_drawing TYPE REF TO if_ixml_document, + rels_drawing_path TYPE string, + stripped_name TYPE chkfile, + dirname TYPE string, + + path TYPE string, + path2 TYPE text255, + file_ext2 TYPE char10. + + " Read Workbook Relationships + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = ip_path + IMPORTING + stripped_name = stripped_name + file_path = dirname. + CONCATENATE dirname '_rels/' stripped_name '.rels' + INTO rels_drawing_path. + rels_drawing_path = resolve_path( rels_drawing_path ). + rels_drawing = me->get_ixml_from_zip_archive( rels_drawing_path ). + node ?= rels_drawing->find_from_name( 'Relationship' ). + WHILE node IS BOUND. + fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). + + rel_drawing-id = relationship-id. + + CONCATENATE dirname relationship-target INTO path. + path = resolve_path( path ). + rel_drawing-content = me->get_from_zip_archive( path ). "------------> This is for template usage + + path2 = path. + zcl_excel_common=>split_file( EXPORTING ip_file = path2 + IMPORTING ep_extension = file_ext2 ). + rel_drawing-file_ext = file_ext2. + + "-------------Added by Alessandro Iannacci - Should load graph xml + CASE relationship-type. + WHEN lc_rel_chart. + "Read chart xml + rel_drawing-content_xml = me->get_ixml_from_zip_archive( path ). + WHEN OTHERS. + ENDCASE. + "---------------------------- + + + APPEND rel_drawing TO rel_drawings. + + node ?= node->get_next( ). + ENDWHILE. + + drawing = me->get_ixml_from_zip_archive( ip_path ). + +* one-cell anchor ************** + anchors = drawing->get_elements_by_tag_name( name = 'oneCellAnchor' namespace = 'xdr' ). + coll_length = anchors->get_length( ). + iterator = anchors->create_iterator( ). + DO coll_length TIMES. + anchor_elem ?= iterator->get_next( ). + + CALL METHOD me->load_drawing_anchor + EXPORTING + io_anchor_element = anchor_elem + io_worksheet = io_worksheet + it_related_drawings = rel_drawings. + + ENDDO. + +* two-cell anchor ****************** + anchors = drawing->get_elements_by_tag_name( name = 'twoCellAnchor' namespace = 'xdr' ). + coll_length = anchors->get_length( ). + iterator = anchors->create_iterator( ). + DO coll_length TIMES. + anchor_elem ?= iterator->get_next( ). + + CALL METHOD me->load_drawing_anchor + EXPORTING + io_anchor_element = anchor_elem + io_worksheet = io_worksheet + it_related_drawings = rel_drawings. + + ENDDO. + + endmethod. + + + + + + + METHOD load_worksheet_hyperlinks. + + DATA: lo_ixml_hyperlinks TYPE REF TO if_ixml_node_collection, + lo_ixml_hyperlink TYPE REF TO if_ixml_element, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lv_row TYPE zexcel_cell_row, + lv_column TYPE zexcel_cell_column_alpha, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + lv_value TYPE zexcel_cell_value. + + DATA: BEGIN OF ls_hyperlink, + ref TYPE string, + display TYPE string, + location TYPE string, + tooltip TYPE string, + r_id TYPE string, + END OF ls_hyperlink. + + FIELD-SYMBOLS: <ls_external_hyperlink> LIKE LINE OF it_external_hyperlinks. + + lo_ixml_hyperlinks = io_ixml_worksheet->get_elements_by_tag_name( name = 'hyperlink' ). + lo_ixml_iterator = lo_ixml_hyperlinks->create_iterator( ). + lo_ixml_hyperlink ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_hyperlink IS BOUND. + + CLEAR ls_hyperlink. + CLEAR lo_hyperlink. + + ls_hyperlink-ref = lo_ixml_hyperlink->get_attribute_ns( 'ref' ). + ls_hyperlink-display = lo_ixml_hyperlink->get_attribute_ns( 'display' ). + ls_hyperlink-location = lo_ixml_hyperlink->get_attribute_ns( 'location' ). + ls_hyperlink-tooltip = lo_ixml_hyperlink->get_attribute_ns( 'tooltip' ). + ls_hyperlink-r_id = lo_ixml_hyperlink->get_attribute( name = 'id' + namespace = 'r' ). + IF ls_hyperlink-r_id IS INITIAL. " Internal link + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = ls_hyperlink-location ). + ELSE. " External link + READ TABLE it_external_hyperlinks ASSIGNING <ls_external_hyperlink> WITH TABLE KEY id = ls_hyperlink-r_id. + IF sy-subrc = 0. + lo_hyperlink = zcl_excel_hyperlink=>create_external_link( iv_url = <ls_external_hyperlink>-target ). + ENDIF. + ENDIF. + IF lo_hyperlink IS BOUND. " because of unsupported external links + + zcl_excel_common=>convert_columnrow2column_a_row( EXPORTING + i_columnrow = ls_hyperlink-ref + IMPORTING + e_row = lv_row + e_column = lv_column ). +* Currently it is not allowed to pass a hyperlink w/o text, but text has already been read. +* So just reread it and be done with it + io_worksheet->get_cell( EXPORTING + ip_column = lv_column + ip_row = lv_row + IMPORTING + ep_value = lv_value ). + io_worksheet->set_cell( ip_column = lv_column + ip_row = lv_row + ip_value = lv_value + ip_hyperlink = lo_hyperlink ). + ENDIF. + + lo_ixml_hyperlink ?= lo_ixml_iterator->get_next( ). + + ENDWHILE. + + +ENDMETHOD. + + + + + + METHOD load_worksheet_pagebreaks. + + DATA: lo_node TYPE REF TO if_ixml_element, + lo_ixml_rowbreaks TYPE REF TO if_ixml_node_collection, + lo_ixml_colbreaks TYPE REF TO if_ixml_node_collection, + lo_ixml_iterator TYPE REF TO if_ixml_node_iterator, + lo_ixml_rowbreak TYPE REF TO if_ixml_element, + lo_ixml_colbreak TYPE REF TO if_ixml_element, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lv_count TYPE i. + + + DATA: lt_pagebreaks TYPE STANDARD TABLE OF zcl_excel_worksheet_pagebreaks=>ts_pagebreak_at, + lo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks. + + FIELD-SYMBOLS: <ls_pagebreak_row> LIKE LINE OF lt_pagebreaks. + FIELD-SYMBOLS: <ls_pagebreak_col> LIKE LINE OF lt_pagebreaks. + +*--------------------------------------------------------------------* +* Get minimal number of cells where to add pagebreaks +* Since rows and columns are handled in separate nodes +* Build table to identify these cells +*--------------------------------------------------------------------* + lo_node ?= io_ixml_worksheet->find_from_name( 'rowBreaks' ). + check lo_node is bound. + lo_ixml_rowbreaks = lo_node->get_elements_by_tag_name( name = 'brk' ). + lo_ixml_iterator = lo_ixml_rowbreaks->create_iterator( ). + lo_ixml_rowbreak ?= lo_ixml_iterator->get_next( ). + WHILE lo_ixml_rowbreak IS BOUND. + APPEND INITIAL LINE TO lt_pagebreaks ASSIGNING <ls_pagebreak_row>. + <ls_pagebreak_row>-cell_row = lo_ixml_rowbreak->get_attribute_ns( 'id' ). + + lo_ixml_rowbreak ?= lo_ixml_iterator->get_next( ). + ENDWHILE. + CHECK <ls_pagebreak_row> IS ASSIGNED. + + lo_node ?= io_ixml_worksheet->find_from_name( 'colBreaks' ). + check lo_node is bound. + lo_ixml_colbreaks = lo_node->get_elements_by_tag_name( name = 'brk' ). + lo_ixml_iterator = lo_ixml_colbreaks->create_iterator( ). + lo_ixml_colbreak ?= lo_ixml_iterator->get_next( ). + CLEAR lv_count. + WHILE lo_ixml_colbreak IS BOUND. + ADD 1 TO lv_count. + READ TABLE lt_pagebreaks INDEX lv_count ASSIGNING <ls_pagebreak_col>. + IF sy-subrc <> 0. + APPEND INITIAL LINE TO lt_pagebreaks ASSIGNING <ls_pagebreak_col>. + <ls_pagebreak_col>-cell_row = <ls_pagebreak_row>-cell_row. + ENDIF. + <ls_pagebreak_col>-cell_column = lo_ixml_colbreak->get_attribute_ns( 'id' ). + + lo_ixml_colbreak ?= lo_ixml_iterator->get_next( ). + ENDWHILE. +*--------------------------------------------------------------------* +* Finally add each pagebreak +*--------------------------------------------------------------------* + lo_pagebreaks = io_worksheet->get_pagebreaks( ). + LOOP AT lt_pagebreaks ASSIGNING <ls_pagebreak_row>. + lo_pagebreaks->add_pagebreak( ip_column = <ls_pagebreak_row>-cell_column + ip_row = <ls_pagebreak_row>-cell_row ). + ENDLOOP. + + +ENDMETHOD. + + + + + + METHOD load_worksheet_pagemargins. + + TYPES: BEGIN OF lty_page_margins, + footer TYPE string, + header TYPE string, + bottom TYPE string, + top TYPE string, + right TYPE string, + left TYPE string, + END OF lty_page_margins. + + DATA:lo_ixml_pagemargins_elem TYPE REF TO if_ixml_element, + ls_pagemargins TYPE lty_page_margins. + + + lo_ixml_pagemargins_elem = io_ixml_worksheet->find_from_name( 'pageMargins' ). + IF lo_ixml_pagemargins_elem IS NOT INITIAL. + fill_struct_from_attributes( EXPORTING + ip_element = lo_ixml_pagemargins_elem + CHANGING + cp_structure = ls_pagemargins ). + io_worksheet->sheet_setup->margin_bottom = zcl_excel_common=>excel_string_to_number( ls_pagemargins-bottom ). + io_worksheet->sheet_setup->margin_footer = zcl_excel_common=>excel_string_to_number( ls_pagemargins-footer ). + io_worksheet->sheet_setup->margin_header = zcl_excel_common=>excel_string_to_number( ls_pagemargins-header ). + io_worksheet->sheet_setup->margin_left = zcl_excel_common=>excel_string_to_number( ls_pagemargins-left ). + io_worksheet->sheet_setup->margin_right = zcl_excel_common=>excel_string_to_number( ls_pagemargins-right ). + io_worksheet->sheet_setup->margin_top = zcl_excel_common=>excel_string_to_number( ls_pagemargins-top ). + ENDIF. + +ENDMETHOD. + + + + + METHOD read_from_applserver. + + DATA: lv_filelength TYPE i, + lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, + ls_binary_data LIKE LINE OF lt_binary_data, + lv_filename TYPE string, + lv_max_length_line TYPE i, + lv_actual_length_line TYPE i, + lv_errormessage TYPE string. + + MOVE i_filename TO lv_filename. + + DESCRIBE FIELD ls_binary_data LENGTH lv_max_length_line IN BYTE MODE. + OPEN DATASET lv_filename FOR INPUT IN BINARY MODE. + IF sy-subrc <> 0. + lv_errormessage = 'A problem occured when reading the file'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + WHILE sy-subrc = 0. + + READ DATASET lv_filename INTO ls_binary_data MAXIMUM LENGTH lv_max_length_line ACTUAL LENGTH lv_actual_length_line. + APPEND ls_binary_data TO lt_binary_data. + lv_filelength = lv_filelength + lv_actual_length_line. + + ENDWHILE. + CLOSE DATASET lv_filename. + +*--------------------------------------------------------------------* +* Binary data needs to be provided as XSTRING for further processing +*--------------------------------------------------------------------* + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filelength + IMPORTING + buffer = r_excel_data + TABLES + binary_tab = lt_binary_data. + ENDMETHOD. + + + + + + METHOD read_from_local_file. + DATA: lv_filelength TYPE i, + lt_binary_data TYPE STANDARD TABLE OF x255 WITH NON-UNIQUE DEFAULT KEY, + ls_binary_data LIKE LINE OF lt_binary_data, + lv_filename TYPE string, + lv_errormessage TYPE string. + + MOVE i_filename TO lv_filename. + + cl_gui_frontend_services=>gui_upload( EXPORTING + filename = lv_filename + filetype = 'BIN' " We are basically working with zipped directories --> force binary read + IMPORTING + filelength = lv_filelength + CHANGING + data_tab = lt_binary_data + EXCEPTIONS + file_open_error = 1 + file_read_error = 2 + no_batch = 3 + gui_refuse_filetransfer = 4 + invalid_type = 5 + no_authority = 6 + unknown_error = 7 + bad_data_format = 8 + header_not_allowed = 9 + separator_not_allowed = 10 + header_too_long = 11 + unknown_dp_error = 12 + access_denied = 13 + dp_out_of_memory = 14 + disk_full = 15 + dp_timeout = 16 + not_supported_by_gui = 17 + error_no_gui = 18 + OTHERS = 19 ). + IF sy-subrc <> 0. + lv_errormessage = 'A problem occured when reading the file'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Binary data needs to be provided as XSTRING for further processing +*--------------------------------------------------------------------* + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_filelength + IMPORTING + buffer = r_excel_data + TABLES + binary_tab = lt_binary_data. + + ENDMETHOD. + + + + + method RESOLVE_PATH. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 Determine whether the replacement should be done +* iterative to allow /../../.. or something alike +* 2do§2 Determine whether /./ has to be supported as well +* 2do§3 Create unit-test for this method +* +* Please don't just delete these ToDos if they are not +* needed but leave a comment that states this +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-11 +* - ... +* changes: replaced previous coding by regular expression +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* §1 This routine will receive a path, that may have a relative pathname (/../) included somewhere +* The output should be a resolved path without relative references +* Example: Input xl/worksheets/../drawings/drawing1.xml +* Output xl/drawings/drawing1.xml +*--------------------------------------------------------------------* + + rp_result = ip_path. +*--------------------------------------------------------------------* +* §1 Remove relative pathnames +*--------------------------------------------------------------------* +* Regular expression [^/]*/\.\./ +* [^/]* --> any number of characters other than / +* followed by /\.\./ --> the sequence /../ +* ==> worksheets/../ will be found in the example +*--------------------------------------------------------------------* + REPLACE REGEX '[^/]*/\.\./' IN rp_result WITH ``. + + + endmethod. + + + method RESOLVE_REFERENCED_FORMULAE. + TYPES: BEGIN OF ty_referenced_cells, + sheet TYPE REF TO zcl_excel_worksheet, + si TYPE i, + row_from TYPE i, + row_to TYPE i, + col_from TYPE i, + col_to TYPE i, + formula TYPE string, + ref_cell TYPE char10, + END OF ty_referenced_cells. + + DATA: ls_ref_formula LIKE LINE OF me->mt_ref_formulae, + lts_referenced_cells TYPE SORTED TABLE OF ty_referenced_cells WITH NON-UNIQUE KEY sheet si row_from row_to col_from col_to, + ls_referenced_cell LIKE LINE OF lts_referenced_cells, + lv_col_from TYPE zexcel_cell_column_alpha, + lv_col_to TYPE zexcel_cell_column_alpha, + lv_resulting_formula TYPE string, + lv_current_cell TYPE char10. + + + me->mt_ref_formulae = me->mt_ref_formulae. + +*--------------------------------------------------------------------* +* Get referenced Cells, Build ranges for easy lookup +*--------------------------------------------------------------------* + LOOP AT me->mt_ref_formulae INTO ls_ref_formula WHERE ref <> space. + + CLEAR ls_referenced_cell. + ls_referenced_cell-sheet = ls_ref_formula-sheet. + ls_referenced_cell-si = ls_ref_formula-si. + ls_referenced_cell-formula = ls_ref_formula-formula. + + TRY. + zcl_excel_common=>convert_range2column_a_row( EXPORTING i_range = ls_ref_formula-ref + IMPORTING e_column_start = lv_col_from + e_column_end = lv_col_to + e_row_start = ls_referenced_cell-row_from + e_row_end = ls_referenced_cell-row_to ). + ls_referenced_cell-col_from = zcl_excel_common=>convert_column2int( lv_col_from ). + ls_referenced_cell-col_to = zcl_excel_common=>convert_column2int( lv_col_to ). + + + CLEAR ls_referenced_cell-ref_cell. + TRY. + ls_referenced_cell-ref_cell(3) = zcl_excel_common=>convert_column2alpha( ls_ref_formula-column ). + ls_referenced_cell-ref_cell+3 = ls_ref_formula-row. + CONDENSE ls_referenced_cell-ref_cell NO-GAPS. + CATCH zcx_excel. + ENDTRY. + + INSERT ls_referenced_cell INTO TABLE lts_referenced_cells. + CATCH zcx_excel. + ENDTRY. + + ENDLOOP. + +* break x0009004. +*--------------------------------------------------------------------* +* For each referencing cell determine the referenced cell +* and resolve the formula +*--------------------------------------------------------------------* + LOOP AT me->mt_ref_formulae INTO ls_ref_formula WHERE ref = space. + + + CLEAR lv_current_cell. + TRY. + lv_current_cell(3) = zcl_excel_common=>convert_column2alpha( ls_ref_formula-column ). + lv_current_cell+3 = ls_ref_formula-row. + CONDENSE lv_current_cell NO-GAPS. + CATCH zcx_excel. + ENDTRY. + + LOOP AT lts_referenced_cells INTO ls_referenced_cell WHERE sheet = ls_ref_formula-sheet + AND si = ls_ref_formula-si + AND row_from <= ls_ref_formula-row + AND row_to >= ls_ref_formula-row + AND col_from <= ls_ref_formula-column + AND col_to >= ls_ref_formula-column. + + TRY. + + lv_resulting_formula = zcl_excel_common=>determine_resulting_formula( iv_reference_cell = ls_referenced_cell-ref_cell + iv_reference_formula = ls_referenced_cell-formula + iv_current_cell = lv_current_cell ). + + ls_referenced_cell-sheet->set_cell_formula( ip_column = ls_ref_formula-column + ip_row = ls_ref_formula-row + ip_formula = lv_resulting_formula ). + CATCH zcx_excel. + ENDTRY. + EXIT. + + ENDLOOP. + + ENDLOOP. + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + METHOD load_vbaproject. + + DATA lv_content TYPE xstring. + + lv_content = me->get_from_zip_archive( ip_path ). + + ip_excel->zif_excel_book_vba_project~set_vbaproject( lv_content ). + + ENDMETHOD. + + + method LOAD_WORKBOOK. + super->load_workbook( EXPORTING iv_workbook_full_filename = iv_workbook_full_filename + io_excel = io_excel ). + + CONSTANTS: lc_vba_project TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject'. + + DATA: rels_workbook_path TYPE string, + rels_workbook TYPE REF TO if_ixml_document, + path TYPE string, + node TYPE REF TO if_ixml_element, + workbook TYPE REF TO if_ixml_document, + stripped_name TYPE chkfile, + dirname TYPE string, + relationship TYPE t_relationship, + fileversion TYPE t_fileversion, + workbookpr TYPE t_workbookpr. + + FIELD-SYMBOLS: <worksheet> TYPE t_relationship. + + CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH' + EXPORTING + full_name = iv_workbook_full_filename + 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. + me->fill_struct_from_attributes( EXPORTING ip_element = node CHANGING cp_structure = relationship ). + + CASE relationship-type. + WHEN lc_vba_project. + " Read VBA binary + CONCATENATE dirname relationship-target INTO path. + me->load_vbaproject( ip_path = path + ip_excel = io_excel ). + WHEN OTHERS. + ENDCASE. + + node ?= node->get_next( ). + ENDWHILE. + + " Read Workbook codeName + workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). + node ?= workbook->find_from_name( 'fileVersion' ). + IF node IS BOUND. + + fill_struct_from_attributes( EXPORTING ip_element = node + CHANGING cp_structure = fileversion ). + + io_excel->zif_excel_book_vba_project~set_codename( fileversion-codename ). + ENDIF. + + " Read Workbook codeName + workbook = me->get_ixml_from_zip_archive( iv_workbook_full_filename ). + node ?= workbook->find_from_name( 'workbookPr' ). + IF node IS BOUND. + + fill_struct_from_attributes( EXPORTING ip_element = node + CHANGING cp_structure = workbookpr ). + + io_excel->zif_excel_book_vba_project~set_codename_pr( workbookpr-codename ). + ENDIF. + + endmethod. + + + METHOD load_worksheet. + + super->load_worksheet( EXPORTING ip_path = ip_path + io_worksheet = io_worksheet ). + + DATA: path TYPE string, + node TYPE REF TO if_ixml_element, + worksheet TYPE REF TO if_ixml_document, + sheetpr TYPE t_sheetpr. + + " Read Workbook codeName + worksheet = me->get_ixml_from_zip_archive( ip_path ). + node ?= worksheet->find_from_name( 'sheetPr' ). + IF node IS BOUND. + + fill_struct_from_attributes( EXPORTING ip_element = node + CHANGING cp_structure = sheetpr ). + IF sheetpr-codename IS NOT INITIAL. + io_worksheet->zif_excel_sheet_vba_project~set_codename_pr( sheetpr-codename ). + ENDIF. + ENDIF. +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + METHOD is_security_enabled. + IF lockrevision EQ abap_true OR lockstructure EQ abap_true OR lockwindows EQ abap_true. + ep_security_enabled = abap_true. + ENDIF. +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + orientation = me->c_orientation_default. + +* default margins + margin_bottom = '0.75'. + margin_footer = '0.3'. + margin_header = '0.3'. + margin_left = '0.7'. + margin_right = '0.7'. + margin_top = '0.75'. + +* clear page settings + CLEAR: black_and_white, + cell_comments, + copies, + draft, + errors, + first_page_number, + fit_to_page, + fit_to_height, + fit_to_width, + horizontal_dpi, + orientation, + page_order, + paper_height, + paper_size, + paper_width, + scale, + use_first_page_num, + use_printer_defaults, + vertical_dpi. + endmethod. + + + + + + + method GET_HEADER_FOOTER_STRING. +* ---------------------------------------------------------------------- + DATA: lc_marker_left(2) TYPE c VALUE '&L' + , lc_marker_right(2) TYPE c VALUE '&R' + , lc_marker_center(2) TYPE c VALUE '&C' + , lv_value TYPE string + . +* ---------------------------------------------------------------------- + IF ep_odd_header IS SUPPLIED. + + IF me->odd_header-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_odd_header. + ENDIF. + + IF me->odd_header-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'CENTER' ). + CONCATENATE ep_odd_header lc_marker_center lv_value INTO ep_odd_header. + ENDIF. + + IF me->odd_header-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_header ip_side = 'RIGHT' ). + CONCATENATE ep_odd_header lc_marker_right lv_value INTO ep_odd_header. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_odd_footer IS SUPPLIED. + + IF me->odd_footer-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_odd_footer. + ENDIF. + + IF me->odd_footer-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'CENTER' ). + CONCATENATE ep_odd_footer lc_marker_center lv_value INTO ep_odd_footer. + ENDIF. + + IF me->odd_footer-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->odd_footer ip_side = 'RIGHT' ). + CONCATENATE ep_odd_footer lc_marker_right lv_value INTO ep_odd_footer. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_even_header IS SUPPLIED. + + IF me->even_header-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_even_header. + ENDIF. + + IF me->even_header-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'CENTER' ). + CONCATENATE ep_even_header lc_marker_center lv_value INTO ep_even_header. + ENDIF. + + IF me->even_header-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_header ip_side = 'RIGHT' ). + CONCATENATE ep_even_header lc_marker_right lv_value INTO ep_even_header. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + IF ep_even_footer IS SUPPLIED. + + IF me->even_footer-left_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'LEFT' ). + CONCATENATE lc_marker_left lv_value INTO ep_even_footer. + ENDIF. + + IF me->even_footer-center_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'CENTER' ). + CONCATENATE ep_even_footer lc_marker_center lv_value INTO ep_even_footer. + ENDIF. + + IF me->even_footer-right_value IS NOT INITIAL. + lv_value = me->process_header_footer( ip_header = me->even_footer ip_side = 'RIGHT' ). + CONCATENATE ep_even_footer lc_marker_right lv_value INTO ep_even_footer. + ENDIF. + + ENDIF. +* ---------------------------------------------------------------------- + endmethod. + + + + + + method PROCESS_HEADER_FOOTER. + +* ---------------------------------------------------------------------- +* Only Basic font/text formatting possible: +* Bold (yes / no), Font Type, Font Size + + DATA: lv_fname(12) TYPE c + , lv_string TYPE string + . + + FIELD-SYMBOLS: <lv_value> TYPE string + , <ls_font> TYPE zexcel_s_style_font + . + +* ---------------------------------------------------------------------- + CONCATENATE ip_side '_VALUE' INTO lv_fname. + ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <lv_value>. + + CONCATENATE ip_side '_FONT' INTO lv_fname. + ASSIGN COMPONENT lv_fname OF STRUCTURE ip_header TO <ls_font>. + + IF <ls_font> IS ASSIGNED AND <lv_value> IS ASSIGNED. + + IF <ls_font>-name IS NOT INITIAL. + CONCATENATE '&"' <ls_font>-name ',' INTO rv_processed_string. + ELSE. + rv_processed_string = '&"-,'. + ENDIF. + + IF <ls_font>-bold = abap_true. + CONCATENATE rv_processed_string 'Bold"' INTO rv_processed_string. + ELSE. + CONCATENATE rv_processed_string 'Standard"' INTO rv_processed_string. + ENDIF. + + IF <ls_font>-size IS NOT INITIAL. + lv_string = <ls_font>-size. + CONCATENATE rv_processed_string '&' lv_string INTO rv_processed_string. + ENDIF. + + CONCATENATE rv_processed_string <lv_value> INTO rv_processed_string. + + ENDIF. +* ---------------------------------------------------------------------- + + endmethod. + + + + + + + method SET_HEADER_FOOTER. + +* Only Basic font/text formatting possible: +* Bold (yes / no), Font Type, Font Size +* +* usefull placeholders, which can be used in header/footer value strings +* '&P' - page number +* '&N' - total number of pages +* '&D' - Date +* '&T' - Time +* '&F' - File Name +* '&Z' - Path +* '&A' - Sheet name +* new line via class constant CL_ABAP_CHAR_UTILITIES=>newline +* +* Example Value String 'page &P of &N' +* +* DO NOT USE &L , &C or &R which automatically created as position markers + + me->odd_header = ip_odd_header. + me->odd_footer = ip_odd_footer. + me->even_header = ip_even_header. + me->even_footer = ip_even_footer. + + IF me->even_header IS NOT INITIAL OR me->even_footer IS NOT INITIAL. + me->diff_oddeven_headerfooter = abap_true. + ENDIF. + + + endmethod. + + + + + + + + + + method SET_PAGE_MARGINS. + DATA: lv_coef TYPE f, + lv_unit TYPE string. + + lv_unit = ip_unit. + TRANSLATE lv_unit TO UPPER CASE. + + CASE lv_unit. + WHEN 'IN'. lv_coef = 1. + WHEN 'CM'. lv_coef = '0.393700787'. + WHEN 'MM'. lv_coef = '0.0393700787'. + ENDCASE. + + IF ip_bottom IS SUPPLIED. margin_bottom = lv_coef * ip_bottom. ENDIF. + IF ip_footer IS SUPPLIED. margin_footer = lv_coef * ip_footer. ENDIF. + IF ip_header IS SUPPLIED. margin_header = lv_coef * ip_header. ENDIF. + IF ip_left IS SUPPLIED. margin_left = lv_coef * ip_left. ENDIF. + IF ip_right IS SUPPLIED. margin_right = lv_coef * ip_right. ENDIF. + IF ip_top IS SUPPLIED. margin_top = lv_coef * ip_top. ENDIF. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + METHOD constructor. + + + CREATE OBJECT font. + CREATE OBJECT fill. + CREATE OBJECT borders. + CREATE OBJECT alignment. + CREATE OBJECT number_format. + CREATE OBJECT protection. + +* Start of insertion # issue 139 - Dateretention of cellstyles + IF ip_guid IS NOT INITIAL. + me->guid = ip_guid. + ELSE. +* End of insertion # issue 139 - Dateretention of cellstyles +* CALL FUNCTION 'GUID_CREATE' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = me->guid. + me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call +* Start of insertion # issue 139 - Dateretention of cellstyles + ENDIF. +* End of insertion # issue 139 - Dateretention of cellstyles + +ENDMETHOD. + + + + method GET_GUID. + + + ep_guid = me->guid. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + + + styles->add( ip_style ). + endmethod. + + + method CLEAR. + + + styles->clear( ). + endmethod. + + + method CONSTRUCTOR. + + + CREATE OBJECT styles. + endmethod. + + + + + method GET. + + + eo_style ?= styles->if_object_collection~get( ip_index ). + endmethod. + + + + method GET_ITERATOR. + + + eo_iterator ?= styles->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + + + is_empty = styles->if_object_collection~is_empty( ). + endmethod. + + + + + method REGISTER_NEW_STYLE. + + + me->add( io_style ). + ep_style_code = me->size( ) - 1. "style count starts from 0 + endmethod. + + + + method REMOVE. + + + styles->remove( ip_style ). + endmethod. + + + + method SIZE. + + + ep_size = styles->if_object_collection~size( ). + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + method ADD. + styles_conditional->add( ip_style_conditional ). + endmethod. + + + method CLEAR. + styles_conditional->clear( ). + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT styles_conditional. + + endmethod. + + + + + method GET. + DATA lv_index TYPE i. + lv_index = ip_index. + eo_style_conditional ?= styles_conditional->if_object_collection~get( lv_index ). + endmethod. + + + + method GET_ITERATOR. + eo_iterator ?= styles_conditional->if_object_collection~get_iterator( ). + endmethod. + + + + method IS_EMPTY. + is_empty = styles_conditional->if_object_collection~is_empty( ). + endmethod. + + + + method REMOVE. + styles_conditional->remove( ip_style_conditional ). + endmethod. + + + + method SIZE. + ep_size = styles_conditional->if_object_collection~size( ). + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + horizontal = me->c_horizontal_general. + vertical = me->c_vertical_bottom. + wrapText = abap_false. + shrinkToFit = abap_false. + endmethod. + + + + method GET_STRUCTURE. + + es_alignment-horizontal = me->horizontal. + es_alignment-vertical = me->vertical. + es_alignment-textrotation = me->textrotation. + es_alignment-wraptext = me->wraptext. + es_alignment-shrinktofit = me->shrinktofit. + es_alignment-indent = me->indent. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + method CONSTRUCTOR. + border_style = zcl_excel_style_border=>c_border_none. + border_color-theme = zcl_excel_style_color=>c_theme_not_set. + border_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + method GET_STRUCTURE. +*initialize colors to 'not set' + es_fill-left_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-left_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-right_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-right_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-top_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-top_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-bottom_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-bottom_color-theme = zcl_excel_style_color=>c_theme_not_set. + es_fill-diagonal_color-indexed = zcl_excel_style_color=>c_indexed_not_set. + es_fill-diagonal_color-theme = zcl_excel_style_color=>c_theme_not_set. + +* Check if all borders is set otherwise check single border + IF me->allborders IS BOUND. + es_fill-left_color = me->allborders->border_color. + es_fill-left_style = me->allborders->border_style. + es_fill-right_color = me->allborders->border_color. + es_fill-right_style = me->allborders->border_style. + es_fill-top_color = me->allborders->border_color. + es_fill-top_style = me->allborders->border_style. + es_fill-bottom_color = me->allborders->border_color. + es_fill-bottom_style = me->allborders->border_style. + ELSE. + IF me->left IS BOUND. + es_fill-left_color = me->left->border_color. + es_fill-left_style = me->left->border_style. + ENDIF. + IF me->right IS BOUND. + es_fill-right_color = me->right->border_color. + es_fill-right_style = me->right->border_style. + ENDIF. + IF me->top IS BOUND. + es_fill-top_color = me->top->border_color. + es_fill-top_style = me->top->border_style. + ENDIF. + IF me->down IS BOUND. + es_fill-bottom_color = me->down->border_color. + es_fill-bottom_style = me->down->border_style. + ENDIF. + ENDIF. + +* Check if diagonal is set + IF me->diagonal IS BOUND. + es_fill-diagonal_color = me->diagonal->border_color. + es_fill-diagonal_style = me->diagonal->border_style. + CASE me->diagonal_mode. + WHEN 1. + es_fill-diagonalup = 1. + es_fill-diagonaldown = 0. + WHEN 2. + es_fill-diagonalup = 0. + es_fill-diagonaldown = 1. + WHEN 3. + es_fill-diagonalup = 1. + es_fill-diagonaldown = 1. + WHEN OTHERS. + es_fill-diagonalup = 0. + es_fill-diagonaldown = 0. + ENDCASE. + ENDIF. + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + METHOD create_new_arbg_int. + DATA: lv_red TYPE int1, + lv_green TYPE int1, + lv_blue TYPE int1, + lv_hex TYPE x, + lv_char_red TYPE zexcel_style_color_component, + lv_char_green TYPE zexcel_style_color_component, + lv_char_blue TYPE zexcel_style_color_component. + + lv_red = iv_red MOD 256. + lv_green = iv_green MOD 256. + lv_blue = iv_blue MOD 256. + + lv_hex = lv_red. + lv_char_red = lv_hex. + + lv_hex = lv_green. + lv_char_green = lv_hex. + + lv_hex = lv_blue. + lv_char_blue = lv_hex. + + + concatenate zcl_excel_style_color=>c_alpha lv_char_red lv_char_green lv_char_blue into rv_color_argb. + + +ENDMETHOD. + + + + + + + METHOD create_new_argb. + + CONCATENATE zcl_excel_style_color=>c_alpha ip_red ip_green ip_blu INTO ep_color_argb. + +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + METHOD add_range. + DATA: lv_column TYPE zexcel_cell_column, + lv_row_alpha TYPE string, + lv_col_alpha TYPE string, + lv_coords1 TYPE string, + lv_coords2 TYPE string. + + + lv_column = zcl_excel_common=>convert_column2int( ip_start_column ). +* me->mv_cell_data-cell_row = 1. +* me->mv_cell_data-cell_column = lv_column. +* + lv_col_alpha = ip_start_column. + lv_row_alpha = ip_start_row. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_col_alpha lv_row_alpha INTO lv_coords1. + + IF ip_stop_column IS NOT INITIAL. + lv_column = zcl_excel_common=>convert_column2int( ip_stop_column ). + ELSE. + lv_column = zcl_excel_common=>convert_column2int( ip_start_column ). + ENDIF. + + IF ip_stop_row IS NOT INITIAL. " If we don't get explicitly a stop column use start column + lv_row_alpha = ip_stop_row. + ELSE. + lv_row_alpha = ip_start_row. + ENDIF. + IF ip_stop_column IS NOT INITIAL. " If we don't get explicitly a stop column use start column + lv_col_alpha = ip_stop_column. + ELSE. + lv_col_alpha = ip_start_column. + ENDIF. + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_col_alpha lv_row_alpha INTO lv_coords2. + IF lv_coords2 IS NOT INITIAL AND lv_coords2 <> lv_coords1. + CONCATENATE me->mv_rule_range ` ` lv_coords1 ':' lv_coords2 INTO me->mv_rule_range. + ELSE. + CONCATENATE me->mv_rule_range ` ` lv_coords1 INTO me->mv_rule_range. + ENDIF. + SHIFT me->mv_rule_range LEFT DELETING LEADING space. + +ENDMETHOD. + + + METHOD constructor. + + DATA: ls_iconset TYPE zexcel_conditional_iconset. + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights. + ls_iconset-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo1_value = '0'. + ls_iconset-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo2_value = '20'. + ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo3_value = '40'. + ls_iconset-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo4_value = '60'. + ls_iconset-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo5_value = '80'. + + + me->rule = zcl_excel_style_conditional=>c_rule_none. +* me->iconset->operator = zcl_excel_style_conditional=>c_operator_none. + me->mode_iconset = ls_iconset. + me->priority = 1. + +* inizialize dimension range + me->MV_RULE_RANGE = 'A1'. +ENDMETHOD. + + + + + + + + + + + + + + + + + METHOD factory_cond_style_iconset. + +*--------------------------------------------------------------------* +* Work in progress +* Missing: LE or LT may be specified --> extend structure ZEXCEL_CONDITIONAL_ICONSET to hold this information as well +*--------------------------------------------------------------------* + +* DATA: lv_needed_values TYPE i. +* CASE icon_type. +* +* WHEN 'C_ICONSET_3ARROWS' +* OR 'C_ICONSET_3ARROWSGRAY' +* OR 'C_ICONSET_3FLAGS' +* OR 'C_ICONSET_3SIGNS' +* OR 'C_ICONSET_3SYMBOLS' +* OR 'C_ICONSET_3SYMBOLS2' +* OR 'C_ICONSET_3TRAFFICLIGHTS' +* OR 'C_ICONSET_3TRAFFICLIGHTS2'. +* lv_needed_values = 3. +* +* WHEN 'C_ICONSET_4ARROWS' +* OR 'C_ICONSET_4ARROWSGRAY' +* OR 'C_ICONSET_4RATING' +* OR 'C_ICONSET_4REDTOBLACK' +* OR 'C_ICONSET_4TRAFFICLIGHTS'. +* lv_needed_values = 4. +* +* WHEN 'C_ICONSET_5ARROWS' +* OR 'C_ICONSET_5ARROWSGRAY' +* OR 'C_ICONSET_5QUARTERS' +* OR 'C_ICONSET_5RATING'. +* lv_needed_values = 5. +* +* WHEN OTHERS. +* RETURN. +* ENDCASE. + +ENDMETHOD. + + + + METHOD get_dimension_range. + + ep_dimension_range = me->mv_rule_range. + +ENDMETHOD. + + + + + + + METHOD set_range. + + CLEAR: me->mv_rule_range. + + me->add_range( ip_start_row = ip_start_row + ip_start_column = ip_start_column + ip_stop_row = ip_stop_row + ip_stop_column = ip_stop_column ). + +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method build_gradient. + check check_filltype_is_gradient( ) eq abap_true. + clear gradtype. + case filltype. + when c_fill_gradient_horizontal90. + gradtype-degree = '90'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_horizontal270. + gradtype-degree = '270'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_horizontalb. + gradtype-degree = '90'. + gradtype-position1 = '0'. + gradtype-position2 = '0.5'. + gradtype-position3 = '1'. + when c_fill_gradient_vertical. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_fromcenter. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-bottom = '0.5'. + gradtype-top = '0.5'. + gradtype-left = '0.5'. + gradtype-right = '0.5'. + when c_fill_gradient_diagonal45. + gradtype-degree = '45'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_diagonal45b. + gradtype-degree = '45'. + gradtype-position1 = '0'. + gradtype-position2 = '0.5'. + gradtype-position3 = '1'. + when c_fill_gradient_diagonal135. + gradtype-degree = '135'. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_diagonal135b. + gradtype-degree = '135'. + gradtype-position1 = '0'. + gradtype-position2 = '0.5'. + gradtype-position3 = '1'. + when c_fill_gradient_cornerlt. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + when c_fill_gradient_cornerlb. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-bottom = '1'. + gradtype-top = '1'. + when c_fill_gradient_cornerrt. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-left = '1'. + gradtype-right = '1'. + when c_fill_gradient_cornerrb. + gradtype-type = c_fill_gradient_path. + gradtype-position1 = '0'. + gradtype-position2 = '1'. + gradtype-bottom = '0.5'. + gradtype-top = '0.5'. + gradtype-left = '0.5'. + gradtype-right = '0.5'. + endcase. + + endmethod. "build_gradient + + + + method check_filltype_is_gradient. + case filltype. + when c_fill_gradient_horizontal90 or + c_fill_gradient_horizontal270 or + c_fill_gradient_horizontalb or + c_fill_gradient_vertical or + c_fill_gradient_fromcenter or + c_fill_gradient_diagonal45 or + c_fill_gradient_diagonal45b or + c_fill_gradient_diagonal135 or + c_fill_gradient_diagonal135b or + c_fill_gradient_cornerlt or + c_fill_gradient_cornerlb or + c_fill_gradient_cornerrt or + c_fill_gradient_cornerrb. + rv_is_gradient = abap_true. + endcase. + endmethod. "check_filltype_is_gradient + + + method constructor. + filltype = zcl_excel_style_fill=>c_fill_none. + fgcolor-theme = zcl_excel_style_color=>c_theme_not_set. + fgcolor-indexed = zcl_excel_style_color=>c_indexed_not_set. + bgcolor-theme = zcl_excel_style_color=>c_theme_not_set. + bgcolor-indexed = zcl_excel_style_color=>c_indexed_sys_foreground. + rotation = 0. + + endmethod. "CONSTRUCTOR + + + + method get_structure. + es_fill-rotation = me->rotation. + es_fill-filltype = me->filltype. + es_fill-fgcolor = me->fgcolor. + es_fill-bgcolor = me->bgcolor. + me->build_gradient( ). + es_fill-gradtype = me->gradtype. + endmethod. "GET_STRUCTURE + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method CALCULATE_TEXT_WIDTH. + " Addition to solve issue #120, contribution by Stefan Schmoecker + r_width = strlen( i_text ). + " use scale factor based on default 11 + " ( don't know where defaultsetting is stored currently ) + r_width = r_width * me->size / 11. + endmethod. + + + method CONSTRUCTOR. + me->color-rgb = zcl_excel_style_color=>c_black. + me->color-theme = zcl_excel_style_color=>c_theme_not_set. + me->color-indexed = zcl_excel_style_color=>c_indexed_not_set. + me->scheme = zcl_excel_style_font=>c_scheme_minor. + me->underline_mode = zcl_excel_style_font=>c_underline_single. + endmethod. + + + + method GET_STRUCTURE. + + es_font-bold = me->bold. + es_font-italic = me->italic. + es_font-underline = me->underline. + es_font-underline_mode = me->underline_mode. + es_font-strikethrough = me->strikethrough. + es_font-size = me->size. + es_font-color = me->color. + es_font-name = me->name. + es_font-family = me->family. + es_font-scheme = me->scheme. + + endmethod. + + + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + METHOD class_constructor. + + DATA: ls_num_format LIKE LINE OF mt_built_in_num_formats. + + DEFINE predefined_format. + ls_num_format-id = &1. + create object ls_num_format-format. + ls_num_format-format->format_code = &2. + insert ls_num_format into table mt_built_in_num_formats. + END-OF-DEFINITION. + + CLEAR mt_built_in_num_formats. + + predefined_format '1' zcl_excel_style_number_format=>c_format_number. " '0'. + predefined_format '2' zcl_excel_style_number_format=>c_format_number_00. " '0.00'. + predefined_format '3' zcl_excel_style_number_format=>c_format_number_comma_sep0. " '#,##0'. + predefined_format '4' zcl_excel_style_number_format=>c_format_number_comma_sep1. " '#,##0.00'. + predefined_format '5' zcl_excel_style_number_format=>c_format_currency_simple. " '$#,##0_);($#,##0)'. + predefined_format '6' zcl_excel_style_number_format=>c_format_currency_simple_red. " '$#,##0_);[Red]($#,##0)'. + predefined_format '7' zcl_excel_style_number_format=>c_format_currency_simple2. " '$#,##0.00_);($#,##0.00)'. + predefined_format '8' zcl_excel_style_number_format=>c_format_currency_simple_red2. " '$#,##0.00_);[Red]($#,##0.00)'. + predefined_format '9' zcl_excel_style_number_format=>c_format_percentage. " '0%'. + predefined_format '10' zcl_excel_style_number_format=>c_format_percentage_00. " '0.00%'. + predefined_format '11' zcl_excel_style_number_format=>c_format_scientific. " '0.00E+00'. + predefined_format '12' zcl_excel_style_number_format=>c_format_fraction_1. " '# ?/?'. + predefined_format '13' zcl_excel_style_number_format=>c_format_fraction_2. " '# ??/??'. + predefined_format '14' zcl_excel_style_number_format=>c_format_date_xlsx14. "'m/d/yyyy'. <-- should have been 'mm-dd-yy' like constant in zcl_excel_style_number_format + predefined_format '15' zcl_excel_style_number_format=>c_format_date_xlsx15. "'d-mmm-yy'. + predefined_format '16' zcl_excel_style_number_format=>c_format_date_xlsx16. "'d-mmm'. + predefined_format '17' zcl_excel_style_number_format=>c_format_date_xlsx17. "'mmm-yy'. + predefined_format '18' zcl_excel_style_number_format=>c_format_date_time1. " 'h:mm AM/PM'. + predefined_format '19' zcl_excel_style_number_format=>c_format_date_time2. " 'h:mm:ss AM/PM'. + predefined_format '20' zcl_excel_style_number_format=>c_format_date_time3. " 'h:mm'. + predefined_format '21' zcl_excel_style_number_format=>c_format_date_time4. " 'h:mm:ss'. + predefined_format '22' zcl_excel_style_number_format=>c_format_date_xlsx22. " 'm/d/yyyy h:mm'. + + + predefined_format '37' zcl_excel_style_number_format=>c_format_xlsx37. " '#,##0_);(#,##0)'. + predefined_format '38' zcl_excel_style_number_format=>c_format_xlsx38. " '#,##0_);[Red](#,##0)'. + predefined_format '39' zcl_excel_style_number_format=>c_format_xlsx39. " '#,##0.00_);(#,##0.00)'. + predefined_format '40' zcl_excel_style_number_format=>c_format_xlsx40. " '#,##0.00_);[Red](#,##0.00)'. + predefined_format '41' zcl_excel_style_number_format=>c_format_xlsx41. " '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)'. + predefined_format '42' zcl_excel_style_number_format=>c_format_xlsx42. " '_($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)'. + predefined_format '43' zcl_excel_style_number_format=>c_format_xlsx43. " '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)'. + predefined_format '44' zcl_excel_style_number_format=>c_format_xlsx44. " '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)'. + predefined_format '45' zcl_excel_style_number_format=>c_format_date_xlsx45. " 'mm:ss'. + predefined_format '46' zcl_excel_style_number_format=>c_format_date_xlsx46. " '[h]:mm:ss'. + predefined_format '47' zcl_excel_style_number_format=>c_format_date_xlsx47. " 'mm:ss.0'. + predefined_format '48' zcl_excel_style_number_format=>c_format_special_01. " '##0.0E+0'. + predefined_format '49' zcl_excel_style_number_format=>c_format_text. " '@'. + +ENDMETHOD. + + + method CONSTRUCTOR. + format_code = me->c_format_general. + endmethod. + + + + method GET_STRUCTURE. + ep_number_format-numfmt = me->format_code. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + method CONSTRUCTOR. + locked = me->c_protection_locked. + hidden = me->c_protection_unhidden. + endmethod. + + + + method GET_STRUCTURE. + ep_protection-locked = me->locked. + ep_protection-hidden = me->hidden. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method GET_BOTTOM_ROW_INTEGER. + DATA: lv_table_lines TYPE i. + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + + IF settings-bottom_right_row IS NOT INITIAL. +* ev_row = zcl_excel_common=>convert_column2int( settings-bottom_right_row ). " del issue #246 + ev_row = settings-bottom_right_row . " ins issue #246 + EXIT. + ENDIF. + + ASSIGN table_data->* TO <fs_table>. + DESCRIBE TABLE <fs_table> LINES lv_table_lines. + IF lv_table_lines = 0. + lv_table_lines = 1. "table needs at least 1 data row + ENDIF. + + ev_row = settings-top_left_row + lv_table_lines. + + IF me->has_totals( ) = abap_true." ???? AND ip_include_totals_row = abap_true. + ADD 1 TO ev_row. + ENDIF. + endmethod. + + + + method GET_ID. + ov_id = id. + endmethod. + + + + method GET_NAME. + + IF me->name IS INITIAL. + me->name = zcl_excel_common=>number_to_excel_string( ip_value = me->id ). + CONCATENATE 'table' me->name INTO me->name. + ENDIF. + + ov_name = me->name. + endmethod. + + + + + method GET_REFERENCE. + DATA: lv_column TYPE zexcel_cell_column, + lv_table_lines TYPE i, + lv_right_column TYPE zexcel_cell_column_alpha, + ls_field_catalog TYPE zexcel_s_fieldcatalog, + lv_bottom_row TYPE zexcel_cell_row, + lv_top_row_string(10) TYPE c, + lv_bottom_row_string(10) TYPE c. + + FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE. + +*column + lv_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). + lv_table_lines = 0. + LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. + ADD 1 TO lv_table_lines. + ENDLOOP. + lv_column = lv_column + lv_table_lines - 1. + lv_right_column = zcl_excel_common=>convert_column2alpha( lv_column ). + +*row + ASSIGN table_data->* TO <fs_table>. + DESCRIBE TABLE <fs_table> LINES lv_table_lines. + IF lv_table_lines = 0. + lv_table_lines = 1. "table needs at least 1 data row + ENDIF. + lv_bottom_row = settings-top_left_row + lv_table_lines . + + IF me->has_totals( ) = abap_true AND ip_include_totals_row = abap_true. + ADD 1 TO lv_bottom_row. + ENDIF. + + lv_top_row_string = zcl_excel_common=>number_to_excel_string( settings-top_left_row ). + lv_bottom_row_string = zcl_excel_common=>number_to_excel_string( lv_bottom_row ). + + CONCATENATE settings-top_left_column lv_top_row_string + ':' + lv_right_column lv_bottom_row_string INTO ov_reference. + + endmethod. + + + + + method GET_RIGHT_COLUMN_INTEGER. + DATA: lv_column TYPE zexcel_cell_column, + lv_table_lines TYPE i, + ls_field_catalog TYPE zexcel_s_fieldcatalog. + + IF settings-bottom_right_column IS NOT INITIAL. + ev_column = zcl_excel_common=>convert_column2int( settings-bottom_right_column ). + EXIT. + ENDIF. + + ev_column = zcl_excel_common=>convert_column2int( settings-top_left_column ). + LOOP AT fieldcat INTO ls_field_catalog WHERE dynpfld EQ abap_true. + ADD 1 TO ev_column. + ENDLOOP. + + endmethod. + + + + + + method GET_TOTALS_FORMULA. + CONSTANTS: lc_function_id_sum TYPE string VALUE '109', + lc_function_id_min TYPE string VALUE '105', + lc_function_id_max TYPE string VALUE '104', + lc_function_id_count TYPE string VALUE '103', + lc_function_id_average TYPE string VALUE '101'. + + DATA: lv_function_id TYPE string. + + CASE ip_function. + WHEN zcl_excel_table=>totals_function_sum. + lv_function_id = lc_function_id_sum. + + WHEN zcl_excel_table=>totals_function_min. + lv_function_id = lc_function_id_min. + + WHEN zcl_excel_table=>totals_function_max. + lv_function_id = lc_function_id_max. + + WHEN zcl_excel_table=>totals_function_count. + lv_function_id = lc_function_id_count. + + WHEN zcl_excel_table=>totals_function_average. + lv_function_id = lc_function_id_average. + + WHEN zcl_excel_table=>totals_function_custom. " issue #292 + RETURN. + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid totals formula. See ZCL_ for possible values'. + ENDCASE. + + CONCATENATE 'SUBTOTAL(' lv_function_id ',[' ip_column '])' INTO ep_formula. + endmethod. + + + + method HAS_TOTALS. + DATA: ls_field_catalog TYPE zexcel_s_fieldcatalog. + + ep_result = abap_false. + + LOOP AT fieldcat INTO ls_field_catalog. + IF ls_field_catalog-totals_function IS NOT INITIAL. + ep_result = abap_true. + EXIT. + ENDIF. + ENDLOOP. + + endmethod. + + + + METHOD set_data. + + DATA lr_temp TYPE REF TO data. + + FIELD-SYMBOLS: <lt_table_temp> TYPE ANY TABLE, + <lt_table> TYPE ANY TABLE. + + GET REFERENCE OF ir_data INTO lr_temp. + ASSIGN lr_temp->* TO <lt_table_temp>. + CREATE DATA table_data LIKE <lt_table_temp>. + ASSIGN me->table_data->* TO <lt_table>. + <lt_table> = <lt_table_temp>. + +ENDMETHOD. + + + + method SET_ID. + id = iv_id. + endmethod. + + + + + + + + + + + + + + + + + *"* local class implementation for public class +*"* use this source file for the implementation part of +*"* local helper classes + +*&---------------------------------------------------------------------* +*& Class (Implementation) C_OI_PROXY_ERROR +*&---------------------------------------------------------------------* +CLASS c_oi_proxy_error IMPLEMENTATION. + METHOD constructor. +* IMPORTING object_name TYPE c +* method_name TYPE c. + error_nr = ret_call_not_flushed. + me->i_oi_error~error_code = c_oi_errors=>ret_call_not_flushed. + me->i_oi_error~is_flushed = ' '. + me->i_oi_error~has_failed = 'X'. + me->i_oi_error~has_succeeded = ' '. + me->message_id = 'SOFFICEINTEGRATION'. + me->message_nr = '899'. + me->param1 = object_name. + me->param2 = method_name. + ENDMETHOD. "constructor + + METHOD i_oi_error~flush_error. + IF error_nr EQ 0. + me->i_oi_error~error_code = c_oi_errors=>ret_ok. + me->i_oi_error~is_flushed = 'X'. + me->i_oi_error~has_failed = ' '. + me->i_oi_error~has_succeeded = 'X'. + me->message_id = ''. + me->message_nr = '000'. + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + IMPORTING + retcode = me->i_oi_error~error_code. + ELSEIF error_nr EQ ret_call_not_flushed. + "call still not flushed + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + errorstring = me->param2 "method name + objectname = me->param1 + IMPORTING + retcode = me->i_oi_error~error_code. + ELSE. + me->i_oi_error~is_flushed = 'X'. + me->i_oi_error~has_succeeded = ' '. + me->i_oi_error~has_failed = 'X'. + CALL METHOD c_oi_errors=>translate_proxy_error_code + EXPORTING + errorcode = error_nr + errorstring = error_string + IMPORTING + retcode = me->i_oi_error~error_code. + CALL METHOD c_oi_errors=>get_message + IMPORTING + message_id = me->message_id + message_number = me->message_nr + param1 = me->param1 + param2 = me->param2 + param3 = me->param3 + param4 = me->param4. + ENDIF. + ENDMETHOD. "i_oi_error~flush_error + + METHOD i_oi_error~raise_message. +* IMPORTING type TYPE c. +* EXCEPTIONS message_raised flush_failed. + IF me->i_oi_error~has_succeeded IS INITIAL. + IF NOT me->i_oi_error~is_flushed IS INITIAL. + MESSAGE ID message_id TYPE type + NUMBER message_nr WITH param1 param2 param3 param4 + RAISING message_raised. + ELSE. + RAISE flush_failed. + ENDIF. + ENDIF. + ENDMETHOD. "i_oi_error~raise_message + + METHOD i_oi_error~get_message. +* EXPORTING message_id TYPE c +* message_number TYPE c +* param1 TYPE c +* param2 TYPE c +* param3 TYPE c +* param4 TYPE c. + param1 = me->param1. param2 = me->param2. + param3 = me->param3. param4 = me->param4. + + message_id = me->message_id. + message_number = me->message_nr. + ENDMETHOD. "i_oi_error~get_message +ENDCLASS. "C_OI_PROXY_ERROR + +*&---------------------------------------------------------------------* +*& Class (Implementation) CL_GRID_ACCESSION +*&---------------------------------------------------------------------* +CLASS lcl_gui_alv_grid IMPLEMENTATION. + + METHOD get_alv_attributes. + CREATE DATA et_table LIKE io_grid->mt_outtab. + et_table = io_grid->mt_outtab. + ENDMETHOD. "get_data + +ENDCLASS. "CL_GRID_ACCESSION + *"* use this source file for any type declarations (class +*"* definitions, interfaces or data types) you need for method +*"* implementation or private method's signature +TYPE-POOLS: sydes. +TYPE-POOLS: slis. +*--------------------------------------------------------------------* +* CLASS c_oi_proxy_error +*--------------------------------------------------------------------* +* use for method bind_ALV +*--------------------------------------------------------------------* +CLASS c_oi_proxy_error DEFINITION. + PUBLIC SECTION. + INTERFACES: i_oi_error. + DATA: error_nr TYPE i. + DATA: error_string TYPE sy-msgv1. + + METHODS: constructor IMPORTING object_name TYPE c + method_name TYPE c. + PRIVATE SECTION. + CONSTANTS: + ret_call_not_flushed TYPE i VALUE -999999. + + DATA: message_id TYPE sy-msgid, + message_nr TYPE sy-msgno, + param1 TYPE sy-msgv1, + param2 TYPE sy-msgv2, + param3 TYPE sy-msgv3, + param4 TYPE sy-msgv4. +ENDCLASS. "c_oi_proxy_error DEFINITION + +*--------------------------------------------------------------------* +* CLASS lcl_gui_alv_grid +*--------------------------------------------------------------------* +* to get protected attribute and method of cl_gui_alv_grid +* use for method bind_ALV +*--------------------------------------------------------------------* +CLASS lcl_gui_alv_grid DEFINITION INHERITING FROM cl_gui_alv_grid. + + PUBLIC SECTION. +* get ALV grid data + METHODS: get_alv_attributes + IMPORTING + io_grid TYPE REF TO cl_gui_alv_grid " ALV grid + EXPORTING + et_table TYPE REF TO data. " dta table + +ENDCLASS. "lcl_gui_alv_grid DEFINITION + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + + ABAP + SLIS + SOI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~CLEAR_PRINT_REPEAT_COLUMNS. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + CLEAR: me->print_title_col_from, + me->print_title_col_to . + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~CLEAR_PRINT_REPEAT_ROWS. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + CLEAR: me->print_title_row_from, + me->print_title_row_to . + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~GET_PRINT_REPEAT_COLUMNS. + ev_columns_from = me->print_title_col_from. + ev_columns_to = me->print_title_col_to. + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~GET_PRINT_REPEAT_ROWS. + ev_rows_from = me->print_title_row_from. + ev_rows_to = me->print_title_row_to. + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~SET_PRINT_REPEAT_COLUMNS. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + DATA: lv_col_from_int TYPE i, + lv_col_to_int TYPE i, + lv_errormessage TYPE string. + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range. + + + lv_col_from_int = zcl_excel_common=>convert_column2int( iv_columns_from ). + lv_col_to_int = zcl_excel_common=>convert_column2int( iv_columns_to ). + +*--------------------------------------------------------------------* +* Check if valid range is supplied +*--------------------------------------------------------------------* + IF lv_col_from_int < 1. + lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF lv_col_from_int > lv_col_to_int. + lv_errormessage = 'Invalid range supplied for print-title repeatable columns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + me->print_title_col_from = iv_columns_from. + me->print_title_col_to = iv_columns_to. + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + endmethod. + + + method ZIF_EXCEL_SHEET_PRINTSETTINGS~SET_PRINT_REPEAT_ROWS. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmöcker, 2012-12-02 +*--------------------------------------------------------------------* + + DATA: lv_errormessage TYPE string. + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range. + + + +*--------------------------------------------------------------------* +* Check if valid range is supplied +*--------------------------------------------------------------------* + IF iv_rows_from < 1. + lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF iv_rows_from > iv_rows_to. + lv_errormessage = 'Invalid range supplied for print-title repeatable rowumns'(401). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* adjust internal representation +*--------------------------------------------------------------------* + me->print_title_row_from = iv_rows_from. + me->print_title_row_to = iv_rows_to. + + +*--------------------------------------------------------------------* +* adjust corresponding range +*--------------------------------------------------------------------* + me->print_title_set_range( ). + + + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~GET_STYLE. + IF zif_excel_sheet_properties~style IS NOT INITIAL. + ep_style = zif_excel_sheet_properties~style. + ELSE. + ep_style = me->excel->get_default_style( ). + ENDIF. + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~INITIALIZE. + + zif_excel_sheet_properties~show_zeros = zif_excel_sheet_properties=>c_showzero. + zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_on. + zif_excel_sheet_properties~summaryright = zif_excel_sheet_properties=>c_right_on. + +* inizialize zoomscale values + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale = 100. + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_normal = 100. + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_pagelayoutview = 100 . + ZIF_EXCEL_SHEET_PROPERTIES~zoomscale_sheetlayoutview = 100 . + endmethod. + + + method ZIF_EXCEL_SHEET_PROPERTIES~SET_STYLE. + zif_excel_sheet_properties~style = ip_style. + endmethod. + + + method ZIF_EXCEL_SHEET_PROTECTION~INITIALIZE. + + me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_unprotected. + CLEAR me->zif_excel_sheet_protection~password. + me->zif_excel_sheet_protection~auto_filter = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~delete_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~delete_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~format_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_columns = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_hyperlinks = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~insert_rows = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_noactive. +* me->zif_excel_sheet_protection~password = zif_excel_sheet_protection=>c_noactive. "issue #68 + me->zif_excel_sheet_protection~pivot_tables = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~select_locked_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~select_unlocked_cells = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_noactive. + me->zif_excel_sheet_protection~sort = zif_excel_sheet_protection=>c_noactive. + + endmethod. + + + method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME. + me->zif_excel_sheet_vba_project~codename = ip_codename. + endmethod. + + + method ZIF_EXCEL_SHEET_VBA_PROJECT~SET_CODENAME_PR. + me->zif_excel_sheet_vba_project~codename_pr = ip_codename_pr. + endmethod. + + + + method ADD_DRAWING. + CASE ip_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. + drawings->include( ip_drawing ). + WHEN zcl_excel_drawing=>type_chart. + charts->include( ip_drawing ). + ENDCASE. + endmethod. + + + + method ADD_NEW_CONDITIONAL_STYLE. + + CREATE OBJECT eo_conditional_style. + conditional_styles->add( eo_conditional_style ). + endmethod. + + + + method ADD_NEW_DATA_VALIDATION. + + CREATE OBJECT eo_data_validation. + data_validations->add( eo_data_validation ). + endmethod. + + + + method ADD_NEW_RANGE. +* Create default blank range + CREATE OBJECT eo_range. + ranges->add( eo_range ). + endmethod. + + + + + + + + + + method BIND_ALV. + data: lo_converter type ref to zcl_excel_converter. + + create object lo_converter. + + try. + lo_converter->convert( + exporting + io_alv = io_alv + it_table = it_table + i_row_int = i_top + i_column_int = i_left + i_table = i_table + i_style_table = table_style + io_worksheet = me + changing + co_excel = excel ). + catch zcx_excel . + endtry. + + endmethod. + + + + + + + + + + + + + + + + + + + + + + method BIND_ALV_OLE2. +*--------------------------------------------------------------------* +* Method description: +* Method use to export a CL_GUI_ALV_GRID object to xlsx/xls file +* with list header and characteristics of ALV field catalog such as: +* + Total, group's subtotal +* + Quantity fields, amount fields (dependent fields) +* + No_out, no_zero, ... +* Technique use in method: +* SAP Desktop Office Integration (DOI) +*--------------------------------------------------------------------* + +* Data for session 0: DOI constructor +* ------------------------------------------ + + data: lo_control type ref to I_OI_CONTAINER_CONTROL. + data: lo_proxy type ref to I_OI_DOCUMENT_PROXY. + data: lo_spreadsheet type ref to I_OI_SPREADSHEET. + data: lo_error type ref to I_OI_ERROR. + data: lc_retcode type SOI_RET_STRING. + data: li_has type i. "Proxy has spreadsheet interface? + data: l_is_closed type i. + +* Data for session 1: Get LVC data from ALV object +* ------------------------------------------ + + data: l_has_activex, + l_doctype_excel_sheet(11) type c. + data: wa_DOC_HANDLE Type CNTL_HANDLE. + +* LVC + data: lt_fieldcat_lvc type LVC_T_FCAT. + data: wa_fieldcat_lvc type lvc_s_fcat. + data: lt_sort_lvc type LVC_T_SORT. + data: lt_filter_idx_lvc type LVC_T_FIDX. + data: lt_GROUPLEVELS_LVC type LVC_T_GRPL. + +* KKBLO + DATA: LT_FIELDCAT_KKBLO Type KKBLO_T_FIELDCAT. + DATA: LT_SORT_KKBLO Type KKBLO_T_SORTINFO. + DATA: LT_GROUPLEVELS_KKBLO Type KKBLO_T_GROUPLEVELS. + DATA: LT_FILTER_IDX_KKBLO Type KKBLO_T_SFINFO. + data: wa_listheader like line of it_listheader. + +* Subtotal + data: lt_collect00 type ref to data. + data: lt_collect01 type ref to data. + data: lt_collect02 type ref to data. + data: lt_collect03 type ref to data. + data: lt_collect04 type ref to data. + data: lt_collect05 type ref to data. + data: lt_collect06 type ref to data. + data: lt_collect07 type ref to data. + data: lt_collect08 type ref to data. + data: lt_collect09 type ref to data. + +* data table name + data: l_tabname type kkblo_tabname. + +* local object + data: lo_grid type ref to lcl_gui_alv_grid. + +* data table get from ALV + data: lt_alv type ref to data. + +* total / subtotal data + field-symbols: <f_collect00> type standard table. + field-symbols: <f_collect01> type standard table. + field-symbols: <f_collect02> type standard table. + field-symbols: <f_collect03> type standard table. + field-symbols: <f_collect04> type standard table. + field-symbols: <f_collect05> type standard table. + field-symbols: <f_collect06> type standard table. + field-symbols: <f_collect07> type standard table. + field-symbols: <f_collect08> type standard table. + field-symbols: <f_collect09> type standard table. + +* table before append subtotal lines + field-symbols: <f_alv_tab> type standard table. + +* data for session 2: sort, filter and calculate total/subtotal +* ------------------------------------------ + +* table to save index of subotal / total line in excel tanle +* this ideal to control index of subtotal / total line later +* for ex, when get subtotal / total line to format + types: begin of st_subtot_indexs, + index type i, + end of st_subtot_indexs. + data: lt_subtot_indexs type table of st_subtot_indexs. + data: wa_subtot_indexs like line of lt_subtot_indexs. + +* data table after append subtotal + data: lt_excel type ref to data. + + data: l_tabix type i. + data: l_save_index type i. + +* dyn subtotal table name + data: l_collect type string. + +* subtotal range, to format subtotal (and total) + data: subranges type soi_range_list. + data: subrangeitem type soi_range_item. + data: l_sub_index type i. + + +* table after append subtotal lines + field-symbols: <f_excel_tab> type standard table. + field-symbols: <f_excel_line> type any. + +* dyn subtotal tables + field-symbols: <f_collect_tab> type standard table. + field-symbols: <f_collect_line> type any. + + field-symbols: <f_filter_idx_line> like line of LT_FILTER_IDX_KKBLO. + field-symbols: <f_fieldcat_line> like line of LT_FIELDCAT_KKBLO. + field-symbols: <f_grouplevels_line> like line of LT_GROUPLEVELS_KKBLO. + field-symbols: <f_line> type any. + +* Data for session 3: map data to semantic table +* ------------------------------------------ + + types: begin of st_column_index, + fieldname type kkblo_fieldname, + tabname type kkblo_tabname, + col like sy-index, + end of st_column_index. + +* columns index + data: lt_column_index type table of st_column_index. + data: wa_column_index like line of lt_column_index. + +* table of dependent field ( currency and quantity unit field) + data: lt_fieldcat_depf type kkblo_t_fieldcat. + data: wa_fieldcat_depf type kkblo_fieldcat. + +* XXL interface: +* -XXL: contain exporting columns characteristic + data: lt_sema type table of gxxlt_s initial size 0. + data: wa_sema like line of lt_sema. + +* -XXL interface: header + data: lt_hkey type table of gxxlt_h initial size 0. + data: wa_hkey like line of lt_hkey. + +* -XXL interface: header keys + data: lt_vkey type table of gxxlt_v initial size 0. + data: wa_vkey like line of lt_vkey. + +* Number of H Keys: number of key columns + data: l_n_hrz_keys type i. +* Number of data columns in the list object: non-key columns no + data: l_n_att_cols type i. +* Number of V Keys: number of header row + data: l_n_vrt_keys type i. + +* curency to format amount + data: lt_tcurx type table of tcurx. + data: wa_tcurx like line of lt_tcurx. + data: l_def type flag. " currency / quantity flag + data: wa_t006 type t006. " decimal place of unit + + data: l_num type i. " table columns number + data: l_typ type c. " table type + data: wa type ref to data. + data: l_int type i. + data: l_counter type i. + + field-symbols: <f_excel_column> type any. + field-symbols: <f_fcat_column> type any. + +* Data for session 4: write to excel +* ------------------------------------------ + + data: data_starting_at type i value 1. + data: data_ending_at type i value -1. + data: sema_type type c. + + data l_error type ref to c_oi_proxy_error. + data count type i. + data datac type i. + data datareal type i. " exporting column number + data vkeycount type i. + data all type i. + data mit type i value 1. " index of recent row? + data li_col_pos type i value 1. " column position + data li_col_num type i. " table columns number + field-symbols: <line> type any. + field-symbols: <item> type any. + + data td type sydes_desc. + + data: typ. + data: ranges type soi_range_list. + data: rangeitem type soi_range_item. + data: contents type soi_generic_table. + data: contentsitem type soi_generic_item. + data: semaitem type gxxlt_s. + data: hkeyitem type gxxlt_h. + data: vkeyitem type gxxlt_v. + data: li_commentary_rows type i. "row number of title lines + 1 + data: lo_error_w type ref to i_oi_error. + data: l_retcode type soi_ret_string. + data: no_flush type c value 'X'. + data: li_head_top type i. "header rows position + +* Data for session 5: Save and clode document +* ------------------------------------------ + + data: li_document_size type i. + data: ls_path type RLGRAP-FILENAME. + +* MACRO: Close_document +*------------------------------------------- + + DEFINE close_document. + clear: l_is_closed. + IF lo_proxy is not initial. + +* check proxy detroyed adi + + call method lo_proxy->is_destroyed + IMPORTING + ret_value = l_is_closed. + +* if dun detroyed yet: close -> release proxy + + IF l_is_closed is initial. + call method lo_proxy->close_document +* EXPORTING +* do_save = do_save + IMPORTING + error = lo_error + retcode = lc_retcode. + ENDIF. + + call method lo_proxy->release_document + IMPORTING + error = lo_error + retcode = lC_retcode. + + else. + lc_retcode = c_oi_errors=>ret_document_not_open. + ENDIF. + +* Detroy control container + + IF lo_control is not initial. + CALL METHOD lo_control->destroy_control. + ENDIF. + + clear: + lo_spreadsheet, + lo_proxy, + lo_control. + +* free local + + clear: l_is_closed. + + END-OF-DEFINITION. + +* Macro to catch DOI error +*------------------------------------------- + + DEFINE error_doi. + if lc_retcode ne c_oi_errors=>ret_ok. + close_document. + call method lo_error->raise_message + EXPORTING + type = 'E'. + clear: lo_error. + endif. + END-OF-DEFINITION. + +*--------------------------------------------------------------------* +* SESSION 0: DOI CONSTRUCTOR +*--------------------------------------------------------------------* + +* check active windown + + call function 'GUI_HAS_ACTIVEX' + IMPORTING + return = l_has_activex. + + if l_has_activex is initial. + raise MISS_GUIDE. + endif. + +* Get Container Object of Screen + + call method c_oi_container_control_creator=>get_container_control + IMPORTING + control = lo_control + retcode = lC_retcode. + + error_doi. + +* Initialize Container control + + CALL METHOD lo_control->init_control + EXPORTING + parent = CL_GUI_CONTAINER=>DEFAULT_SCREEN + r3_application_name = '' + inplace_enabled = 'X' + no_flush = 'X' + register_on_close_event = 'X' + register_on_custom_event = 'X' + IMPORTING + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + +* Get Proxy Document: +* check exist of document proxy, if exist -> close first + + if not lo_proxy is initial. + close_document. + endif. + + IF i_xls is not initial. +* xls format, doctype = soi_doctype_excel97_sheet + l_doctype_excel_sheet = 'Excel.Sheet.8'. + else. +* xlsx format, doctype = soi_doctype_excel_sheet + l_doctype_excel_sheet = 'Excel.Sheet'. + ENDIF. + + CALL METHOD lo_control->get_document_proxy + EXPORTING + document_type = l_doctype_excel_sheet + register_container = 'X' + IMPORTING + document_proxy = lo_proxy + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + + IF I_DOCUMENT_URL is initial. + +* create new excel document + + call method lo_proxy->create_document + EXPORTING + create_view_data = 'X' + open_inplace = 'X' + no_flush = 'X' + IMPORTING + ERROR = lO_ERROR + retcode = lc_retcode. + + error_doi. + + else. + +* Read excel template for i_DOCUMENT_URL +* this excel template can be store in local or server + + CALL METHOD lo_proxy->open_document + EXPORTING + document_url = i_document_url + open_inplace = 'X' + no_flush = 'X' + IMPORTING + error = lo_error + retcode = lc_retcode. + + error_doi. + + endif. + +* Check Spreadsheet Interface of Document Proxy + + CALL METHOD lo_proxy->has_spreadsheet_interface + IMPORTING + is_available = li_has + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + +* create Spreadsheet object + + CHECK li_has IS NOT INITIAL. + + CALL METHOD lo_proxy->get_spreadsheet_interface + IMPORTING + sheet_interface = lo_spreadsheet + error = lO_ERROR + retcode = lc_retcode. + + error_doi. + +*--------------------------------------------------------------------* +* SESSION 1: GET LVC DATA FROM ALV OBJECT +*--------------------------------------------------------------------* + +* data table + + create object lo_grid + EXPORTING + i_parent = CL_GUI_CONTAINER=>SCREEN0. + + call method lo_grid->get_alv_attributes + EXPORTING + io_grid = io_alv + IMPORTING + Et_table = lt_alv. + + assign lt_alv->* to <f_alv_tab>. + +* fieldcat + + CALL METHOD iO_alv->GET_FRONTEND_FIELDCATALOG + IMPORTING + ET_FIELDCATALOG = lt_fieldcat_LVC. + +* table name + + loop at lt_fieldcat_LVC into wa_fieldcat_lvc + where not tabname is initial. + l_tabname = wa_fieldcat_lvc-tabname. + exit. + endloop. + + if sy-subrc ne 0. + l_tabname = '1'. + endif. + clear: wa_fieldcat_lvc. + +* sort table + + CALL METHOD IO_ALV->GET_SORT_CRITERIA + IMPORTING + ET_SORT = lt_sort_lvc. + + +* filter index + + CALL METHOD IO_ALV->GET_FILTERED_ENTRIES + IMPORTING + ET_FILTERED_ENTRIES = lt_filter_idx_lvc. + +* group level + subtotal + + CALL METHOD IO_ALV->GET_SUBTOTALS + IMPORTING + EP_COLLECT00 = lt_collect00 + EP_COLLECT01 = lt_collect01 + EP_COLLECT02 = lt_collect02 + EP_COLLECT03 = lt_collect03 + EP_COLLECT04 = lt_collect04 + EP_COLLECT05 = lt_collect05 + EP_COLLECT06 = lt_collect06 + EP_COLLECT07 = lt_collect07 + EP_COLLECT08 = lt_collect08 + EP_COLLECT09 = lt_collect09 + ET_GROUPLEVELS = lt_GROUPLEVELS_LVC. + + assign lt_collect00->* to <f_collect00>. + assign lt_collect01->* to <f_collect01>. + assign lt_collect02->* to <f_collect02>. + assign lt_collect03->* to <f_collect03>. + assign lt_collect04->* to <f_collect04>. + assign lt_collect05->* to <f_collect05>. + assign lt_collect06->* to <f_collect06>. + assign lt_collect07->* to <f_collect07>. + assign lt_collect08->* to <f_collect08>. + assign lt_collect09->* to <f_collect09>. + +* transfer to KKBLO struct + + CALL FUNCTION 'LVC_TRANSFER_TO_KKBLO' + EXPORTING + IT_FIELDCAT_LVC = lt_fieldcat_lvc + IT_SORT_LVC = lt_sort_lvc + IT_FILTER_INDEX_LVC = lt_filter_idx_lvc + IT_GROUPLEVELS_LVC = lt_grouplevels_lvc + IMPORTING + ET_FIELDCAT_KKBLO = lt_fieldcat_kkblo + ET_SORT_KKBLO = lt_sort_kkblo + ET_FILTERED_ENTRIES_KKBLO = lt_filter_idx_kkblo + ET_GROUPLEVELS_KKBLO = lt_grouplevels_kkblo + TABLES + IT_DATA = <f_alv_tab> + EXCEPTIONS + IT_DATA_MISSING = 1 + IT_FIELDCAT_LVC_MISSING = 2 + OTHERS = 3. + IF SY-SUBRC <> 0. + raise ex_transfer_KKBLO_ERROR. + ENDIF. + + clear: + wa_fieldcat_lvc, + lt_fieldcat_lvc, + lt_sort_lvc, + lt_filter_idx_lvc, + lt_GROUPLEVELS_LVC. + + clear: + lo_grid. + + +*--------------------------------------------------------------------* +* SESSION 2: SORT, FILTER AND CALCULATE TOTAL / SUBTOTAL +*--------------------------------------------------------------------* + +* append subtotal & total line + + create data lt_excel like <f_ALV_TAB>. + assign lt_excel->* to <f_excel_tab>. + + loop at <f_alv_tab> assigning <f_line>. + l_save_index = sy-tabix. + +* filter base on filter index table + + read table LT_FILTER_IDX_KKBLO assigning <f_filter_idx_line> + with key index = l_save_index + binary search. + if sy-subrc ne 0. + append <f_line> to <f_excel_tab>. + endif. + +* append subtotal lines + + read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> + with key index_to = l_save_index + binary search. + if sy-subrc = 0. + l_tabix = sy-tabix. + do. + if <f_grouplevels_line>-subtot eq 'X' and + <f_grouplevels_line>-hide_level is initial and + <f_grouplevels_line>-cindex_from ne 0. + +* dynamic append subtotal line to excel table base on grouplevel table +* ex <f_GROUPLEVELS_line>-level = 1 +* then <f_collect_tab> = '<F_COLLECT01>' + + l_collect = <f_grouplevels_line>-level. + condense l_collect. + concatenate '<F_COLLECT0' + l_collect '>' +* '->*' + into l_collect. + + assign (l_collect) to <f_collect_tab>. + +* incase there're more than 1 total line of group, at the same level +* for example: subtotal of multi currency + + LOOP AT <f_collect_tab> assigning <f_collect_line>. + IF sy-tabix between <f_grouplevels_line>-cindex_from + and <f_grouplevels_line>-cindex_to. + + + append <f_collect_line> to <f_excel_tab>. + +* save subtotal lines index + + wa_subtot_indexs-index = sy-tabix. + append wa_subtot_indexs to lt_subtot_indexs. + +* append sub total ranges table for format later + + add 1 to l_sub_index. + subrangeitem-name = l_sub_index. + condense subrangeitem-name. + concatenate 'SUBTOT' + subrangeitem-name + into subrangeitem-name. + + subrangeitem-rows = wa_subtot_indexs-index. + subrangeitem-columns = 1. " start col + append subrangeitem to subranges. + clear: subrangeitem. + + ENDIF. + ENDLOOP. + unassign: <f_collect_tab>. + unassign: <f_collect_line>. + clear: l_collect. + endif. + +* check next subtotal level of group + + unassign: <f_grouplevels_line>. + add 1 to l_tabix. + + read table LT_GROUPLEVELS_KKBLO assigning <f_grouplevels_line> + index l_tabix. + if sy-subrc ne 0 + or <f_grouplevels_line>-index_to ne l_save_index. + exit. + endif. + + unassign: + <f_collect_tab>, + <f_collect_line>. + + enddo. + endif. + + clear: + l_tabix, + l_save_index. + + unassign: + <f_filter_idx_line>, + <f_grouplevels_line>. + + endloop. + +* free local data + + unassign: + <f_line>, + <f_collect_tab>, + <f_collect_line>, + <f_fieldcat_line>. + +* append grand total line + + IF <f_collect00> is assigned. + assign <f_collect00> to <f_collect_tab>. + if <f_collect_tab> is not initial. + LOOP AT <f_collect_tab> assigning <f_collect_line>. + + append <f_collect_line> to <f_excel_tab>. + +* save total line index + + wa_subtot_indexs-index = sy-tabix. + append wa_subtot_indexs to lt_subtot_indexs. + +* append grand total range (to format) + + add 1 to l_sub_index. + subrangeitem-name = l_sub_index. + condense subrangeitem-name. + concatenate 'TOTAL' + subrangeitem-name + into subrangeitem-name. + + subrangeitem-rows = wa_subtot_indexs-index. + subrangeitem-columns = 1. " start col + append subrangeitem to subranges. + ENDLOOP. + endif. + ENDIF. + + clear: + subrangeitem, + LT_SORT_KKBLO, + <f_collect00>, + <f_collect01>, + <f_collect02>, + <f_collect03>, + <f_collect04>, + <f_collect05>, + <f_collect06>, + <f_collect07>, + <f_collect08>, + <f_collect09>. + + unassign: + <f_collect00>, + <f_collect01>, + <f_collect02>, + <f_collect03>, + <f_collect04>, + <f_collect05>, + <f_collect06>, + <f_collect07>, + <f_collect08>, + <f_collect09>, + <f_collect_tab>, + <f_collect_line>. + +*--------------------------------------------------------------------* +* SESSION 3: MAP DATA TO SEMANTIC TABLE +*--------------------------------------------------------------------* + +* get dependent field field: currency and quantity + + create data wa like line of <f_excel_tab>. + assign wa->* to <f_excel_line>. + + describe field <f_excel_line> type l_typ components l_num. + + do l_num times. + l_save_index = sy-index. + assign component l_save_index of structure <f_excel_line> + to <f_excel_column>. + if sy-subrc ne 0. + message e059(0k) with 'FATAL ERROR' raising fatal_error. + endif. + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname. + assign component <f_fieldcat_line>-fieldname + of structure <f_excel_line> to <f_fcat_column>. + + describe distance between <f_excel_column> and <f_fcat_column> + into l_int in byte mode. + +* append column index +* this columns index is of table, not fieldcat + + if l_int = 0. + wa_column_index-fieldname = <f_fieldcat_line>-fieldname. + wa_column_index-tabname = <f_fieldcat_line>-tabname. + wa_column_index-col = l_save_index. + append wa_column_index to lt_column_index. + endif. + +* append dependent fields (currency and quantity unit) + + if <f_fieldcat_line>-cfieldname is not initial. + clear wa_fieldcat_depf. + wa_fieldcat_depf-fieldname = <f_fieldcat_line>-cfieldname. + wa_fieldcat_depf-tabname = <f_fieldcat_line>-ctabname. + collect wa_fieldcat_depf into lt_fieldcat_depf. + endif. + + if <f_fieldcat_line>-qfieldname is not initial. + clear wa_fieldcat_depf. + wa_fieldcat_depf-fieldname = <f_fieldcat_line>-qfieldname. + wa_fieldcat_depf-tabname = <f_fieldcat_line>-qtabname. + collect wa_fieldcat_depf into lt_fieldcat_depf. + endif. + +* rewrite field data type + + if <f_fieldcat_line>-inttype = 'X' + and <f_fieldcat_line>-datatype(3) = 'INT'. + <f_fieldcat_line>-inttype = 'I'. + endif. + + endloop. + + clear: l_save_index. + unassign: <f_fieldcat_line>. + + enddo. + +* build semantic tables + + l_n_hrz_keys = 1. + +* Get keyfigures + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname + and tech ne 'X' + and no_out ne 'X'. + + clear wa_sema. + clear wa_hkey. + +* Units belong to keyfigures -> display as str + + read table lt_fieldcat_depf into wa_fieldcat_depf with key + fieldname = <f_fieldcat_line>-fieldname + tabname = <f_fieldcat_line>-tabname. + + if sy-subrc = 0. + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. + +* Keyfigures + + else. + case <f_fieldcat_line>-datatype. + when 'QUAN'. + wa_sema-col_typ = 'N03'. + + if <f_fieldcat_line>-no_sum ne 'X'. + wa_sema-col_ops = 'ADD'. + else. + wa_sema-col_ops = 'NOP'. " no dependent field + endif. + + when 'DATS'. + wa_sema-col_typ = 'DAT'. + wa_sema-col_ops = 'NOP'. + + when 'CHAR' OR 'UNIT' OR 'CUKY'. " Added fieldformats UNIT and CUKY - dd. 26-10-2012 Wouter Heuvelmans + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. " dependent field + +* incase numeric, ex '00120' -> display as '12' + + when 'NUMC'. + wa_sema-col_typ = 'STR'. + wa_sema-col_ops = 'DFT'. + + when others. + wa_sema-col_typ = 'NUM'. + + if <f_fieldcat_line>-no_sum ne 'X'. + wa_sema-col_ops = 'ADD'. + else. + wa_sema-col_ops = 'NOP'. + endif. + endcase. + endif. + + l_counter = l_counter + 1. + l_n_att_cols = l_n_att_cols + 1. + + wa_sema-col_no = l_counter. + + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-fieldname + tabname = <f_fieldcat_line>-tabname. + + if sy-subrc = 0. + wa_sema-col_src = wa_column_index-col. + else. + raise fatal_error. + endif. + +* columns index of ref currency field in table + + if not <f_fieldcat_line>-cfieldname is initial. + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-cfieldname + tabname = <f_fieldcat_line>-ctabname. + + if sy-subrc = 0. + wa_sema-col_cur = wa_column_index-col. + endif. + +* quantities fields +* treat as currency when display on excel + + elseif not <f_fieldcat_line>-qfieldname is initial. + read table lt_column_index into wa_column_index with key + fieldname = <f_fieldcat_line>-qfieldname + tabname = <f_fieldcat_line>-qtabname. + if sy-subrc = 0. + wa_sema-col_cur = wa_column_index-col. + endif. + + endif. + +* Treat of fixed currency in the fieldcatalog for column + + data: l_num_help(2) type n. + + if not <f_fieldcat_line>-currency is initial. + + select * from tcurx into table lt_tcurx. + sort lt_tcurx. + read table lt_tcurx into wa_tcurx + with key currkey = <f_fieldcat_line>-currency. + if sy-subrc = 0. + l_num_help = wa_tcurx-currdec. + concatenate 'N' l_num_help into wa_sema-col_typ. + wa_sema-col_cur = sy-tabix * ( -1 ). + endif. + + endif. + + wa_hkey-col_no = l_n_att_cols. + wa_hkey-row_no = l_n_hrz_keys. + wa_hkey-col_name = <f_fieldcat_line>-reptext. + append wa_hkey to lt_hkey. + append wa_sema to lt_sema. + + endloop. + +* free local data + + clear: + lt_column_index, + wa_column_index, + lt_fieldcat_depf, + wa_fieldcat_depf, + lt_tcurx, + wa_tcurx, + l_num, + l_typ, + wa, + l_int, + l_counter. + + unassign: + <f_fieldcat_line>, + <f_excel_line>, + <f_excel_column>, + <f_fcat_column>. + +*--------------------------------------------------------------------* +* SESSION 4: WRITE TO EXCEL +*--------------------------------------------------------------------* + + clear: wa_tcurx. + refresh: lt_tcurx. + +* if spreadsheet dun have proxy yet + + if li_has is initial. + l_retcode = c_oi_errors=>ret_interface_not_supported. + call method c_oi_errors=>create_error_for_retcode + EXPORTING + retcode = l_retcode + no_flush = no_flush + IMPORTING + error = lo_error_w. + exit. + endif. + + create object l_error + EXPORTING + object_name = 'OLE_DOCUMENT_PROXY' + method_name = 'get_ranges_names'. + + call method c_oi_errors=>add_error + EXPORTING + error = l_error. + + + describe table lt_sema lines datareal. + describe table <f_excel_tab> lines datac. + describe table lt_vkey lines vkeycount. + + if datac = 0. + raise inv_data_range. + endif. + + + if vkeycount ne l_n_vrt_keys. + raise dim_mismatch_vkey. + endif. + + all = l_n_vrt_keys + l_n_att_cols. + + if datareal ne all. + raise dim_mismatch_sema. + endif. + + data: decimal type c. + +* get decimal separator format ('.', ',', ...) in Office config + + call method lo_proxy->get_application_property + EXPORTING + property_name = 'INTERNATIONAL' + subproperty_name = 'DECIMAL_SEPARATOR' + CHANGING + retvalue = decimal. + + data: wa_usr type usr01. + select * from usr01 into wa_usr where bname = sy-uname. + endselect. + + data: comma_elim(4) type c. + data: help6 type i. + field-symbols <g> type any. + data search_item(4) value ' #'. + + concatenate ',' decimal '.' decimal into comma_elim. + + data help type i. " table (with subtotal) line number + + help = datac. + + data: rowmax type i value 1. " header row number + data: columnmax type i value 0. " header columns number + + loop at lt_hkey into hkeyitem. + if hkeyitem-col_no > columnmax. + columnmax = hkeyitem-col_no. + endif. + + if hkeyitem-row_no > rowmax. + rowmax = hkeyitem-row_no. + endif. + endloop. + + data: hkeycolumns type i. " header columns no + + hkeycolumns = columnmax. + + if hkeycolumns < l_n_att_cols. + hkeycolumns = l_n_att_cols. + endif. + + columnmax = 0. + + loop at lt_vkey into vkeyitem. + if vkeyitem-col_no > columnmax. + columnmax = vkeyitem-col_no. + endif. + endloop. + + data overflow type i value 1. + data testname(10) type c. + data temp2 type i. " 1st item row position in excel + data realmit type i value 1. + data realoverflow type i value 1. " row index in content + + call method lo_spreadsheet->screen_update + EXPORTING + updating = ''. + + call method lo_spreadsheet->load_lib. + + data: str(40) type c. " range names of columns range (w/o col header) + data: rows type i. " row postion of 1st item line in ecxel + +* calculate row position of data table + + describe table iT_LISTHEADER lines li_commentary_rows. + +* if grid had title, add 1 empy line between title and table + + if li_commentary_rows ne 0. + add 1 to li_commentary_rows. + endif. + +* add top position of block data + + li_commentary_rows = li_commentary_rows + i_top - 1. + +* write header (commentary rows) + + data: li_commentary_row_index type i value 1. + data: li_content_index type i value 1. + data: ls_index(10) type c. + data ls_commentary_range(40) type c value 'TITLE'. + data: li_font_bold type i. + data: li_font_italic type i. + data: li_font_size type i. + + loop at iT_LISTHEADER into wa_listheader. + li_commentary_row_index = i_top + li_content_index - 1. + ls_index = li_content_index. + condense ls_index. + concatenate ls_commentary_range(5) ls_index + into ls_commentary_range. + condense ls_commentary_range. + +* insert title range + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = ls_commentary_range + top = li_commentary_row_index + left = i_left + rows = 1 + columns = 1 + no_flush = no_flush. + +* format range + + case wa_listheader-typ. + when 'H'. "title + li_font_size = 16. + li_font_bold = 1. + li_font_italic = -1. + when 'S'. "subtile + li_font_size = -1. + li_font_bold = 1. + li_font_italic = -1. + when others. "'A' comment + li_font_size = -1. + li_font_bold = -1. + li_font_italic = 1. + endcase. + + call method lo_spreadsheet->set_font + EXPORTING + rangename = ls_commentary_range + family = '' + size = li_font_size + bold = li_font_bold + italic = li_font_italic + align = 0 + no_flush = no_flush. + +* title: range content + + rangeitem-name = ls_commentary_range. + rangeitem-columns = 1. + rangeitem-rows = 1. + append rangeitem to ranges. + + contentsitem-row = li_content_index. + contentsitem-column = 1. + concatenate wa_listheader-key + wa_listheader-info + into contentsitem-value + separated by space. + condense contentsitem-value. + append contentsitem to contents. + + add 1 to li_content_index. + + clear: + rangeitem, + contentsitem, + ls_index. + + endloop. + +* set range data title + + call method lo_spreadsheet->set_ranges_data + EXPORTING + ranges = ranges + contents = contents + no_flush = no_flush. + + refresh: + ranges, + contents. + + rows = rowmax + li_commentary_rows + 1. + + all = wa_usr-datfm. + all = all + 3. + + loop at lt_sema into semaitem. + if semaitem-col_typ = 'DAT' or semaitem-col_typ = 'MON' or + semaitem-col_typ = 'N00' or semaitem-col_typ = 'N01' or + semaitem-col_typ = 'N01' or semaitem-col_typ = 'N02' or + semaitem-col_typ = 'N03' or semaitem-col_typ = 'PCT' or + semaitem-col_typ = 'STR' or semaitem-col_typ = 'NUM'. + clear str. + str = semaitem-col_no. + condense str. + concatenate 'DATA' str into str. + mit = semaitem-col_no. + li_col_pos = semaitem-col_no + i_left - 1. + +* range from data1 to data(n), for each columns of table + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = str + top = rows + left = li_col_pos + rows = help + columns = 1 + no_flush = no_flush. + + data dec type i value -1. + data typeinfo type sydes_typeinfo. + loop at <f_excel_tab> assigning <line>. + assign component semaitem-col_no of structure <line> to <item>. + describe field <item> into td. + read table td-types index 1 into typeinfo. + if typeinfo-type = 'P'. + dec = typeinfo-decimals. + elseif typeinfo-type = 'I'. + dec = 0. + endif. + + describe field <line> type typ components count. + mit = 1. + do count times. + if mit = semaitem-col_src. + assign component sy-index of structure <line> to <item>. + describe field <item> into td. + read table td-types index 1 into typeinfo. + if typeinfo-type = 'P'. + dec = typeinfo-decimals. + endif. + exit. + endif. + mit = mit + 1. + enddo. + exit. + endloop. + +* format for each columns of table (w/o columns headers) + + if semaitem-col_typ = 'DAT'. + if semaitem-col_no > vkeycount. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = all + no_flush = no_flush. + else. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 0 + no_flush = no_flush. + endif. + elseif semaitem-col_typ = 'STR'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 0 + no_flush = no_flush. + elseif semaitem-col_typ = 'MON'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 10 + no_flush = no_flush. + elseif semaitem-col_typ = 'N00'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 0 + no_flush = no_flush. + elseif semaitem-col_typ = 'N01'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 1 + no_flush = no_flush. + elseif semaitem-col_typ = 'N02'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 2 + no_flush = no_flush. + elseif semaitem-col_typ = 'N03'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 3 + no_flush = no_flush. + elseif semaitem-col_typ = 'N04'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 4 + no_flush = no_flush. + elseif semaitem-col_typ = 'NUM'. + if dec eq -1. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = 2 + no_flush = no_flush. + else. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 1 + decimals = dec + no_flush = no_flush. + endif. + elseif semaitem-col_typ = 'PCT'. + call method lo_spreadsheet->set_format + EXPORTING + rangename = str + currency = '' + typ = 3 + decimals = 0 + no_flush = no_flush. + endif. + + endif. + endloop. + +* get item contents for set_range_data method +* get currency cell also + + mit = 1. + + data: currcells type soi_cell_table. + data: curritem type soi_cell_item. + + curritem-rows = 1. + curritem-columns = 1. + curritem-front = -1. + curritem-back = -1. + curritem-font = ''. + curritem-size = -1. + curritem-bold = -1. + curritem-italic = -1. + curritem-align = -1. + curritem-frametyp = -1. + curritem-framecolor = -1. + curritem-currency = ''. + curritem-number = 1. + curritem-input = -1. + + data: conv_exit(10) type c. + data: const type i. + +* Change for Correction request +* Initial 10000 lines are missing in Excel Export +* if there are only 2 columns in exported List object. + + if datareal gt 2. + const = 20000 / datareal. + else. + const = 20000 / ( datareal + 2 ). + endif. + + data: lines type i. + data: innerlines type i. + data: counter type i. + data: curritem2 like curritem. + data: curritem3 like curritem. + data: length type i. + data: found. + +* append content table (for method set_range_content) + + loop at <f_excel_tab> assigning <line>. + +* save line index to compare with lt_subtot_indexs, +* to discover line is a subtotal / totale line or not +* ex use to set 'dun display zero in subtotal / total line' + + l_save_index = sy-tabix. + + do datareal times. + read table lt_sema into semaitem with key col_no = sy-index. + if semaitem-col_src ne 0. + assign component semaitem-col_src + of structure <line> to <item>. + else. + assign component sy-index + of structure <line> to <item>. + endif. + + contentsitem-row = realoverflow. + + if sy-subrc = 0. + move semaitem-col_ops to search_item(3). + search 'ADD#CNT#MIN#MAX#AVG#NOP#DFT#' + for search_item. + if sy-subrc ne 0. + raise error_in_sema. + endif. + move semaitem-col_typ to search_item(3). + search 'NUM#N00#N01#N02#N03#N04#PCT#DAT#MON#STR#' + for search_item. + if sy-subrc ne 0. + raise error_in_sema. + endif. + contentsitem-column = sy-index. + if semaitem-col_typ eq 'DAT' or semaitem-col_typ eq 'MON'. + if semaitem-col_no > vkeycount. + + " Hinweis 512418 + " EXCEL bezieht Datumsangaben + " auf den 31.12.1899, behandelt + " aber 1900 als ein Schaltjahr + " d.h. ab 1.3.1900 korrekt + " 1.3.1900 als Zahl = 61 + + data: genesis type d value '18991230'. + data: number_of_days type p. +* change for date in char format & sema_type = X + data: temp_date type d. + + if not <item> is initial and not <item> co ' ' and not + <item> co '0'. +* change for date in char format & sema_type = X starts + if sema_type = 'X'. + describe field <item> type typ. + if typ = 'C'. + temp_date = <item>. + number_of_days = temp_date - genesis. + else. + number_of_days = <item> - genesis. + endif. + else. + number_of_days = <item> - genesis. + endif. +* change for date in char format & sema_type = X ends + if number_of_days < 61. + number_of_days = number_of_days - 1. + endif. + + set country 'DE'. + write number_of_days to contentsitem-value + no-grouping + left-justified. + set country space. + translate contentsitem-value using comma_elim. + else. + clear contentsitem-value. + endif. + else. + move <item> to contentsitem-value. + endif. + elseif semaitem-col_typ eq 'NUM' or + semaitem-col_typ eq 'N00' or + semaitem-col_typ eq 'N01' or + semaitem-col_typ eq 'N02' or + semaitem-col_typ eq 'N03' or + semaitem-col_typ eq 'N04' or + semaitem-col_typ eq 'PCT'. + set country 'DE'. + describe field <item> type typ. + + if semaitem-col_cur is initial. + if typ ne 'F'. + write <item> to contentsitem-value no-grouping + no-sign decimals 14. + else. + write <item> to contentsitem-value no-grouping + no-sign. + endif. + else. +* Treat of fixed curreny for column >>Y9CK007319 + if semaitem-col_cur < 0. + semaitem-col_cur = semaitem-col_cur * ( -1 ). + select * from tcurx into table lt_tcurx. + sort lt_tcurx. + read table lt_tcurx into + wa_tcurx index semaitem-col_cur. + if sy-subrc = 0. + if typ ne 'F'. + write <item> to contentsitem-value no-grouping + currency wa_tcurx-currkey no-sign decimals 14. + else. + write <item> to contentsitem-value no-grouping + currency wa_tcurx-currkey no-sign. + endif. + endif. + else. + assign component semaitem-col_cur + of structure <line> to <g>. +* mit = index of recent row + curritem-top = rowmax + mit + li_commentary_rows. + + li_col_pos = sy-index + i_left - 1. + curritem-left = li_col_pos. + +* if filed is quantity field (qfieldname ne space) +* or amount field (cfieldname ne space), then format decimal place +* corresponding with config + + clear: l_def. + read table LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + with key tabname = l_tabname + tech = space + no_out = space + col_pos = semaitem-col_no. + IF sy-subrc = 0. + IF <f_fieldcat_line>-cfieldname is not initial. + l_def = 'C'. + else."if <f_fieldcat_line>-qfieldname is not initial. + l_def = 'Q'. + ENDIF. + ENDIF. + +* if field is amount field +* exporting of amount field base on currency decimal table: TCURX + IF l_def = 'C'. "field is amount field + select single * from tcurx into wa_tcurx + where currkey = <g>. +* if amount ref to un-know currency -> default decimal = 2 + if sy-subrc eq 0. + curritem-decimals = wa_tcurx-currdec. + else. + curritem-decimals = 2. + endif. + + append curritem to currcells. + if typ ne 'F'. + write <item> to contentsitem-value + currency <g> + no-sign no-grouping. + else. + write <item> to contentsitem-value + decimals 14 currency <g> + no-sign no-grouping. + endif. + +* if field is quantity field +* exporting of quantity field base on quantity decimal table: T006 + + else."if l_def = 'Q'. " field is quantity field + clear: wa_t006. + select single * from t006 into wa_t006 + where MSEHI = <g>. +* if quantity ref to un-know unit-> default decimal = 2 + if sy-subrc eq 0. + curritem-decimals = wa_t006-decan. + else. + curritem-decimals = 2. + endif. + append curritem to currcells. + + write <item> to contentsitem-value + unit <g> + no-sign no-grouping. + condense contentsitem-value. + + ENDIF. + + endif. "Y9CK007319 + endif. + condense contentsitem-value. + +* add function fieldcat-no zero display + + loop at LT_FIELDCAT_KKBLO assigning <f_fieldcat_line> + where tabname = l_tabname + and tech ne 'X' + and no_out ne 'X'. + if <f_fieldcat_line>-col_pos = semaitem-col_no. + if <f_fieldcat_line>-no_zero = 'X'. + if <item> = '0'. + clear: contentsitem-value. + endif. + +* dun display zero in total/subtotal line too + + else. + clear: wa_subtot_indexs. + read table lt_subtot_indexs into wa_subtot_indexs + with key index = l_save_index. + IF sy-subrc = 0. + if <item> = '0'. + clear: contentsitem-value. + endif. + ENDIF. + endif. + endif. + endloop. + unassign: <f_fieldcat_line>. + + if <item> lt 0. + search contentsitem-value for 'E'. + if sy-fdpos eq 0. + +* use prefix notation for signed numbers + + translate contentsitem-value using '- '. + condense contentsitem-value no-gaps. + concatenate '-' contentsitem-value + into contentsitem-value. + else. + concatenate '-' contentsitem-value + into contentsitem-value. + endif. + endif. + set country space. +* Hier wird nur die korrekte Kommaseparatierung gemacht, wenn die +* Zeichen einer +* Zahl enthalten sind. Das ist für Timestamps, die auch ":" enthalten. +* Für die +* darf keine Kommaseparierung stattfinden. +* Changing for correction request - Y6BK041073 + if contentsitem-value co '0123456789.,-+E '. + translate contentsitem-value using comma_elim. + endif. + else. + clear contentsitem-value. + +* if type is not numeric -> dun display with zero + + write <item> to contentsitem-value no-zero. + + shift contentsitem-value left deleting leading space. + + endif. + append contentsitem to contents. + endif. + enddo. + + realmit = realmit + 1. + realoverflow = realoverflow + 1. + + mit = mit + 1. +* overflow = current row index in content table + overflow = overflow + 1. + endloop. + + unassign: <f_fieldcat_line>. + +* set item range for set_range_data method + + testname = mit / const. + condense testname. + + concatenate 'TEST' testname into testname. + + realoverflow = realoverflow - 1. + realmit = realmit - 1. + help = realoverflow. + + rangeitem-name = testname. + rangeitem-columns = datareal. + rangeitem-rows = help. + append rangeitem to ranges. + +* insert item range dim + + temp2 = rowmax + 1 + li_commentary_rows + realmit - realoverflow. + +* items data + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = testname + top = temp2 + left = i_left + rows = help + columns = datareal + no_flush = no_flush. + +* get columns header contents for set_range_data method +* export columns header only if no columns header option = space + + data: rowcount type i. + data: columncount type i. + + if i_columns_header = 'X'. + +* append columns header to contents: hkey + + rowcount = 1. + do rowmax times. + columncount = 1. + do hkeycolumns times. + loop at lt_hkey into hkeyitem where col_no = columncount + and row_no = rowcount. + endloop. + if sy-subrc = 0. + str = hkeyitem-col_name. + contentsitem-value = hkeyitem-col_name. + else. + contentsitem-value = str. + endif. + contentsitem-column = columncount. + contentsitem-row = rowcount. + append contentsitem to contents. + columncount = columncount + 1. + enddo. + rowcount = rowcount + 1. + enddo. + +* incase columns header in multiline + + data: rowmaxtemp type i. + if rowmax > 1. + rowmaxtemp = rowmax - 1. + rowcount = 1. + do rowmaxtemp times. + columncount = 1. + do columnmax times. + contentsitem-column = columncount. + contentsitem-row = rowcount. + contentsitem-value = ''. + append contentsitem to contents. + columncount = columncount + 1. + enddo. + rowcount = rowcount + 1. + enddo. + endif. + +* append columns header to contents: vkey + + columncount = 1. + do columnmax times. + loop at lt_vkey into vkeyitem where col_no = columncount. + endloop. + contentsitem-value = vkeyitem-col_name. + contentsitem-row = rowmax. + contentsitem-column = columncount. + append contentsitem to contents. + columncount = columncount + 1. + enddo. +*--------------------------------------------------------------------* +* set header range for method set_range_data +* insert header keys range dim + + li_head_top = li_commentary_rows + 1. + li_col_pos = i_left. + +* insert range headers + + if hkeycolumns ne 0. + rangeitem-name = 'TESTHKEY'. + rangeitem-rows = rowmax. + rangeitem-columns = hkeycolumns. + append rangeitem to ranges. + clear: rangeitem. + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = 'TESTHKEY' + top = li_head_top + left = li_col_pos + rows = rowmax + columns = hkeycolumns + no_flush = no_flush. + endif. + endif. + +* format for columns header + total + subtotal +* ------------------------------------------ + + help = rowmax + realmit. " table + header lines + + data: item type colxxl_t. + data: lt_format type soi_format_table. + data: wa_format like line of lt_format. + data: wa_format_temp like line of lt_format. + + field-symbols: <f_source> type any. + field-symbols: <f_des> type any. + +* columns header format + + wa_format-front = -1. + wa_format-back = 15. "grey + wa_format-font = space. + wa_format-size = -1. + wa_format-bold = 1. + wa_format-align = 0. + wa_format-frametyp = -1. + wa_format-framecolor = -1. + +* get column header format from input record +* -> map input format + + if i_columns_header = 'X'. + wa_format-name = 'TESTHKEY'. + if i_format_col_header is not initial. + describe field i_format_col_header type l_typ components + li_col_num. + do li_col_num times. + if sy-index ne 1. " dun map range name + assign component sy-index of structure i_format_col_header + to <f_source>. + if <f_source> is not initial. + assign component sy-index of structure wa_format to <f_des>. + <f_des> = <f_source>. + unassign: <f_des>. + endif. + unassign: <f_source>. + endif. + enddo. + + clear: li_col_num. + endif. + + append wa_format to lt_format. + endif. + +* Zusammenfassen der Spalten mit gleicher Nachkommastellenzahl +* collect vertical cells (col) with the same number of decimal places +* to increase perfomance in currency cell format + + describe table currcells lines lines. + lines = lines - 1. + do lines times. + describe table currcells lines innerlines. + innerlines = innerlines - 1. + sort currcells by left top. + clear found. + do innerlines times. + read table currcells index sy-index into curritem. + counter = sy-index + 1. + read table currcells index counter into curritem2. + if curritem-left eq curritem2-left. + length = curritem-top + curritem-rows. + if length eq curritem2-top. + if curritem-decimals eq curritem2-decimals. + move curritem to curritem3. + curritem3-rows = curritem3-rows + curritem2-rows. + curritem-left = -1. + modify currcells index sy-index from curritem. + curritem2-left = -1. + modify currcells index counter from curritem2. + append curritem3 to currcells. + found = 'X'. + endif. + endif. + endif. + enddo. + if found is initial. + exit. + endif. + delete currcells where left = -1. + enddo. + +* Zusammenfassen der Zeilen mit gleicher Nachkommastellenzahl +* collect horizontal cells (row) with the same number of decimal places +* to increase perfomance in currency cell format + + describe table currcells lines lines. + lines = lines - 1. + do lines times. + describe table currcells lines innerlines. + innerlines = innerlines - 1. + sort currcells by top left. + clear found. + do innerlines times. + read table currcells index sy-index into curritem. + counter = sy-index + 1. + read table currcells index counter into curritem2. + if curritem-top eq curritem2-top and curritem-rows eq + curritem2-rows. + length = curritem-left + curritem-columns. + if length eq curritem2-left. + if curritem-decimals eq curritem2-decimals. + move curritem to curritem3. + curritem3-columns = curritem3-columns + curritem2-columns. + curritem-left = -1. + modify currcells index sy-index from curritem. + curritem2-left = -1. + modify currcells index counter from curritem2. + append curritem3 to currcells. + found = 'X'. + endif. + endif. + endif. + enddo. + if found is initial. + exit. + endif. + delete currcells where left = -1. + enddo. +* Ende der Zusammenfassung + + +* item data: format for currency cell, corresponding with currency + + call method lo_spreadsheet->cell_format + EXPORTING + cells = currcells + no_flush = no_flush. + +* item data: write item table content + + call method lo_spreadsheet->set_ranges_data + EXPORTING + ranges = ranges + contents = contents + no_flush = no_flush. + +* whole table range to format all table + + if i_columns_header = 'X'. + li_head_top = li_commentary_rows + 1. + else. + li_head_top = li_commentary_rows + 2. + help = help - 1. + endif. + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = 'WHOLE_TABLE' + top = li_head_top + left = i_left + rows = help + columns = datareal + no_flush = no_flush. + +* columns width auto fix +* this parameter = space in case use with exist template + + IF i_columns_autofit = 'X'. + call method lo_spreadsheet->fit_widest + EXPORTING + name = 'WHOLE_TABLE' + no_flush = no_flush. + ENDIF. + +* frame +* The parameter has 8 bits +*0 Left margin +*1 Top marginT +*2 Bottom margin +*3 Right margin +*4 Horizontal line +*5 Vertical line +*6 Thinness +*7 Thickness +* here 127 = 1111111 6-5-4-3-2-1 mean Thin-ver-hor-right-bot-top-left + +* ( final DOI method call, set no_flush = space +* equal to call method CL_GUI_CFW=>FLUSH ) + + call method lo_spreadsheet->set_frame + EXPORTING + rangename = 'WHOLE_TABLE' + typ = 127 + color = 1 + no_flush = space + IMPORTING + error = lo_error + retcode = lc_retcode. + + error_doi. + +* reformat subtotal / total line after format wholw table + + loop at subranges into subrangeitem. + l_sub_index = subrangeitem-rows + li_commentary_rows + rowmax. + + call method lo_spreadsheet->insert_range_dim + EXPORTING + name = subrangeitem-name + left = i_left + top = l_sub_index + rows = 1 + columns = datareal + no_flush = no_flush. + + wa_format-name = subrangeitem-name. + +* default format: +* - clolor: subtotal = light yellow, subtotal = yellow +* - frame: box + + IF subrangeitem-name(3) = 'SUB'. + wa_format-back = 36. "subtotal line + wa_format_temp = i_format_subtotal. + else. + wa_format-back = 27. "total line + wa_format_temp = i_format_total. + endif. + wa_format-FRAMETYP = 79. + wa_format-FRAMEcolor = 1. + wa_format-number = -1. + wa_format-align = -1. + +* get subtoal + total format from intput parameter +* overwrite default format + + if wa_format_temp is not initial. + describe field wa_format_temp type l_typ components li_col_num. + do li_col_num times. + if sy-index ne 1. " dun map range name + assign component sy-index of structure wa_format_temp + to <f_source>. + if <f_source> is not initial. + assign component sy-index of structure wa_format to <f_des>. + <f_des> = <f_source>. + unassign: <f_des>. + endif. + unassign: <f_source>. + endif. + enddo. + + clear: li_col_num. + endif. + + append wa_format to lt_format. + clear: wa_format-name. + clear: l_sub_index. + clear: wa_format_temp. + + endloop. + + if lt_format[] is not initial. + call method lo_spreadsheet->set_ranges_format + EXPORTING + formattable = lt_format + no_flush = no_flush. + refresh: lt_format. + endif. +*--------------------------------------------------------------------* + call method lo_spreadsheet->screen_update + EXPORTING + updating = 'X'. + + call method c_oi_errors=>flush_errors. + + lo_error_w = l_error. + lc_retcode = lo_error_w->error_code. + +** catch no_flush -> led to dump ( optional ) +* go_error = l_error. +* gc_retcode = go_error->error_code. +* error_doi. + + clear: + lt_sema, + wa_sema, + lt_hkey, + wa_hkey, + lt_vkey, + wa_vkey, + l_n_hrz_keys, + l_n_att_cols, + l_n_vrt_keys, + count, + datac, + datareal, + vkeycount, + all, + mit, + li_col_pos, + li_col_num, + ranges, + rangeitem, + contents, + contentsitem, + semaitem, + hkeyitem, + vkeyitem, + li_commentary_rows, + l_retcode, + li_head_top, + <f_excel_tab>. + + clear: + lo_error_w. + + unassign: + <line>, + <item>, + <f_excel_tab>. + +*--------------------------------------------------------------------* +* SESSION 5: SAVE AND CLOSE FILE +*--------------------------------------------------------------------* + +* ex of save path: 'FILE://C:\temp\test.xlsx' + concatenate 'FILE://' I_save_path + into ls_path. + + call method lo_proxy->save_document_to_url + EXPORTING + no_flush = 'X' + url = ls_path + IMPORTING + error = lo_error + retcode = lc_retcode + CHANGING + document_size = li_document_size. + + error_doi. + +* if save successfully -> raise successful message +* message i499(sy) with 'Document is Exported to ' p_path. + message i499(sy) with 'Data has been exported successfully'. + + clear: + ls_path, + li_document_size. + + close_document. + endmethod. + + + + + + + + + method BIND_TABLE. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmöcker, (wi p) 2012-12-01 +* - ... +* aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue #237 - Check if overlapping areas exist +* - Alessandro Iannacci 2012-12-01 +* changes: - Added raise if overlaps are detected +*--------------------------------------------------------------------* + + CONSTANTS: + lc_top_left_column TYPE zexcel_cell_column_alpha VALUE 'A', + lc_top_left_row TYPE zexcel_cell_row VALUE 1. + + DATA: + lv_row_int TYPE zexcel_cell_row, + lv_first_row TYPE zexcel_cell_row, + lv_last_row TYPE zexcel_cell_row, + lv_column_int TYPE zexcel_cell_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lt_field_catalog TYPE zexcel_t_fieldcatalog, + lv_id TYPE i, + lv_rows TYPE i, + lv_formula TYPE string, + ls_settings TYPE zexcel_s_table_settings, + lo_table TYPE REF TO zcl_excel_table, + lt_column_name_buffer TYPE SORTED TABLE OF string WITH UNIQUE KEY table_line, + lv_value TYPE string, + lv_value_lowercase TYPE string, + lv_syindex TYPE char3, + lv_errormessage TYPE string, "ins issue #237 + + lv_columns TYPE i, + lt_columns TYPE zexcel_t_fieldcatalog, + lv_maxcol TYPE i, + lv_maxrow TYPE i, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_curtable TYPE REF TO zcl_excel_table. + + FIELD-SYMBOLS: + <ls_field_catalog> TYPE zexcel_s_fieldcatalog, + <ls_field_catalog_custom> TYPE zexcel_s_fieldcatalog, + <fs_table_line> TYPE ANY, + <fs_fldval> TYPE ANY. + + ls_settings = is_table_settings. + + IF ls_settings-top_left_column IS INITIAL. + ls_settings-top_left_column = lc_top_left_column. + ENDIF. + + IF ls_settings-table_style IS INITIAL. + ls_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ENDIF. + + IF ls_settings-top_left_row IS INITIAL. + ls_settings-top_left_row = lc_top_left_row. + ENDIF. + + IF it_field_catalog IS NOT SUPPLIED. + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = ip_table ). + ELSE. + lt_field_catalog = it_field_catalog. + ENDIF. + + SORT lt_field_catalog BY position. + +*--------------------------------------------------------------------* +* issue #237 Check if overlapping areas exist Start +*--------------------------------------------------------------------* + "Get the number of columns for the current table + lt_columns = lt_field_catalog. + DELETE lt_columns WHERE dynpfld NE abap_true. + DESCRIBE TABLE lt_columns LINES lv_columns. + + "Calculate the top left row of the current table + lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). + lv_row_int = ls_settings-top_left_row. + + "Get number of row for the current table + DESCRIBE TABLE ip_table LINES lv_rows. + + "Calculate the bottom right row for the current table + lv_maxcol = lv_column_int + lv_columns - 1. + lv_maxrow = lv_row_int + lv_rows - 1. + ls_settings-bottom_right_column = zcl_excel_common=>convert_column2alpha( lv_maxcol ). + ls_settings-bottom_right_row = lv_maxrow. + + lv_column_int = zcl_excel_common=>convert_column2int( ls_settings-top_left_column ). + + lo_iterator = me->tables->if_object_collection~get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + + lo_curtable ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF ( ( ls_settings-top_left_row GE lo_curtable->settings-top_left_row AND ls_settings-top_left_row LE lo_curtable->settings-bottom_right_row ) + OR + ( ls_settings-bottom_right_row GE lo_curtable->settings-top_left_row AND ls_settings-bottom_right_row LE lo_curtable->settings-bottom_right_row ) + ) + AND + ( ( lv_column_int GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_column_int LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) + OR + ( lv_maxcol GE zcl_excel_common=>convert_column2int( lo_curtable->settings-top_left_column ) AND lv_maxcol LE zcl_excel_common=>convert_column2int( lo_curtable->settings-bottom_right_column ) ) + ). + lv_errormessage = 'Table overlaps with previously bound table and will not be added to worksheet.'(400). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ENDWHILE. +*--------------------------------------------------------------------* +* issue #237 Check if overlapping areas exist End +*--------------------------------------------------------------------* + + CREATE OBJECT lo_table. + lo_table->settings = ls_settings. + lo_table->set_data( ir_data = ip_table ). + lv_id = me->excel->get_next_table_id( ). + lo_table->set_id( iv_id = lv_id ). +* lo_table->fieldcat = lt_field_catalog[]. + + me->tables->add( lo_table ). + +* It is better to loop column by column (only visible column) + LOOP AT lt_field_catalog ASSIGNING <ls_field_catalog> WHERE dynpfld EQ abap_true. + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + + " Due restrinction of new table object we cannot have two column with the same name + " Check if a column with the same name exists, if exists add a counter + " If no medium description is provided we try to use small or long +* lv_value = <ls_field_catalog>-scrtext_m. + field-symbols: <scrtxt1> type any, + <scrtxt2> type any, + <scrtxt3> type any. + + case iv_default_descr. + when 'M'. + assign <ls_field_catalog>-scrtext_m to <scrtxt1>. + assign <ls_field_catalog>-scrtext_s to <scrtxt2>. + assign <ls_field_catalog>-scrtext_l to <scrtxt3>. + when 'S'. + assign <ls_field_catalog>-scrtext_s to <scrtxt1>. + assign <ls_field_catalog>-scrtext_m to <scrtxt2>. + assign <ls_field_catalog>-scrtext_l to <scrtxt3>. + when 'L'. + assign <ls_field_catalog>-scrtext_l to <scrtxt1>. + assign <ls_field_catalog>-scrtext_m to <scrtxt2>. + assign <ls_field_catalog>-scrtext_s to <scrtxt3>. + when others. + assign <ls_field_catalog>-scrtext_m to <scrtxt1>. + assign <ls_field_catalog>-scrtext_s to <scrtxt2>. + assign <ls_field_catalog>-scrtext_l to <scrtxt3>. + endcase. + + + if <scrtxt1> is not initial. + lv_value = <scrtxt1>. + <ls_field_catalog>-scrtext_l = lv_value. + elseif <scrtxt2> is not initial. + lv_value = <scrtxt2>. + <ls_field_catalog>-scrtext_l = lv_value. + elseif <scrtxt3> is not initial. + lv_value = <scrtxt3>. + <ls_field_catalog>-scrtext_l = lv_value. + else. + lv_value = 'Column'. " default value as Excel does + <ls_field_catalog>-scrtext_l = lv_value. + endif. + WHILE 1 = 1. + lv_value_lowercase = lv_value. + TRANSLATE lv_value_lowercase TO LOWER CASE. + READ TABLE lt_column_name_buffer TRANSPORTING NO FIELDS WITH KEY table_line = lv_value_lowercase BINARY SEARCH. + IF sy-subrc <> 0. + <ls_field_catalog>-scrtext_l = lv_value. + INSERT lv_value_lowercase INTO TABLE lt_column_name_buffer. + EXIT. + ELSE. + lv_syindex = sy-index. + CONCATENATE <ls_field_catalog>-scrtext_l lv_syindex INTO lv_value. + ENDIF. + + ENDWHILE. + " First of all write column header + IF <ls_field_catalog>-style_header IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_value + ip_style = <ls_field_catalog>-style_header ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_value ). + ENDIF. + + ADD 1 TO lv_row_int. + LOOP AT ip_table ASSIGNING <fs_table_line>. + + ASSIGN COMPONENT <ls_field_catalog>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. + " issue #290 Add formula support in table + IF <ls_field_catalog>-formula EQ abap_true. + IF <ls_field_catalog>-style IS NOT INITIAL. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> + ip_abap_type = <ls_field_catalog>-abap_type + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ENDIF. + ELSE. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + + ip_formula = <fs_fldval> + ip_abap_type = <ls_field_catalog>-abap_type ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = <fs_fldval> ). + ENDIF. + ENDIF. + ELSE. + IF <ls_field_catalog>-style IS NOT INITIAL. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> + ip_abap_type = <ls_field_catalog>-abap_type + ip_style = <ls_field_catalog>-style ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> + ip_style = <ls_field_catalog>-style ). + ENDIF. + ELSE. + IF <ls_field_catalog>-abap_type IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_abap_type = <ls_field_catalog>-abap_type + ip_value = <fs_fldval> ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> ). + ENDIF. + ENDIF. + ENDIF. + ADD 1 TO lv_row_int. + + ENDLOOP. + IF sy-subrc <> 0. "create empty row if table has no data + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = space ). + ADD 1 TO lv_row_int. + ENDIF. + +*--------------------------------------------------------------------* + " totals +*--------------------------------------------------------------------* + IF <ls_field_catalog>-totals_function IS NOT INITIAL. + lv_formula = lo_table->get_totals_formula( ip_column = <ls_field_catalog>-scrtext_l ip_function = <ls_field_catalog>-totals_function ). + IF <ls_field_catalog>-style_total IS NOT INITIAL. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = lv_formula + ip_style = <ls_field_catalog>-style_total ). + ELSE. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_formula = lv_formula ). + ENDIF. + ENDIF. + + lv_row_int = ls_settings-top_left_row. + ADD 1 TO lv_column_int. + +*--------------------------------------------------------------------* + " conditional formatting +*--------------------------------------------------------------------* + IF <ls_field_catalog>-cond_style IS NOT INITIAL. + lv_first_row = ls_settings-top_left_row + 1. " +1 to exclude header + lv_last_row = ls_settings-top_left_row + lv_rows. + <ls_field_catalog>-cond_style->set_range( ip_start_column = lv_column_alpha + ip_start_row = lv_first_row + ip_stop_column = lv_column_alpha + ip_stop_row = lv_last_row ). + ENDIF. + + ENDLOOP. + +*--------------------------------------------------------------------* + " Set field catalog +*--------------------------------------------------------------------* + lo_table->fieldcat = lt_field_catalog[]. + + es_table_settings = ls_settings. + es_table_settings-bottom_right_column = lv_column_alpha. + " >> Issue #291 + IF ip_table IS INITIAL. + es_table_settings-bottom_right_row = ls_settings-top_left_row + 2. "Last rows + ELSE. + es_table_settings-bottom_right_row = ls_settings-top_left_row + lv_rows + 1. "Last rows + ENDIF. + " << Issue #291 + + endmethod. + + + + + + + *--------------------------------------------------------------------* +* issue #293 - Roberto Bianco +* - Christian Assig 2014-03-14 +* +* changes: - Calculate widths using SAPscript font metrics +* (transaction SE73) +* - Calculate the width of dates +* - Add additional width for auto filter buttons +* - Add cell padding to simulate Excel behavior +*--------------------------------------------------------------------* +METHOD calculate_cell_width. + + CONSTANTS: + lc_default_font_name TYPE zexcel_style_font_name VALUE 'Calibri', "#EC NOTEXT + lc_default_font_height TYPE tdfontsize VALUE '110', + lc_excel_cell_padding TYPE float VALUE '0.75'. + + DATA: ld_cell_value TYPE zexcel_cell_value, + ld_current_character TYPE c LENGTH 1, + ld_style_guid TYPE zexcel_cell_style, + ls_stylemapping TYPE zexcel_s_stylemapping, + lo_table_object TYPE REF TO object, + lo_table TYPE REF TO zcl_excel_table, + ld_table_top_left_column TYPE zexcel_cell_column, + ld_table_bottom_right_column TYPE zexcel_cell_column, + ld_flag_contains_auto_filter TYPE abap_bool VALUE abap_false, + ld_flag_bold TYPE abap_bool VALUE abap_false, + ld_flag_italic TYPE abap_bool VALUE abap_false, + ld_date TYPE d, + ld_date_char TYPE c LENGTH 50, + ld_font_height TYPE tdfontsize VALUE lc_default_font_height, + lt_itcfc TYPE STANDARD TABLE OF itcfc, + ld_offset TYPE i, + ld_length TYPE i, + ld_uccp TYPE i, + ls_font_metric TYPE mty_s_font_metric, + ld_width_from_font_metrics TYPE i, + ld_font_family TYPE itcfh-tdfamily, + ld_font_name TYPE zexcel_style_font_name VALUE lc_default_font_name, + lt_font_families LIKE STANDARD TABLE OF ld_font_family, + ls_font_cache TYPE mty_s_font_cache. + + FIELD-SYMBOLS: <ls_font_cache> TYPE mty_s_font_cache, + <ls_font_metric> TYPE mty_s_font_metric, + <ls_itcfc> TYPE itcfc. + + " Determine cell content and cell style + me->get_cell( EXPORTING ip_column = ip_column + ip_row = ip_row + IMPORTING ep_value = ld_cell_value + ep_guid = ld_style_guid ). + + " ABAP2XLSX uses tables to define areas containing headers and + " auto-filters. Find out if the current cell is in the header + " of one of these tables. + LOOP AT me->tables->collection INTO lo_table_object. + " Downcast: OBJECT -> ZCL_EXCEL_TABLE + lo_table ?= lo_table_object. + + " Convert column letters to corresponding integer values + ld_table_top_left_column = + zcl_excel_common=>convert_column2int( + lo_table->settings-top_left_column ). + + ld_table_bottom_right_column = + zcl_excel_common=>convert_column2int( + lo_table->settings-bottom_right_column ). + + " Is the current cell part of the table header? + IF ip_column BETWEEN ld_table_top_left_column AND + ld_table_bottom_right_column AND + ip_row EQ lo_table->settings-top_left_row. + " Current cell is part of the table header + " -> Assume that an auto filter is present and that the font is + " bold + ld_flag_contains_auto_filter = abap_true. + ld_flag_bold = abap_true. + ENDIF. + ENDLOOP. + + " If a style GUID is present, read style attributes + IF ld_style_guid IS NOT INITIAL. + TRY. + " Read style attributes + ls_stylemapping = me->excel->get_style_to_guid( ld_style_guid ). + + " If the current cell contains the default date format, + " convert the cell value to a date and calculate its length + IF ls_stylemapping-complete_style-number_format-format_code = + zcl_excel_style_number_format=>c_format_date_std. + + " Convert excel date to ABAP date + ld_date = + zcl_excel_common=>excel_string_to_date( ld_cell_value ). + + " Format ABAP date using user's formatting settings + WRITE ld_date TO ld_date_char. + + " Remember the formatted date to calculate the cell size + ld_cell_value = ld_date_char. + + ENDIF. + + " Read the font size and convert it to the font height + " used by SAPscript (multiplication by 10) + IF ls_stylemapping-complete_stylex-font-size = abap_true. + ld_font_height = ls_stylemapping-complete_style-font-size * 10. + ENDIF. + + " If set, remember the font name + IF ls_stylemapping-complete_stylex-font-name = abap_true. + ld_font_name = ls_stylemapping-complete_style-font-name. + ENDIF. + + " If set, remember whether font is bold and italic. + IF ls_stylemapping-complete_stylex-font-bold = abap_true. + ld_flag_bold = ls_stylemapping-complete_style-font-bold. + ENDIF. + + IF ls_stylemapping-complete_stylex-font-italic = abap_true. + ld_flag_italic = ls_stylemapping-complete_style-font-italic. + ENDIF. + + CATCH zcx_excel. "#EC NO_HANDLER + " Style GUID is present, but style was not found + " Continue with default values + + ENDTRY. + ENDIF. + + " Check if the same font (font name and font attributes) was already + " used before + READ TABLE mth_font_cache + WITH TABLE KEY + font_name = ld_font_name + font_height = ld_font_height + flag_bold = ld_flag_bold + flag_italic = ld_flag_italic + ASSIGNING <ls_font_cache>. + + IF sy-subrc <> 0. + " Font is used for the first time + " Add the font to our local font cache + ls_font_cache-font_name = ld_font_name. + ls_font_cache-font_height = ld_font_height. + ls_font_cache-flag_bold = ld_flag_bold. + ls_font_cache-flag_italic = ld_flag_italic. + INSERT ls_font_cache INTO TABLE mth_font_cache + ASSIGNING <ls_font_cache>. + + " Determine the SAPscript font family name from the Excel + " font name + SELECT tdfamily + FROM tfo01 + INTO TABLE lt_font_families + UP TO 1 ROWS + WHERE tdtext = ld_font_name + ORDER BY PRIMARY KEY. + + " Check if a matching font family was found + " Fonts can be uploaded from TTF files using transaction SE73 + IF lines( lt_font_families ) > 0. + READ TABLE lt_font_families INDEX 1 INTO ld_font_family. + + " Load font metrics (returns a table with the size of each letter + " in the font) + CALL FUNCTION 'LOAD_FONT' + EXPORTING + family = ld_font_family + height = ld_font_height + printer = 'SWIN' + bold = ld_flag_bold + italic = ld_flag_italic + TABLES + metric = lt_itcfc + EXCEPTIONS + font_family = 1 + codepage = 2 + device_type = 3 + OTHERS = 4. + IF sy-subrc <> 0. + CLEAR lt_itcfc. + ENDIF. + + " For faster access, convert each character number to the actual + " character, and store the characters and their sizes in a hash + " table + LOOP AT lt_itcfc ASSIGNING <ls_itcfc>. + ld_uccp = <ls_itcfc>-cpcharno. + ls_font_metric-char = + cl_abap_conv_in_ce=>uccpi( ld_uccp ). + ls_font_metric-char_width = <ls_itcfc>-tdcwidths. + INSERT ls_font_metric + INTO TABLE <ls_font_cache>-th_font_metrics. + ENDLOOP. + + ENDIF. + ENDIF. + + " Calculate the cell width + " If available, use font metrics + IF lines( <ls_font_cache>-th_font_metrics ) = 0. + " Font metrics are not available + " -> Calculate the cell width using only the font size + ld_length = strlen( ld_cell_value ). + ep_width = ld_length * ld_font_height / lc_default_font_height + lc_excel_cell_padding. + + ELSE. + " Font metrics are available + + " Calculate the size of the text by adding the sizes of each + " letter + ld_length = strlen( ld_cell_value ). + DO ld_length TIMES. + " Subtract 1, because the first character is at offset 0 + ld_offset = sy-index - 1. + + " Read the current character from the cell value + ld_current_character = ld_cell_value+ld_offset(1). + + " Look up the size of the current letter + READ TABLE <ls_font_cache>-th_font_metrics + WITH TABLE KEY char = ld_current_character + ASSIGNING <ls_font_metric>. + IF sy-subrc = 0. + " The size of the letter is known + " -> Add the actual size of the letter + ADD <ls_font_metric>-char_width TO ld_width_from_font_metrics. + ELSE. + " The size of the letter is unknown + " -> Add the font height as the default letter size + ADD ld_font_height TO ld_width_from_font_metrics. + ENDIF. + ENDDO. + + " Add cell padding (Excel makes columns a bit wider than the space + " that is needed for the text itself) and convert unit + " (division by 100) + ep_width = ld_width_from_font_metrics / 100 + lc_excel_cell_padding. + ENDIF. + + " If the current cell contains an auto filter, make it a bit wider. + " The size used by the auto filter button does not depend on the font + " size. + IF ld_flag_contains_auto_filter = abap_true. + ADD 2 TO ep_width. + ENDIF. + +ENDMETHOD. + + + + method CALCULATE_COLUMN_WIDTHS. + TYPES: + BEGIN OF t_auto_size, + col_index TYPE int4, + width TYPE float, + END OF t_auto_size. + TYPES: tt_auto_size TYPE TABLE OF t_auto_size. + + DATA: column_dimensions TYPE zexcel_t_worksheet_columndime. + DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + DATA: auto_size TYPE flag. + DATA: auto_sizes TYPE tt_auto_size. +* DATA: col_alpha TYPE zexcel_cell_column_alpha." issue #155 - less restrictive typing for ip_column + DATA: cell_value TYPE zexcel_cell_value. + DATA: cell_style TYPE REF TO zcl_excel_style. + DATA: count TYPE int4. + DATA: highest_row TYPE int4. + DATA: width TYPE float. + + FIELD-SYMBOLS: <column_dimension> LIKE LINE OF column_dimensions. + FIELD-SYMBOLS: <auto_size> LIKE LINE OF auto_sizes. + + column_dimensions[] = me->get_column_dimensions( ). + LOOP AT column_dimensions ASSIGNING <column_dimension>. + auto_size = <column_dimension>-column_dimension->get_auto_size( ). + IF auto_size = abap_true. + APPEND INITIAL LINE TO auto_sizes ASSIGNING <auto_size>. + <auto_size>-col_index = <column_dimension>-column_dimension->get_column_index( ). + <auto_size>-width = -1. + ENDIF. + ENDLOOP. + + " There is only something to do if there are some auto-size columns + IF NOT auto_sizes IS INITIAL. + highest_row = me->get_highest_row( ). + LOOP AT auto_sizes ASSIGNING <auto_size>. +* col_alpha = zcl_excel_common=>convert_column2alpha( <auto_size>-col_index )." issue #155 - less restrictive typing for ip_column + count = 1. + WHILE count <= highest_row. +* Do not check merged cells + IF is_cell_merged( + ip_column = <auto_size>-col_index + ip_row = count ) = abap_false. +* Start of change # issue 139 - Dateretention of cellstyles +* IF cell_style IS BOUND. +* CREATE OBJECT cell_style. +* ENDIF. +* me->get_cell( +* EXPORTING +* ip_column = col_alpha " Cell Column +* ip_row = count " Cell Row +* IMPORTING +* ep_value = cell_value " Cell Value +* ep_style = cell_style " Request Cell Style as well +* ). +* " For an easy start we just take the number of characters as the width +* width = strlen( cell_value ). +* " Addition to solve issue #120, contribution by Stefan Schmöcker +* " Calculate width using Font Size and Font Type +* IF cell_style IS BOUND +* AND cell_style->font IS BOUND. +* width = cell_style->font->calculate_text_width( cell_value ). +* ENDIF. +* width = calculate_cell_width( ip_column = col_alpha " issue #155 - less restrictive typing for ip_column + width = calculate_cell_width( ip_column = <auto_size>-col_index " issue #155 - less restrictive typing for ip_column + ip_row = count ). +* End of change # issue 139 - Dateretention of cellstyles + IF width > <auto_size>-width. + <auto_size>-width = width. + ENDIF. + ENDIF. + count = count + 1. + ENDWHILE. +* column_dimension = me->get_column_dimension( col_alpha ). " issue #155 - less restrictive typing for ip_column + column_dimension = me->get_column_dimension( <auto_size>-col_index ). " issue #155 - less restrictive typing for ip_column + column_dimension->set_width( <auto_size>-width ). + ENDLOOP. + ENDIF. + + endmethod. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + METHOD change_cell_style. + " issue # 139 + DATA: stylemapping TYPE zexcel_s_stylemapping, + + complete_style TYPE zexcel_s_cstyle_complete, + complete_stylex TYPE zexcel_s_cstylex_complete, + + borderx TYPE zexcel_s_cstylex_border, + l_guid TYPE zexcel_cell_style. "issue # 177 + +* We have a lot of parameters. Use some macros to make the coding more structured + + DEFINE clear_initial_colorxfields. + if &1-rgb is initial. + clear &2-rgb. + endif. + if &1-indexed is initial. + clear &2-indexed. + endif. + if &1-theme is initial. + clear &2-theme. + endif. + if &1-tint is initial. + clear &2-tint. + endif. + END-OF-DEFINITION. + + DEFINE move_supplied_borders. + if ip_&1 is supplied. " only act if parameter was supplied + if ip_x&1 is supplied. " + borderx = ip_x&1. " use supplied x-parameter + else. + clear borderx with 'X'. +* clear in a way that would be expected to work easily + if ip_&1-border_style is initial. + clear borderx-border_style. + endif. + clear_initial_colorxfields ip_&1-border_color borderx-border_color. + endif. + move-corresponding ip_&1 to complete_style-&2. + move-corresponding borderx to complete_stylex-&2. + endif. + END-OF-DEFINITION. + +* First get current stylsettings + TRY. + me->get_cell( EXPORTING ip_column = ip_column " Cell Column + ip_row = ip_row " Cell Row + IMPORTING ep_guid = l_guid )." Cell Value ). "issue # 177 + + + stylemapping = me->excel->get_style_to_guid( l_guid ). "issue # 177 + complete_style = stylemapping-complete_style. + complete_stylex = stylemapping-complete_stylex. + CATCH zcx_excel. +* Error --> use submitted style + ENDTRY. + +* move_supplied_multistyles: complete. + IF ip_complete IS SUPPLIED. + IF ip_xcomplete IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Complete styleinfo has to be supplied with corresponding X-field'. + ENDIF. + MOVE-CORRESPONDING ip_complete TO complete_style. + MOVE-CORRESPONDING ip_xcomplete TO complete_stylex. + ENDIF. + + + + IF ip_font IS SUPPLIED. + DATA: fontx LIKE ip_xfont. + IF ip_xfont IS SUPPLIED. + fontx = ip_xfont. + ELSE. +* Only supplied values should be used - exception: Flags bold and italic strikethrough underline + MOVE 'X' TO: fontx-bold, + fontx-italic, + fontx-strikethrough, + fontx-underline_mode. + CLEAR fontx-color WITH 'X'. + clear_initial_colorxfields ip_font-color fontx-color. + IF ip_font-family IS NOT INITIAL. + fontx-family = 'X'. + ENDIF. + IF ip_font-name IS NOT INITIAL. + fontx-name = 'X'. + ENDIF. + IF ip_font-scheme IS NOT INITIAL. + fontx-scheme = 'X'. + ENDIF. + IF ip_font-size IS NOT INITIAL. + fontx-size = 'X'. + ENDIF. + IF ip_font-underline_mode IS NOT INITIAL. + fontx-underline_mode = 'X'. + ENDIF. + ENDIF. + MOVE-CORRESPONDING ip_font TO complete_style-font. + MOVE-CORRESPONDING fontx TO complete_stylex-font. +* Correction for undeline mode + ENDIF. + + IF ip_fill IS SUPPLIED. + DATA: fillx LIKE ip_xfill. + IF ip_xfill IS SUPPLIED. + fillx = ip_xfill. + ELSE. + CLEAR fillx WITH 'X'. + IF ip_fill-filltype IS INITIAL. + CLEAR fillx-filltype. + ENDIF. + clear_initial_colorxfields ip_fill-fgcolor fillx-fgcolor. + clear_initial_colorxfields ip_fill-bgcolor fillx-bgcolor. + + ENDIF. + MOVE-CORRESPONDING ip_fill TO complete_style-fill. + MOVE-CORRESPONDING fillx TO complete_stylex-fill. + ENDIF. + + + IF ip_borders IS SUPPLIED. + DATA: bordersx LIKE ip_xborders. + IF ip_xborders IS SUPPLIED. + bordersx = ip_xborders. + ELSE. + CLEAR bordersx WITH 'X'. + IF ip_borders-allborders-border_style IS INITIAL. + CLEAR bordersx-allborders-border_style. + ENDIF. + IF ip_borders-diagonal-border_style IS INITIAL. + CLEAR bordersx-diagonal-border_style. + ENDIF. + IF ip_borders-down-border_style IS INITIAL. + CLEAR bordersx-down-border_style. + ENDIF. + IF ip_borders-left-border_style IS INITIAL. + CLEAR bordersx-left-border_style. + ENDIF. + IF ip_borders-right-border_style IS INITIAL. + CLEAR bordersx-right-border_style. + ENDIF. + IF ip_borders-top-border_style IS INITIAL. + CLEAR bordersx-top-border_style. + ENDIF. + clear_initial_colorxfields ip_borders-allborders-border_color bordersx-allborders-border_color. + clear_initial_colorxfields ip_borders-diagonal-border_color bordersx-diagonal-border_color. + clear_initial_colorxfields ip_borders-down-border_color bordersx-down-border_color. + clear_initial_colorxfields ip_borders-left-border_color bordersx-left-border_color. + clear_initial_colorxfields ip_borders-right-border_color bordersx-right-border_color. + clear_initial_colorxfields ip_borders-top-border_color bordersx-top-border_color. + + ENDIF. + MOVE-CORRESPONDING ip_borders TO complete_style-borders. + MOVE-CORRESPONDING bordersx TO complete_stylex-borders. + ENDIF. + + IF ip_alignment IS SUPPLIED. + DATA: alignmentx LIKE ip_xalignment. + IF ip_xalignment IS SUPPLIED. + alignmentx = ip_xalignment. + ELSE. + CLEAR alignmentx WITH 'X'. + IF ip_alignment-horizontal IS INITIAL. + CLEAR alignmentx-horizontal. + ENDIF. + IF ip_alignment-vertical IS INITIAL. + CLEAR alignmentx-vertical. + ENDIF. + ENDIF. + MOVE-CORRESPONDING ip_alignment TO complete_style-alignment. + MOVE-CORRESPONDING alignmentx TO complete_stylex-alignment. + ENDIF. + + IF ip_protection IS SUPPLIED. + MOVE-CORRESPONDING ip_protection TO complete_style-protection. + IF ip_xprotection IS SUPPLIED. + MOVE-CORRESPONDING ip_xprotection TO complete_stylex-protection. + ELSE. + IF ip_protection-hidden IS NOT INITIAL. + complete_stylex-protection-hidden = 'X'. + ENDIF. + IF ip_protection-locked IS NOT INITIAL. + complete_stylex-protection-locked = 'X'. + ENDIF. + ENDIF. + ENDIF. + + + move_supplied_borders : borders_allborders borders-allborders, + borders_diagonal borders-diagonal , + borders_down borders-down , + borders_left borders-left , + borders_right borders-right , + borders_top borders-top . + + DEFINE move_supplied_singlestyles. + if ip_&1 is supplied. + complete_style-&2 = ip_&1. + complete_stylex-&2 = 'X'. + endif. + END-OF-DEFINITION. + + move_supplied_singlestyles: number_format_format_code number_format-format_code, + font_bold font-bold, + font_color font-color, + font_color_rgb font-color-rgb, + font_color_indexed font-color-indexed, + font_color_theme font-color-theme, + font_color_tint font-color-tint, + + font_family font-family, + font_italic font-italic, + font_name font-name, + font_scheme font-scheme, + font_size font-size, + font_strikethrough font-strikethrough, + font_underline font-underline, + font_underline_mode font-underline_mode, + fill_filltype fill-filltype, + fill_rotation fill-rotation, + fill_fgcolor fill-fgcolor, + fill_fgcolor_rgb fill-fgcolor-rgb, + fill_fgcolor_indexed fill-fgcolor-indexed, + fill_fgcolor_theme fill-fgcolor-theme, + fill_fgcolor_tint fill-fgcolor-tint, + + fill_bgcolor fill-bgcolor, + fill_bgcolor_rgb fill-bgcolor-rgb, + fill_bgcolor_indexed fill-bgcolor-indexed, + fill_bgcolor_theme fill-bgcolor-theme, + fill_bgcolor_tint fill-bgcolor-tint, + + fill_gradtype_type fill-gradtype-TYPE, + fill_gradtype_degree fill-gradtype-DEGREE, + fill_gradtype_bottom fill-gradtype-BOTTOM, + fill_gradtype_left fill-gradtype-LEFT, + fill_gradtype_top fill-gradtype-TOP, + fill_gradtype_right fill-gradtype-RIGHT, + fill_gradtype_position1 fill-gradtype-POSITION1, + fill_gradtype_position2 fill-gradtype-POSITION2, + fill_gradtype_position3 fill-gradtype-POSITION3, + + + + borders_diagonal_mode borders-diagonal_mode, + alignment_horizontal alignment-horizontal, + alignment_vertical alignment-vertical, + alignment_textrotation alignment-textrotation, + alignment_wraptext alignment-wraptext, + alignment_shrinktofit alignment-shrinktofit, + alignment_indent alignment-indent, + protection_hidden protection-hidden, + protection_locked protection-locked, + + borders_allborders_style borders-allborders-border_style, + borders_allborders_color borders-allborders-border_color, + borders_allbo_color_rgb borders-allborders-border_color-rgb, + borders_allbo_color_indexed borders-allborders-border_color-indexed, + borders_allbo_color_theme borders-allborders-border_color-theme, + borders_allbo_color_tint borders-allborders-border_color-tint, + + borders_diagonal_style borders-diagonal-border_style, + borders_diagonal_color borders-diagonal-border_color, + borders_diagonal_color_rgb borders-diagonal-border_color-rgb, + borders_diagonal_color_inde borders-diagonal-border_color-indexed, + borders_diagonal_color_them borders-diagonal-border_color-theme, + borders_diagonal_color_tint borders-diagonal-border_color-tint, + + borders_down_style borders-down-border_style, + borders_down_color borders-down-border_color, + borders_down_color_rgb borders-down-border_color-rgb, + borders_down_color_indexed borders-down-border_color-indexed, + borders_down_color_theme borders-down-border_color-theme, + borders_down_color_tint borders-down-border_color-tint, + + borders_left_style borders-left-border_style, + borders_left_color borders-left-border_color, + borders_left_color_rgb borders-left-border_color-rgb, + borders_left_color_indexed borders-left-border_color-indexed, + borders_left_color_theme borders-left-border_color-theme, + borders_left_color_tint borders-left-border_color-tint, + + borders_right_style borders-right-border_style, + borders_right_color borders-right-border_color, + borders_right_color_rgb borders-right-border_color-rgb, + borders_right_color_indexed borders-right-border_color-indexed, + borders_right_color_theme borders-right-border_color-theme, + borders_right_color_tint borders-right-border_color-tint, + + borders_top_style borders-top-border_style, + borders_top_color borders-top-border_color, + borders_top_color_rgb borders-top-border_color-rgb, + borders_top_color_indexed borders-top-border_color-indexed, + borders_top_color_theme borders-top-border_color-theme, + borders_top_color_tint borders-top-border_color-tint. + + +* Now we have a completly filled styles. +* This can be used to get the guid +* Return guid if requested. Might be used if copy&paste of styles is requested + ep_guid = me->excel->get_static_cellstyle_guid( ip_cstyle_complete = complete_style + ip_cstylex_complete = complete_stylex ). + me->set_cell_style( ip_column = ip_column + ip_row = ip_row + ip_style = ep_guid ). + +ENDMETHOD. + + + + + + METHOD constructor. + DATA: lv_title TYPE zexcel_sheet_title. + + me->excel = ip_excel. + +* CALL FUNCTION 'GUID_CREATE' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = me->guid. + me->guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call + + IF ip_title IS NOT INITIAL. + lv_title = ip_title. + ELSE. +* lv_title = me->guid. " del issue #154 - Names of worksheets + lv_title = me->generate_title( ). " ins issue #154 - Names of worksheets + ENDIF. + + me->set_title( ip_title = lv_title ). + + CREATE OBJECT sheet_setup. + CREATE OBJECT conditional_styles. + CREATE OBJECT data_validations. + CREATE OBJECT tables. + CREATE OBJECT ranges. " issue #163 + CREATE OBJECT mo_pagebreaks. + CREATE OBJECT drawings + EXPORTING + ip_type = zcl_excel_drawing=>type_image. + CREATE OBJECT charts + EXPORTING + ip_type = zcl_excel_drawing=>type_chart. + me->zif_excel_sheet_protection~initialize( ). + me->zif_excel_sheet_properties~initialize( ). + CREATE OBJECT hyperlinks. + +* initialize active cell coordinates + active_cell-cell_row = 1. + active_cell-cell_column = 1. + +* inizialize dimension range + lower_cell-cell_row = 1. + lower_cell-cell_column = 1. + upper_cell-cell_row = 1. + upper_cell-cell_column = 1. + +ENDMETHOD. + + + + + METHOD delete_merge. + + FIELD-SYMBOLS: <ls_merged_cell> LIKE LINE OF me->mt_merged_cells. + DATA: is_merged TYPE abap_bool. +*--------------------------------------------------------------------* +* If cell information is passed delete merge including this cell, +* otherwise delete all merges +*--------------------------------------------------------------------* + IF ip_cell_column IS INITIAL + OR ip_cell_row IS INITIAL. + CLEAR me->mt_merged_cells. + ELSE. + LOOP AT me->mt_merged_cells ASSIGNING <ls_merged_cell>. + + is_merged = me->is_cell_merged( ip_column = ip_cell_column + ip_row = ip_cell_row ). + IF is_merged = abap_true. + DELETE me->mt_merged_cells. " Delete this merge, that includes this cell + EXIT. + ENDIF. + + ENDLOOP. + ENDIF. + +ENDMETHOD. + + + + + + METHOD delete_row_outline. + + DELETE me->mt_row_outlines WHERE row_from = iv_row_from + AND row_to = iv_row_to. + IF sy-subrc <> 0. " didn't find outline that was to be deleted + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Row outline to be deleted does not exist'. + ENDIF. + +ENDMETHOD. + + + + + + method FREEZE_PANES. + data: lv_xsplit type i, + lv_ysplit type i. + + IF ip_num_columns IS NOT SUPPLIED AND ip_num_rows IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Pleas provide number of rows and/or columns to freeze'. + ENDIF. + + IF ip_num_columns IS SUPPLIED AND ip_num_columns <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Number of columns to freeze should be positive'. + ENDIF. + + IF ip_num_rows IS SUPPLIED AND ip_num_rows <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Number of rows to freeze should be positive'. + ENDIF. + + freeze_pane_cell_column = ip_num_columns + 1. + freeze_pane_cell_row = ip_num_rows + 1. + endmethod. + + + + method GENERATE_TITLE. + DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + errormessage TYPE string. + + DATA: t_titles TYPE HASHED TABLE OF zexcel_sheet_title WITH UNIQUE KEY table_line, + title TYPE zexcel_sheet_title, + sheetnumber TYPE i. + +* Get list of currently used titles + lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_worksheets_iterator->has_next( ) = abap_true. + lo_worksheet ?= lo_worksheets_iterator->get_next( ). + title = lo_worksheet->get_title( ). + INSERT title INTO TABLE t_titles. + ADD 1 TO sheetnumber. + ENDWHILE. + +* Now build sheetnumber. Increase counter until we hit a number that is not used so far + ADD 1 TO sheetnumber. " Start counting with next number + DO. + title = sheetnumber. + SHIFT title LEFT DELETING LEADING space. + CONCATENATE 'Sheet'(001) title INTO ep_title. + INSERT ep_title INTO TABLE t_titles. + IF sy-subrc = 0. " Title not used so far --> take it + EXIT. + ENDIF. + + ADD 1 TO sheetnumber. + ENDDO. + endmethod. + + + + + method GET_ACTIVE_CELL. + + DATA: lv_active_column TYPE zexcel_cell_column_alpha, + lv_active_row TYPE string. + + lv_active_column = zcl_excel_common=>convert_column2alpha( active_cell-cell_column ). + lv_active_row = active_cell-cell_row. + SHIFT lv_active_row RIGHT DELETING TRAILING space. + SHIFT lv_active_row LEFT DELETING LEADING space. + CONCATENATE lv_active_column lv_active_row INTO ep_active_cell. + + endmethod. + + + + + + + + + + + method GET_CELL. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + READ TABLE sheet_content INTO ls_sheet_content WITH TABLE KEY cell_row = ip_row + cell_column = lv_column. + + ep_rc = sy-subrc. + ep_value = ls_sheet_content-cell_value. + ep_guid = ls_sheet_content-cell_style. " issue 139 - added this to be used for columnwidth calculation + ep_formula = ls_sheet_content-cell_formula. + + " Addition to solve issue #120, contribution by Stefan Schmöcker + DATA: style_iterator TYPE REF TO cl_object_collection_iterator, + style TYPE REF TO zcl_excel_style. + IF ep_style IS REQUESTED. + style_iterator = me->excel->get_styles_iterator( ). + WHILE style_iterator->has_next( ) = 'X'. + style ?= style_iterator->get_next( ). + IF style->get_guid( ) = ls_sheet_content-cell_style. + ep_style = style. + EXIT. + ENDIF. + ENDWHILE. + ENDIF. + endmethod. + + + + + + method GET_COLUMN_DIMENSION. + FIELD-SYMBOLS: <fs_column_dimension> LIKE LINE OF column_dimensions. + DATA: lv_column_alpha TYPE zexcel_cell_column_alpha. " issue #155 - less restrictive typing for ip_column + + lv_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column )." issue #155 - less restrictive typing for ip_column + READ TABLE me->column_dimensions ASSIGNING <fs_column_dimension> + WITH KEY column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column + + IF NOT <fs_column_dimension> IS ASSIGNED. + CREATE OBJECT r_column_dimension + EXPORTING + ip_index = lv_column_alpha " issue #155 - less restrictive typing for ip_column + ip_excel = me->excel " issue #157 - Allow style for columns + ip_worksheet = me. " issue #157 - Allow style for columns + APPEND INITIAL LINE TO me->column_dimensions ASSIGNING <fs_column_dimension>. + <fs_column_dimension>-column = lv_column_alpha. " issue #155 - less restrictive typing for ip_column + <fs_column_dimension>-column_dimension = r_column_dimension. + ELSE. + r_column_dimension = <fs_column_dimension>-column_dimension. + ENDIF. + + endmethod. + + + + method GET_COLUMN_DIMENSIONS. + r_column_dimension[] = me->column_dimensions[]. + endmethod. + + + + method GET_COND_STYLES_ITERATOR. + + eo_iterator = me->conditional_styles->get_iterator( ). + endmethod. + + + + method GET_DATA_VALIDATIONS_ITERATOR. + + eo_iterator = me->data_validations->get_iterator( ). + endmethod. + + + + method GET_DATA_VALIDATIONS_SIZE. + ep_size = me->data_validations->size( ). + endmethod. + + + + method GET_DEFAULT_COLUMN_DIMENSION. + IF me->default_column_dimension IS NOT BOUND. + CREATE OBJECT me->default_column_dimension + EXPORTING + ip_index = 'A' " ???? + ip_worksheet = me + ip_excel = me->excel. + ENDIF. + + r_column_dimension = me->default_column_dimension. + endmethod. + + + + method GET_DEFAULT_EXCEL_DATE_FORMAT. + CONSTANTS: c_lang_e TYPE lang VALUE 'E'. + + IF default_excel_date_format IS NOT INITIAL. + ep_default_excel_date_format = default_excel_date_format. + RETURN. + ENDIF. + + "try to get defaults + TRY. + cl_abap_datfm=>get_date_format_des( EXPORTING im_langu = c_lang_e + IMPORTING ex_dateformat = default_excel_date_format ). + CATCH cx_abap_datfm_format_unknown. + + ENDTRY. + + " and fallback to fixed format + IF default_excel_date_format IS INITIAL. + default_excel_date_format = zcl_excel_style_number_format=>c_format_date_ddmmyyyydot. + ENDIF. + + ep_default_excel_date_format = default_excel_date_format. + endmethod. + + + + method GET_DEFAULT_EXCEL_TIME_FORMAT. + DATA: l_timefm TYPE xutimefm. + + IF default_excel_time_format IS NOT INITIAL. + ep_default_excel_time_format = default_excel_time_format. + RETURN. + ENDIF. + +* Let's get default + l_timefm = cl_abap_timefm=>get_environment_timefm( ). + CASE l_timefm. + WHEN 0. +*0 24 Hour Format (Example: 12:05:10) + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. + WHEN 1. +*1 12 Hour Format (Example: 12:05:10 PM) + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 2. +*2 12 Hour Format (Example: 12:05:10 pm) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 3. +*3 Hours from 0 to 11 (Example: 00:05:10 PM) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN 4. +*4 Hours from 0 to 11 (Example: 00:05:10 pm) for now all the same. no chnage upper lower + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time2. + WHEN OTHERS. + " and fallback to fixed format + default_excel_time_format = zcl_excel_style_number_format=>c_format_date_time6. + ENDCASE. + + ep_default_excel_time_format = default_excel_time_format. + endmethod. + + + + method GET_DEFAULT_ROW_DIMENSION. + IF me->default_row_dimension IS NOT BOUND. + CREATE OBJECT me->default_row_dimension. + ENDIF. + + r_row_dimension = me->default_row_dimension. + endmethod. + + + + + method GET_DIMENSION_RANGE. + + me->update_dimension_range( ). + IF upper_cell EQ lower_cell. "only one cell + " Worksheet not filled +* IF upper_cell-cell_coords = '0'. + IF upper_cell-cell_coords IS INITIAL. + ep_dimension_range = 'A1'. + ELSE. + ep_dimension_range = upper_cell-cell_coords. + ENDIF. + ELSE. + CONCATENATE upper_cell-cell_coords ':' lower_cell-cell_coords INTO ep_dimension_range. + ENDIF. + + endmethod. + + + + + method GET_DRAWINGS. + + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + lo_iterator TYPE REF TO cl_object_collection_iterator. + + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + r_drawings = drawings. + WHEN zcl_excel_drawing=>type_chart. + r_drawings = charts. + WHEN space. + CREATE OBJECT r_drawings + EXPORTING + ip_type = ''. + + lo_iterator = drawings->get_iterator( ). + WHILE lo_iterator->has_next( ) = abap_true. + lo_drawing ?= lo_iterator->get_next( ). + r_drawings->include( lo_drawing ). + ENDWHILE. + lo_iterator = charts->get_iterator( ). + WHILE lo_iterator->has_next( ) = abap_true. + lo_drawing ?= lo_iterator->get_next( ). + r_drawings->include( lo_drawing ). + ENDWHILE. + WHEN OTHERS. + ENDCASE. + endmethod. + + + + + method GET_DRAWINGS_ITERATOR. + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + eo_iterator = drawings->get_iterator( ). + WHEN zcl_excel_drawing=>type_chart. + eo_iterator = charts->get_iterator( ). + ENDCASE. + endmethod. + + + + + method GET_FREEZE_CELL. + ep_row = me->freeze_pane_cell_row. + ep_column = me->freeze_pane_cell_column. + endmethod. + + + + METHOD get_guid. + + ep_guid = me->guid. + +ENDMETHOD. + + + + + method GET_HIGHEST_COLUMN. + me->update_dimension_range( ). + r_highest_column = me->lower_cell-cell_column. + endmethod. + + + + + METHOD get_highest_row. + me->update_dimension_range( ). + r_highest_row = me->lower_cell-cell_row. +ENDMETHOD. + + + + method GET_HYPERLINKS_ITERATOR. + eo_iterator = hyperlinks->get_iterator( ). + endmethod. + + + + method GET_HYPERLINKS_SIZE. + ep_size = hyperlinks->size( ). + endmethod. + + + + + METHOD get_merge. + + FIELD-SYMBOLS: <ls_merged_cell> LIKE LINE OF me->mt_merged_cells. + + DATA: lv_col_from TYPE string, + lv_col_to TYPE string, + lv_row_from TYPE string, + lv_row_to TYPE string, + lv_merge_range TYPE string. + + LOOP AT me->mt_merged_cells ASSIGNING <ls_merged_cell>. + + lv_col_from = zcl_excel_common=>convert_column2alpha( <ls_merged_cell>-col_from ). + lv_col_to = zcl_excel_common=>convert_column2alpha( <ls_merged_cell>-col_to ). + lv_row_from = <ls_merged_cell>-row_from. + lv_row_to = <ls_merged_cell>-row_to . + CONCATENATE lv_col_from lv_row_from ':' lv_col_to lv_row_to + INTO lv_merge_range. + CONDENSE lv_merge_range NO-GAPS. + APPEND lv_merge_range TO merge_range. + + ENDLOOP. + +ENDMETHOD. + + + + + method GET_PAGEBREAKS. + ro_pagebreaks = mo_pagebreaks. +endmethod. + + + + method GET_RANGES_ITERATOR. + + eo_iterator = me->ranges->get_iterator( ). + + endmethod. + + + + + METHOD GET_ROW_DIMENSION. + + FIELD-SYMBOLS: <ls_row_dimension> LIKE LINE OF me->row_dimensions. + + DATA: ls_row_dimension LIKE LINE OF me->row_dimensions. + + READ TABLE me->row_dimensions ASSIGNING <ls_row_dimension> + WITH TABLE KEY row = ip_row. + + IF NOT <ls_row_dimension> IS ASSIGNED. + CREATE OBJECT r_row_dimension + EXPORTING + ip_index = ip_row. + ls_row_dimension-row = ip_row. + ls_row_dimension-row_dimension = r_row_dimension. + INSERT ls_row_dimension INTO TABLE me->row_dimensions. + ELSE. + r_row_dimension = <ls_row_dimension>-row_dimension. + ENDIF. + +ENDMETHOD. + + + + METHOD get_row_dimensions. + + r_row_dimension[] = me->row_dimensions[]. + +ENDMETHOD. + + + + METHOD get_row_outlines. + + rt_row_outlines = me->mt_row_outlines. + +ENDMETHOD. + + + + method GET_TABCOLOR. + ev_tabcolor = me->tabcolor. + endmethod. + + + + method GET_TABLES_ITERATOR. + eo_iterator = tables->if_object_collection~get_iterator( ). + endmethod. + + + + method GET_TABLES_SIZE. + ep_size = tables->if_object_collection~size( ). + endmethod. + + + + + method GET_TITLE. + DATA lv_value TYPE string. + IF ip_escaped EQ abap_true. + lv_value = me->title. + ep_title = zcl_excel_common=>escape_string( lv_value ). + ELSE. + ep_title = me->title. + ENDIF. + endmethod. + + + + + + METHOD get_value_type. + DATA: lo_addit TYPE REF TO cl_abap_elemdescr, + ls_dfies TYPE dfies, + l_function TYPE funcname, + l_value(50) TYPE c. + + ep_value = ip_value. + ep_value_type = cl_abap_typedescr=>typekind_string. " Thats our default if something goes wrong. + + TRY. + lo_addit ?= cl_abap_typedescr=>describe_by_data( ip_value ). + CATCH cx_sy_move_cast_error. + CLEAR lo_addit. + ENDTRY. + IF lo_addit IS BOUND. + lo_addit->get_ddic_field( RECEIVING p_flddescr = ls_dfies + EXCEPTIONS not_found = 1 + no_ddic_type = 2 + OTHERS = 3 ) . + IF sy-subrc = 0. + ep_value_type = ls_dfies-inttype. + + IF ls_dfies-convexit IS NOT INITIAL. +* We need to convert with output conversion function + CONCATENATE 'CONVERSION_EXIT_' ls_dfies-convexit '_OUTPUT' INTO l_function. + SELECT SINGLE funcname INTO l_function + FROM tfdir + WHERE funcname = l_function. + IF sy-subrc = 0. + CALL FUNCTION l_function + EXPORTING + input = ip_value + IMPORTING +* LONG_TEXT = + output = l_value +* SHORT_TEXT = + EXCEPTIONS + OTHERS = 1. + IF sy-subrc <> 0. +* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO +* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4. + ELSE. + TRY. + ep_value = l_value. + CATCH cx_root. + ep_value = ip_value. + ENDTRY. + ENDIF. + ENDIF. + ENDIF. + ELSE. + ep_value_type = lo_addit->get_data_type_kind( ip_value ). + ENDIF. + ENDIF. + +ENDMETHOD. + + + + + + + METHOD is_cell_merged. + + DATA: lv_column TYPE i. + + FIELD-SYMBOLS: <ls_merged_cell> LIKE LINE OF me->mt_merged_cells. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + rp_is_merged = abap_false. " Assume not in merged area + + LOOP AT me->mt_merged_cells ASSIGNING <ls_merged_cell>. + + IF <ls_merged_cell>-col_from <= lv_column + AND <ls_merged_cell>-col_to >= lv_column + AND <ls_merged_cell>-row_from <= ip_row + AND <ls_merged_cell>-row_to >= ip_row. + rp_is_merged = abap_true. " until we are proven different + RETURN. + ENDIF. + + ENDLOOP. + +ENDMETHOD. + + + method PRINT_TITLE_SET_RANGE. +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmoecker, 2012-12-02 +*--------------------------------------------------------------------* + + + DATA: lo_range_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range, + lv_repeat_range_sheetname TYPE string, + lv_repeat_range_col TYPE string, + lv_row_char_from TYPE char10, + lv_row_char_to TYPE char10, + lv_repeat_range_row TYPE string, + lv_repeat_range TYPE string. + + +*--------------------------------------------------------------------* +* Get range that represents printarea +* if non-existant, create it +*--------------------------------------------------------------------* + lo_range_iterator = me->get_ranges_iterator( ). + WHILE lo_range_iterator->has_next( ) = abap_true. + + lo_range ?= lo_range_iterator->get_next( ). + IF lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. + EXIT. " Found it + ENDIF. + CLEAR lo_range. + + ENDWHILE. + + + IF me->print_title_col_from IS INITIAL AND + me->print_title_row_from IS INITIAL. +*--------------------------------------------------------------------* +* No print titles are present, +*--------------------------------------------------------------------* + IF lo_range IS BOUND. + me->ranges->remove( lo_range ). + ENDIF. + ELSE. +*--------------------------------------------------------------------* +* Print titles are present, +*--------------------------------------------------------------------* + IF lo_range IS NOT BOUND. + lo_range = me->add_new_range( ). + lo_range->name = zif_excel_sheet_printsettings=>gcv_print_title_name. + ENDIF. + + lv_repeat_range_sheetname = me->get_title( ). + lv_repeat_range_sheetname = zcl_excel_common=>escape_string( lv_repeat_range_sheetname ). + +*--------------------------------------------------------------------* +* Repeat-columns +*--------------------------------------------------------------------* + IF me->print_title_col_from IS NOT INITIAL. + CONCATENATE lv_repeat_range_sheetname + '!$' me->print_title_col_from + ':$' me->print_title_col_to + INTO lv_repeat_range_col. + ENDIF. + +*--------------------------------------------------------------------* +* Repeat-rows +*--------------------------------------------------------------------* + IF me->print_title_row_from IS NOT INITIAL. + lv_row_char_from = me->print_title_row_from. + lv_row_char_to = me->print_title_row_to. + CONCATENATE '!$' lv_row_char_from + ':$' lv_row_char_to + INTO lv_repeat_range_row. + CONDENSE lv_repeat_range_row NO-GAPS. + CONCATENATE lv_repeat_range_sheetname + lv_repeat_range_row + INTO lv_repeat_range_row. + ENDIF. + +*--------------------------------------------------------------------* +* Concatenate repeat-rows and columns +*--------------------------------------------------------------------* + IF lv_repeat_range_col IS INITIAL. + lv_repeat_range = lv_repeat_range_row. + ELSEIF lv_repeat_range_row IS INITIAL. + lv_repeat_range = lv_repeat_range_col. + ELSE. + CONCATENATE lv_repeat_range_col lv_repeat_range_row + INTO lv_repeat_range SEPARATED BY ','. + ENDIF. + + + lo_range->set_range_value( lv_repeat_range ). + ENDIF. + + + + endmethod. + + + + + + + + + + + + method SET_CELL. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string, + lv_col_alpha TYPE zexcel_cell_column_alpha, + lv_value TYPE zexcel_cell_value, + lv_data_type TYPE zexcel_cell_data_type, + lv_value_type TYPE abap_typekind, + lo_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style, + lo_addit TYPE REF TO cl_abap_elemdescr, + lo_value TYPE REF TO data, + lo_value_new TYPE REF TO data. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data, + <fs_numeric> TYPE numeric, + <fs_date> TYPE d, + <fs_time> TYPE t, + <fs_value> TYPE simple. + + IF ip_value IS NOT SUPPLIED AND ip_formula IS NOT SUPPLIED. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please provide the value or formula'. + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* lv_style_guid = ip_style. + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH TABLE KEY cell_row = ip_row " Changed to access via table key , Stefan Schmöcker, 2013-08-03 + cell_column = lv_column. + IF sy-subrc = 0. + IF ip_style IS INITIAL. + " If no style is provided as method-parameter and cell is found use cell's current style + lv_style_guid = <fs_sheet_content>-cell_style. + ELSE. + " Style provided as method-parameter --> use this + lv_style_guid = ip_style. + ENDIF. + ELSE. + " No cell found --> use supplied style even if empty + lv_style_guid = ip_style. + ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + IF ip_value IS SUPPLIED. + "if data type is passed just write the value. Otherwise map abap type to excel and perform conversion + "IP_DATA_TYPE is passed by excel reader so source types are preserved +*First we get reference into local var. + CREATE DATA lo_value LIKE ip_value. + ASSIGN lo_value->* TO <fs_value>. + <fs_value> = ip_value. + IF ip_data_type IS SUPPLIED. + IF ip_abap_type IS NOT SUPPLIED. + get_value_type( EXPORTING ip_value = ip_value + IMPORTING ep_value = <fs_value> ) . + ENDIF. + lv_value = <fs_value>. + lv_data_type = ip_data_type. + ELSE. + IF ip_abap_type IS SUPPLIED. + lv_value_type = ip_abap_type. + ELSE. + get_value_type( EXPORTING ip_value = ip_value + IMPORTING ep_value = <fs_value> + ep_value_type = lv_value_type ). + ENDIF. + CASE lv_value_type. + WHEN cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR cl_abap_typedescr=>typekind_int2. + lo_addit = cl_abap_elemdescr=>get_i( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_numeric>. + IF sy-subrc = 0. + <fs_numeric> = <fs_value>. + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). + ENDIF. + + WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_packed. + lo_addit = cl_abap_elemdescr=>get_f( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_numeric>. + IF sy-subrc = 0. + <fs_numeric> = <fs_value>. + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = <fs_numeric> ). + ENDIF. + + WHEN cl_abap_typedescr=>typekind_char OR cl_abap_typedescr=>typekind_string OR cl_abap_typedescr=>typekind_num OR + cl_abap_typedescr=>typekind_hex. + lv_value = <fs_value>. + lv_data_type = 's'. + + WHEN cl_abap_typedescr=>typekind_date. + lo_addit = cl_abap_elemdescr=>get_d( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_date>. + IF sy-subrc = 0. + <fs_date> = <fs_value>. + lv_value = zcl_excel_common=>date_to_excel_string( ip_value = <fs_date> ) . + ENDIF. +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Moved to end of routine - apply date-format even if other styleinformation is passed +* IF ip_style IS NOT SUPPLIED. "get default date format in case parameter is initial +* lo_style = excel->add_new_style( ). +* lo_style->number_format->format_code = get_default_excel_date_format( ). +* lv_style_guid = lo_style->get_guid( ). +* ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + WHEN cl_abap_typedescr=>typekind_time. + lo_addit = cl_abap_elemdescr=>get_t( ). + CREATE DATA lo_value_new TYPE HANDLE lo_addit. + ASSIGN lo_value_new->* TO <fs_time>. + IF sy-subrc = 0. + <fs_time> = <fs_value>. + lv_value = zcl_excel_common=>time_to_excel_string( ip_value = <fs_time> ). + ENDIF. +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Moved to end of routine - apply time-format even if other styleinformation is passed +* IF ip_style IS NOT SUPPLIED. "get default time format for user in case parameter is initial +* lo_style = excel->add_new_style( ). +* lo_style->number_format->format_code = zcl_excel_style_number_format=>c_format_date_time6. +* lv_style_guid = lo_style->get_guid( ). +* ENDIF. +* End of change issue #152 - don't touch exisiting style if only value is passed + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Invalid data type of input value'. + ENDCASE. + ENDIF. + + ENDIF. + + IF ip_hyperlink IS BOUND. + ip_hyperlink->set_cell_reference( ip_column = ip_column + ip_row = ip_row ). + me->hyperlinks->add( ip_hyperlink ). + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* Read table moved up, so that current style may be evaluated +* lv_column = zcl_excel_common=>convert_column2int( ip_column ). + +* READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row +* cell_column = lv_column. +* +* IF sy-subrc EQ 0. + IF <fs_sheet_content> IS ASSIGNED. +* End of change issue #152 - don't touch exisiting style if only value is passed + <fs_sheet_content>-cell_value = lv_value. + <fs_sheet_content>-cell_formula = ip_formula. + <fs_sheet_content>-cell_style = lv_style_guid. + <fs_sheet_content>-data_type = lv_data_type. + ELSE. + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column. + ls_sheet_content-cell_value = lv_value. + ls_sheet_content-cell_formula = ip_formula. + ls_sheet_content-cell_style = lv_style_guid. + ls_sheet_content-data_type = lv_data_type. + lv_row_alpha = ip_row. +* SHIFT lv_row_alpha RIGHT DELETING TRAILING space."del #152 - replaced with condense - should be faster +* SHIFT lv_row_alpha LEFT DELETING LEADING space. "del #152 - replaced with condense - should be faster + CONDENSE lv_row_alpha NO-GAPS. "ins #152 - replaced 2 shifts - should be faster + lv_col_alpha = zcl_excel_common=>convert_column2alpha( ip_column ). " issue #155 - less restrictive typing for ip_column + CONCATENATE lv_col_alpha lv_row_alpha INTO ls_sheet_content-cell_coords. " issue #155 - less restrictive typing for ip_column + INSERT ls_sheet_content INTO TABLE sheet_content ASSIGNING <fs_sheet_content>. "ins #152 - Now <fs_sheet_content> always holds the data +* APPEND ls_sheet_content TO sheet_content. +* SORT sheet_content BY cell_row cell_column. + " me->update_dimension_range( ). + + ENDIF. + +* Begin of change issue #152 - don't touch exisiting style if only value is passed +* For Date- or Timefields change the formatcode if nothing is set yet +* Enhancement option: Check if existing formatcode is a date/ or timeformat +* If not, use default + DATA: lo_format_code_datetime TYPE zexcel_number_format. + DATA: stylemapping TYPE zexcel_s_stylemapping. + CASE lv_value_type. + WHEN cl_abap_typedescr=>typekind_date. + TRY. + stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). + CATCH zcx_excel . + ENDTRY. + IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR + stylemapping-complete_style-number_format-format_code IS INITIAL. + lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_std. + ELSE. + lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. + ENDIF. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_number_format_format_code = lo_format_code_datetime ). + + WHEN cl_abap_typedescr=>typekind_time. + TRY. + stylemapping = me->excel->get_style_to_guid( <fs_sheet_content>-cell_style ). + CATCH zcx_excel . + ENDTRY. + IF stylemapping-complete_stylex-number_format-format_code IS INITIAL OR + stylemapping-complete_style-number_format-format_code IS INITIAL. + lo_format_code_datetime = zcl_excel_style_number_format=>c_format_date_time6. + ELSE. + lo_format_code_datetime = stylemapping-complete_style-number_format-format_code. + ENDIF. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_number_format_format_code = lo_format_code_datetime ). + + ENDCASE. +* End of change issue #152 - don't touch exisiting style if only value is passed + +* Fix issue #162 + lv_value = ip_value. + IF lv_value CS cl_abap_char_utilities=>cr_lf. + me->change_cell_style( ip_column = ip_column + ip_row = ip_row + ip_alignment_wraptext = abap_true ). + ENDIF. +* End of Fix issue #162 + + endmethod. + + + + + + + method SET_CELL_FORMULA. + DATA: + lv_column TYPE zexcel_cell_column, + ls_sheet_content LIKE LINE OF me->sheet_content. + + FIELD-SYMBOLS: + <sheet_content> LIKE LINE OF me->sheet_content. + +*--------------------------------------------------------------------* +* Get cell to set formula into +*--------------------------------------------------------------------* + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + READ TABLE me->sheet_content ASSIGNING <sheet_content> WITH TABLE KEY cell_row = ip_row + cell_column = lv_column. + IF sy-subrc <> 0. " Create new entry in sheet_content if necessary + CHECK ip_formula IS INITIAL. " no need to create new entry in sheet_content when no formula is passed + ls_sheet_content-cell_row = ip_row. + ls_sheet_content-cell_column = lv_column. + INSERT ls_sheet_content INTO TABLE me->sheet_content ASSIGNING <sheet_content>. + ENDIF. + +*--------------------------------------------------------------------* +* Fieldsymbol now holds the relevant cell +*--------------------------------------------------------------------* + <sheet_content>-cell_formula = ip_formula. + + + endmethod. + + + + + + + method SET_CELL_STYLE. + + DATA: lv_column TYPE zexcel_cell_column, + ls_sheet_content TYPE zexcel_s_cell_data, + lv_row_alpha TYPE string, + lo_style TYPE REF TO zcl_excel_style, + lv_style_guid TYPE zexcel_cell_style. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + + lv_style_guid = ip_style. + + lv_column = zcl_excel_common=>convert_column2int( ip_column ). + + READ TABLE sheet_content ASSIGNING <fs_sheet_content> WITH KEY cell_row = ip_row + cell_column = lv_column. + + IF sy-subrc EQ 0. + <fs_sheet_content>-cell_style = lv_style_guid. + ELSE. + set_cell( ip_column = ip_column ip_row = ip_row ip_value = '' ip_style = ip_style ). + ENDIF. + + endmethod. + + + + + + + method SET_COLUMN_WIDTH. + DATA: column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + DATA: width TYPE float. + + column_dimension = me->get_column_dimension( ip_column ). + +* if a fix size is supplied use this + IF ip_width_fix IS SUPPLIED. + TRY. + width = ip_width_fix. + IF width <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please supply a positive number as column-width'. + ENDIF. + column_dimension->set_width( width ). + EXIT. + CATCH cx_sy_conversion_no_number. +* Strange stuff passed --> raise error + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret supplied input as number'. + ENDTRY. + ENDIF. + +* If we get down to here, we have to use whatever is found in autosize. + column_dimension->set_auto_size( ip_width_autosize ). + + + endmethod. + + + + + method SET_DEFAULT_EXCEL_DATE_FORMAT. + + IF ip_default_excel_date_format IS INITIAL. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Default date format cannot be blank'. + ENDIF. + + default_excel_date_format = ip_default_excel_date_format. + endmethod. + + + + + + + + METHOD set_merge. + + DATA: ls_merge TYPE mty_merge, + lv_errormessage TYPE string. + + FIELD-SYMBOLS: <ls_merge> LIKE LINE OF me->mt_merged_cells. + +*--------------------------------------------------------------------* +* Build new range area to insert into range table +*--------------------------------------------------------------------* + ls_merge-row_from = ip_row. + IF ip_row IS SUPPLIED AND ip_row IS NOT INITIAL AND ip_row_to IS NOT SUPPLIED. + ls_merge-row_to = ls_merge-row_from. + ELSE. + ls_merge-row_to = ip_row_to. + ENDIF. + IF ls_merge-row_from > ls_merge-row_to. + lv_errormessage = 'Merge: First row larger then last row'(405). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + ls_merge-col_from = zcl_excel_common=>convert_column2int( ip_column_start ). + IF ip_column_start IS SUPPLIED AND ip_column_start IS NOT INITIAL AND ip_column_end IS NOT SUPPLIED. + ls_merge-col_to = ls_merge-col_from. + ELSE. + ls_merge-col_to = zcl_excel_common=>convert_column2int( ip_column_end ). + ENDIF. + IF ls_merge-col_from > ls_merge-col_to. + lv_errormessage = 'Merge: First column larger then last column'(406). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + +*--------------------------------------------------------------------* +* Check merge not overlapping with existing merges +*--------------------------------------------------------------------* + LOOP AT me->mt_merged_cells TRANSPORTING NO FIELDS WHERE NOT ( row_from > ls_merge-row_to + OR row_to < ls_merge-row_from + OR col_from > ls_merge-col_to + OR col_to < ls_merge-col_from ). + lv_errormessage = 'Overlapping merges'(404). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + + ENDLOOP. + +*--------------------------------------------------------------------* +* Everything seems ok --> add to merge table +*--------------------------------------------------------------------* + INSERT ls_merge INTO TABLE me->mt_merged_cells. + +ENDMETHOD. + + + + method SET_PRINT_GRIDLINES. + me->print_gridlines = i_print_gridlines. + endmethod. + + + + + + method SET_ROW_HEIGHT. + DATA: row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + DATA: height TYPE float. + + row_dimension = me->get_row_dimension( ip_row ). + +* if a fix size is supplied use this + TRY. + height = ip_height_fix. + IF height <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Please supply a positive number as row-height'. + ENDIF. + row_dimension->set_row_height( height ). + EXIT. + CATCH cx_sy_conversion_no_number. +* Strange stuff passed --> raise error + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret supplied input as number'. + ENDTRY. + + + + endmethod. + + + + + + + METHOD set_row_outline. + + DATA: ls_row_outline LIKE LINE OF me->mt_row_outlines. + FIELD-SYMBOLS: <ls_row_outline> LIKE LINE OF me->mt_row_outlines. + + READ TABLE me->mt_row_outlines ASSIGNING <ls_row_outline> WITH TABLE KEY row_from = iv_row_from + row_to = iv_row_to. + IF sy-subrc <> 0. + IF iv_row_from <= 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'First row of outline must be a positive number'. + ENDIF. + IF iv_row_to < iv_row_from. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Last row of outline may not be less than first line of outline'. + ENDIF. + ls_row_outline-row_from = iv_row_from. + ls_row_outline-row_to = iv_row_to. + INSERT ls_row_outline INTO TABLE me->mt_row_outlines ASSIGNING <ls_row_outline>. + ENDIF. + + CASE iv_collapsed. + + WHEN abap_true + OR abap_false. + <ls_row_outline>-collapsed = iv_collapsed. + + WHEN OTHERS. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unknown collapse state'. + + ENDCASE. +ENDMETHOD. + + + + method SET_SHOW_GRIDLINES. + me->show_gridlines = i_show_gridlines. + endmethod. + + + + method SET_SHOW_ROWCOLHEADERS. + me->show_rowcolheaders = i_show_rowcolheaders. + endmethod. + + + + method SET_TABCOLOR. + me->tabcolor = iv_tabcolor. + endmethod. + + + + + + + + + + + + method SET_TABLE. + + DATA: lo_tabdescr TYPE REF TO cl_abap_structdescr, + lr_data TYPE REF TO data, + ls_newline TYPE REF TO data, + ls_header TYPE x030l, + lt_dfies TYPE ddfields, + lv_row_header TYPE zexcel_cell_row VALUE 2, + lv_col_header TYPE zexcel_cell_column_alpha VALUE 'B', + lv_row_int TYPE zexcel_cell_row, + lv_column_int TYPE zexcel_cell_column, + lv_column_alpha TYPE zexcel_cell_column_alpha, + lv_cell_value TYPE zexcel_cell_value. + + + FIELD-SYMBOLS: <fs_table_line> TYPE ANY, + <fs_fldval> TYPE ANY, + <fs_dfies> TYPE dfies, + <fs_cell_value> TYPE zexcel_cell_value. + + lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). + lv_row_int = ip_top_left_row. + + CREATE DATA lr_data LIKE LINE OF ip_table. + + lo_tabdescr ?= cl_abap_structdescr=>describe_by_data_ref( lr_data ). + + ls_header = lo_tabdescr->get_ddic_header( ). + + lt_dfies = lo_tabdescr->get_ddic_field_list( ). + +* It is better to loop column by column + LOOP AT lt_dfies ASSIGNING <fs_dfies>. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + + IF ip_no_header = abap_false. + " First of all write column header + lv_cell_value = <fs_dfies>-scrtext_m. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = lv_cell_value + ip_style = ip_hdr_style ). + IF ip_transpose = abap_true. + ADD 1 TO lv_column_int. + ELSE. + ADD 1 TO lv_row_int. + ENDIF. + ENDIF. + + LOOP AT ip_table ASSIGNING <fs_table_line>. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lv_column_int ). + ASSIGN COMPONENT <fs_dfies>-fieldname OF STRUCTURE <fs_table_line> TO <fs_fldval>. + MOVE <fs_fldval> TO lv_cell_value. + me->set_cell( ip_column = lv_column_alpha + ip_row = lv_row_int + ip_value = <fs_fldval> "lv_cell_value + ip_style = ip_body_style ). + IF ip_transpose = abap_true. + ADD 1 TO lv_column_int. + ELSE. + ADD 1 TO lv_row_int. + ENDIF. + ENDLOOP. + IF ip_transpose = abap_true. + lv_column_int = zcl_excel_common=>convert_column2int( ip_top_left_column ). + ADD 1 TO lv_row_int. + ELSE. + lv_row_int = ip_top_left_row. + ADD 1 TO lv_column_int. + ENDIF. + ENDLOOP. + + endmethod. + + + + + method SET_TITLE. +*--------------------------------------------------------------------* +* ToDos: +* 2do §1 The current coding for replacing a named ranges name +* after renaming a sheet should be checked if it is +* really working if sheetname should be escaped +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (wip ) 2012-12-08 +* - ... +* changes: aligning code +* message made to support multilinguality +*--------------------------------------------------------------------* +* issue#243 - ' is not allowed as first character in sheet title +* - Stefan Schmoecker, 2012-12-02 +* changes: added additional check for ' as first character +*--------------------------------------------------------------------* + DATA: lo_worksheets_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + errormessage TYPE string, + lv_rangesheetname_old TYPE string, + lv_rangesheetname_new TYPE string, + lo_ranges_iterator TYPE REF TO cl_object_collection_iterator, + lo_range TYPE REF TO zcl_excel_range, + lv_range_value TYPE zexcel_range_value, + lv_errormessage TYPE string. " Can't pass '...'(abc) to exception-class + + +*--------------------------------------------------------------------* +* Check whether title consists only of allowed characters +* Illegal characters are: / \ [ ] * ? : --> http://msdn.microsoft.com/en-us/library/ff837411.aspx +* Illegal characters not in documentation: ' as first character +*--------------------------------------------------------------------* + IF ip_title CA '/\[]*?:'. + lv_errormessage = 'Found illegal character in sheetname. List of forbidden characters: /\[]*?:'(402). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + IF ip_title IS NOT INITIAL AND ip_title(1) = `'`. + lv_errormessage = 'Sheetname may not start with &'(403). " & used instead of ' to allow fallbacklanguage + REPLACE '&' IN lv_errormessage WITH `'`. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + +*--------------------------------------------------------------------* +* Check whether title is unique in workbook +*--------------------------------------------------------------------* + lo_worksheets_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_worksheets_iterator->has_next( ) = 'X'. + + lo_worksheet ?= lo_worksheets_iterator->get_next( ). + CHECK me->guid <> lo_worksheet->get_guid( ). " Don't check against itself + IF ip_title = lo_worksheet->get_title( ). " Not unique --> raise exception + errormessage = 'Duplicate sheetname &'. + REPLACE '&' IN errormessage WITH ip_title. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = errormessage. + ENDIF. + + ENDWHILE. + +*--------------------------------------------------------------------* +* Remember old sheetname and rename sheet to desired name +*--------------------------------------------------------------------* + CONCATENATE me->title '!' INTO lv_rangesheetname_old. + me->title = ip_title. + +*--------------------------------------------------------------------* +* After changing this worksheet's title we have to adjust +* all ranges that are referring to this worksheet. +*--------------------------------------------------------------------* +* 2do §1 - Check if the following quickfix is solid +* I fear it isn't - but this implementation is better then +* nothing at all since it handles a supposed majority of cases +*--------------------------------------------------------------------* + CONCATENATE me->title '!' INTO lv_rangesheetname_new. + + lo_ranges_iterator = me->excel->get_ranges_iterator( ). + WHILE lo_ranges_iterator->has_next( ) = 'X'. + + lo_range ?= lo_ranges_iterator->get_next( ). + lv_range_value = lo_range->get_value( ). + REPLACE ALL OCCURRENCES OF lv_rangesheetname_old IN lv_range_value WITH lv_rangesheetname_new. + IF sy-subrc = 0. + lo_range->set_range_value( lv_range_value ). + ENDIF. + + ENDWHILE. + + + endmethod. + + + + METHOD update_dimension_range. + + DATA: ls_sheet_content TYPE zexcel_s_cell_data, + lt_sheet_content TYPE zexcel_t_cell_data_unsorted, + lv_row_alpha TYPE string, + lv_column_alpha TYPE zexcel_cell_column_alpha. + + CHECK sheet_content IS NOT INITIAL. + +* update dimension range + lt_sheet_content = sheet_content. + "upper left corner + SORT lt_sheet_content BY cell_row. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + upper_cell-cell_row = ls_sheet_content-cell_row. + SORT lt_sheet_content BY cell_column. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + upper_cell-cell_column = ls_sheet_content-cell_column. + + lv_row_alpha = upper_cell-cell_row. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( upper_cell-cell_column ). + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_column_alpha lv_row_alpha INTO upper_cell-cell_coords. + + "bottom right corner + SORT lt_sheet_content BY cell_row DESCENDING. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + lower_cell-cell_row = ls_sheet_content-cell_row. + SORT lt_sheet_content BY cell_column DESCENDING. + READ TABLE lt_sheet_content INDEX 1 INTO ls_sheet_content. + lower_cell-cell_column = ls_sheet_content-cell_column. + + lv_row_alpha = lower_cell-cell_row. + lv_column_alpha = zcl_excel_common=>convert_column2alpha( lower_cell-cell_column ). + SHIFT lv_row_alpha RIGHT DELETING TRAILING space. + SHIFT lv_row_alpha LEFT DELETING LEADING space. + CONCATENATE lv_column_alpha lv_row_alpha INTO lower_cell-cell_coords. + +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + method ADD. + + worksheets->add( ip_worksheet ). + + endmethod. + + + method CLEAR. + + worksheets->clear( ). + + endmethod. + + + method CONSTRUCTOR. + + CREATE OBJECT worksheets. + + endmethod. + + + + + method GET. + + DATA lv_index TYPE i. + lv_index = ip_index. + eo_worksheet ?= worksheets->if_object_collection~get( lv_index ). + + endmethod. + + + + method GET_ITERATOR. + + eo_iterator ?= worksheets->if_object_collection~get_iterator( ). + + endmethod. + + + + method IS_EMPTY. + + is_empty = worksheets->if_object_collection~is_empty( ). + + endmethod. + + + + method REMOVE. + + worksheets->remove( ip_worksheet ). + + endmethod. + + + + method SIZE. + + ep_size = worksheets->if_object_collection~size( ). + + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + + + + + + + method CONSTRUCTOR. + me->column_index = zcl_excel_common=>convert_column2int( ip_index ). + me->width = -1. + me->auto_size = abap_false. + me->visible = abap_true. + me->outline_level = 0. + me->collapsed = abap_false. + me->excel = ip_excel. "ins issue #157 - Allow Style for columns + me->worksheet = ip_worksheet. "ins issue #157 - Allow Style for columns + + " set default index to cellXf + me->xf_index = 0. + + endmethod. + + + + method GET_AUTO_SIZE. + r_auto_size = me->auto_size. + endmethod. + + + + method GET_COLLAPSED. + r_Collapsed = me->Collapsed. + endmethod. + + + + method GET_COLUMN_INDEX. + r_column_index = me->column_index. + endmethod. + + + + + method GET_COLUMN_STYLE_GUID. + IF me->style_guid IS NOT INITIAL. + ep_style_guid = me->style_guid. + ELSE. + ep_style_guid = me->worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. + endmethod. + + + + method GET_OUTLINE_LEVEL. + r_outline_level = me->outline_level. + endmethod. + + + + method GET_VISIBLE. + r_Visible = me->Visible. + endmethod. + + + + method GET_WIDTH. + r_WIDTH = me->WIDTH. + endmethod. + + + + method GET_XF_INDEX. + r_xf_index = me->xf_index. + endmethod. + + + + + method SET_AUTO_SIZE. + me->auto_size = ip_auto_size. + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLLAPSED. + me->Collapsed = ip_Collapsed. + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLUMN_INDEX. + me->column_index = zcl_excel_common=>convert_column2int( ip_index ). + r_worksheet_columndime = me. + endmethod. + + + + + method SET_COLUMN_STYLE_BY_GUID. + DATA: stylemapping TYPE zexcel_s_stylemapping. + + IF me->excel IS NOT BOUND. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Internal error - reference to ZCL_EXCEL not bound'. + ENDIF. + TRY. + stylemapping = me->excel->get_style_to_guid( ip_style_guid ). + me->style_guid = stylemapping-guid. + + CATCH zcx_excel . + EXIT. " leave as is in case of error + ENDTRY. + + endmethod. + + + + method SET_OUTLINE_LEVEL. + me->outline_level = ip_outline_level. + endmethod. + + + + + method SET_VISIBLE. + me->Visible = ip_Visible. + r_worksheet_columndime = me. + endmethod. + + + + + + method SET_WIDTH. + TRY. + me->width = ip_width. + r_worksheet_columndime = me. + CATCH cx_sy_conversion_no_number. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret width as number'. + ENDTRY. + endmethod. + + + + + method SET_XF_INDEX. + me->XF_INDEX = ip_XF_INDEX. + r_worksheet_columndime = me. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + ABAP + + + + + + + + + method CONSTRUCTOR. + " Initialise values + me->row_index = ip_index. + me->row_height = -1. + me->visible = abap_true. + me->outline_level = 0. + me->collapsed = abap_false. + + " set row dimension as unformatted by default + me->xf_index = 0. + endmethod. + + + + + METHOD get_collapsed. + + DATA: lt_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + lv_previous_row TYPE i, + lv_following_row TYPE i. + + r_collapsed = me->collapsed. + + CHECK r_collapsed = abap_false. " Maybe new method for outlines is being used + CHECK io_worksheet IS BOUND. + +* If an outline is collapsed ( even inside an outer outline ) the line following the last line +* of the group gets the flag "collapsed" + IF io_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_off. + lv_following_row = me->row_index + 1. + lt_row_outlines = io_worksheet->get_row_outlines( ). + READ TABLE lt_row_outlines TRANSPORTING NO FIELDS WITH KEY row_from = lv_following_row " first line of an outline + collapsed = abap_true. " that is collapsed + ELSE. + lv_previous_row = me->row_index - 1. + lt_row_outlines = io_worksheet->get_row_outlines( ). + READ TABLE lt_row_outlines TRANSPORTING NO FIELDS WITH KEY row_to = lv_previous_row " last line of an outline + collapsed = abap_true. " that is collapsed + ENDIF. + CHECK sy-subrc = 0. " ok - we found it + r_collapsed = abap_true. + + +ENDMETHOD. + + + + + METHOD get_outline_level. + + DATA: lt_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row. + FIELD-SYMBOLS: <ls_row_outline> LIKE LINE OF lt_row_outlines. + +* if someone has set the outline level explicitly - just use that + IF me->outline_level IS NOT INITIAL. + r_outline_level = me->outline_level. + RETURN. + ENDIF. +* Maybe we can use the outline information in the worksheet + CHECK io_worksheet IS BOUND. + + lt_row_outlines = io_worksheet->get_row_outlines( ). + LOOP AT lt_row_outlines ASSIGNING <ls_row_outline> WHERE row_from <= me->row_index + AND row_to >= me->row_index. + + ADD 1 TO r_outline_level. + + ENDLOOP. + +ENDMETHOD. + + + + method GET_ROW_HEIGHT. + r_row_height = me->row_height. + endmethod. + + + + method GET_ROW_INDEX. + r_row_index = me->row_index. + endmethod. + + + + + METHOD get_visible. + + DATA: lt_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row. + FIELD-SYMBOLS: <ls_row_outline> LIKE LINE OF lt_row_outlines. + + r_visible = me->visible. + CHECK r_visible = 'X'. " Currently visible --> but maybe the new outline methodology will hide it implicitly + CHECK io_worksheet IS BOUND. " But we have to see the worksheet to make sure + + lt_row_outlines = io_worksheet->get_row_outlines( ). + LOOP AT lt_row_outlines ASSIGNING <ls_row_outline> WHERE row_from <= me->row_index + AND row_to >= me->row_index + AND collapsed = abap_true. " row is in a collapsed outline --> not visible + CLEAR r_visible. + RETURN. " one hit is enough to ensure invisibility + + ENDLOOP. + +ENDMETHOD. + + + + method GET_XF_INDEX. + r_xf_index = me->xf_index. + endmethod. + + + + method SET_COLLAPSED. + me->collapsed = ip_collapsed. + endmethod. + + + + + method SET_OUTLINE_LEVEL. + IF ip_outline_level < 0 + OR ip_outline_level > 7. + + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Outline level must range between 0 and 7.'. + + ENDIF. + me->outline_level = ip_outline_level. + endmethod. + + + + + method SET_ROW_HEIGHT. + TRY. + me->row_height = ip_row_height. + CATCH cx_sy_conversion_no_number. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Unable to interpret ip_row_height as number'. + ENDTRY. + endmethod. + + + + method SET_ROW_INDEX. + me->row_index = ip_index. + endmethod. + + + + method SET_VISIBLE. + me->visible = ip_visible. + endmethod. + + + + method SET_XF_INDEX. + me->XF_INDEX = ip_XF_INDEX. + endmethod. + + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + + + + method ZIF_EXCEL_WRITER~WRITE_FILE. + me->excel = io_excel. + + ep_file = me->create( ). + endmethod. + + + + METHOD add_further_data_to_zip. +* Can be used by child classes like xlsm-writer to write additional data to zip archive +ENDMETHOD. + + + + method CREATE. + +* Office 2007 file format is a cab of several xml files with extension .xlsx + + DATA: lo_zip TYPE REF TO cl_abap_zip, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_active_worksheet TYPE REF TO zcl_excel_worksheet, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_nested_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_drawings TYPE REF TO zcl_excel_drawings. + + DATA: lv_content TYPE xstring, + lv_active TYPE flag, + lv_xl_sheet TYPE string, + lv_xl_sheet_rels TYPE string, + lv_xl_drawing TYPE string, + lv_xl_drawing_rels TYPE string, + lv_syindex TYPE string, + lv_value TYPE string, + lv_drawing_index TYPE i. + +********************************************************************** +* Start of insertion # issue 139 - Dateretention of cellstyles + me->excel->add_static_styles( ). +* End of insertion # issue 139 - Dateretention of cellstyles + +********************************************************************** +* STEP 1: Create archive object file (ZIP) + CREATE OBJECT lo_zip. + +********************************************************************** +* STEP 2: Add [Content_Types].xml to zip + lv_content = me->create_content_types( ). + lo_zip->add( name = me->c_content_types + content = lv_content ). + +********************************************************************** +* STEP 3: Add _rels/.rels to zip + lv_content = me->create_relationships( ). + lo_zip->add( name = me->c_relationships + content = lv_content ). + +********************************************************************** +* STEP 4: Add docProps/app.xml to zip + lv_content = me->create_docprops_app( ). + lo_zip->add( name = me->c_docprops_app + content = lv_content ). + +********************************************************************** +* STEP 5: Add docProps/core.xml to zip + lv_content = me->create_docprops_core( ). + lo_zip->add( name = me->c_docprops_core + content = lv_content ). + +********************************************************************** +* STEP 6: Add xl/_rels/workbook.xml.rels to zip + lv_content = me->create_xl_relationships( ). + lo_zip->add( name = me->c_xl_relationships + content = lv_content ). + +********************************************************************** +* STEP 6: Add xl/_rels/workbook.xml.rels to zip + lv_content = me->create_xl_theme( ). + lo_zip->add( name = me->c_xl_theme + content = lv_content ). + +********************************************************************** +* STEP 7: Add xl/workbook.xml to zip + lv_content = me->create_xl_workbook( ). + lo_zip->add( name = me->c_xl_workbook + content = lv_content ). + +********************************************************************** +* STEP 8: Add xl/workbook.xml to zip +* lv_content = me->create_xl_styles_static( ). + lv_content = me->create_xl_styles( ). + lo_zip->add( name = me->c_xl_styles + content = lv_content ). + +********************************************************************** +* STEP 9: Add sharedStrings.xml to zip + lv_content = me->create_xl_sharedstrings( ). + lo_zip->add( name = me->c_xl_sharedstrings + content = lv_content ). + +********************************************************************** +* STEP 10: Add sheet#.xml and drawing#.xml to zip + lo_iterator = me->excel->get_worksheets_iterator( ). + lo_active_worksheet = me->excel->get_active_worksheet( ). + lv_drawing_index = 1. + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF lo_active_worksheet->get_guid( ) EQ lo_worksheet->get_guid( ). + lv_active = abap_true. + ELSE. + lv_active = abap_false. + ENDIF. + lv_content = me->create_xl_sheet( io_worksheet = lo_worksheet + iv_active = lv_active ). + lv_xl_sheet = me->c_xl_sheet. + MOVE sy-index TO lv_syindex. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet WITH lv_syindex. + lo_zip->add( name = lv_xl_sheet + content = lv_content ). + + lv_xl_sheet_rels = me->c_xl_sheet_rels. + lv_content = me->create_xl_sheet_rels( io_worksheet = lo_worksheet + iv_drawing_index = lv_drawing_index ). + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet_rels WITH lv_syindex. + lo_zip->add( name = lv_xl_sheet_rels + content = lv_content ). + + lo_nested_iterator = lo_worksheet->get_tables_iterator( ). + + WHILE lo_nested_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_nested_iterator->if_object_collection_iterator~get_next( ). + lv_content = me->create_xl_table( lo_table ). + + lv_value = lo_table->get_name( ). + CONCATENATE 'xl/tables/' lv_value '.xml' INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +* Add drawings ********************************** + lo_drawings = lo_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + MOVE lv_drawing_index TO lv_syindex. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + + lv_content = me->create_xl_drawings( lo_worksheet ). + lv_xl_drawing = me->c_xl_drawings. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing WITH lv_syindex. + lo_zip->add( name = lv_xl_drawing + content = lv_content ). + + lv_content = me->create_xl_drawings_rels( lo_worksheet ). + lv_xl_drawing_rels = me->c_xl_drawings_rels. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing_rels WITH lv_syindex. + lo_zip->add( name = lv_xl_drawing_rels + content = lv_content ). + ADD 1 TO lv_drawing_index. + ENDIF. + + ENDWHILE. + +********************************************************************** +* STEP 11: Add media + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_image ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_content = lo_drawing->get_media( ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/media/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +********************************************************************** +* STEP 12: Add charts + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_chart ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_content = lo_drawing->get_media( ). + + "-------------Added by Alessandro Iannacci - Only if template exist + IF lv_content IS NOT INITIAL AND me->excel->use_template EQ abap_true. + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/charts/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ELSE. "ADD CUSTOM CHART!!!! + lv_content = me->create_xl_charts( lo_drawing ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/charts/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDIF. + "------------------------------------------------- + ENDWHILE. + +* Second to last step: Allow further information put into the zip archive by child classes + me->add_further_data_to_zip( lo_zip ). + +********************************************************************** +* Last step: Create the final zip + ep_excel = lo_zip->save( ). + + endmethod. + + + + method CREATE_CONTENT_TYPES. + + +** Constant node name + DATA: lc_xml_node_types TYPE string VALUE 'Types', + lc_xml_node_override TYPE string VALUE 'Override', + lc_xml_node_default TYPE string VALUE 'Default', + " Node attributes + lc_xml_attr_partname TYPE string VALUE 'PartName', + lc_xml_attr_extension TYPE string VALUE 'Extension', + lc_xml_attr_contenttype TYPE string VALUE 'ContentType', + " Node namespace + lc_xml_node_types_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/content-types', + " Node extension + lc_xml_node_rels_ext TYPE string VALUE 'rels', + lc_xml_node_xml_ext TYPE string VALUE 'xml', + " Node partnumber + lc_xml_node_theme_pn TYPE string VALUE '/xl/theme/theme1.xml', + lc_xml_node_styles_pn TYPE string VALUE '/xl/styles.xml', + lc_xml_node_workb_pn TYPE string VALUE '/xl/workbook.xml', + lc_xml_node_props_pn TYPE string VALUE '/docProps/app.xml', + lc_xml_node_worksheet_pn TYPE string VALUE '/xl/worksheets/sheet#.xml', + lc_xml_node_strings_pn TYPE string VALUE '/xl/sharedStrings.xml', + lc_xml_node_core_pn TYPE string VALUE '/docProps/core.xml', + lc_xml_node_chart_pn TYPE string VALUE '/xl/charts/chart#.xml', + " Node contentType + lc_xml_node_theme_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.theme+xml', + lc_xml_node_styles_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml', + lc_xml_node_workb_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml', + lc_xml_node_rels_ct TYPE string VALUE 'application/vnd.openxmlformats-package.relationships+xml', + lc_xml_node_xml_ct TYPE string VALUE 'application/xml', + lc_xml_node_props_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.extended-properties+xml', + lc_xml_node_worksheet_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml', + lc_xml_node_strings_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml', + lc_xml_node_core_ct TYPE string VALUE 'application/vnd.openxmlformats-package.core-properties+xml', + lc_xml_node_table_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml', + lc_xml_node_drawings_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.drawing+xml', + lc_xml_node_chart_ct TYPE string VALUE 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_nested_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table. + + DATA: lv_worksheets_num TYPE i, + lv_worksheets_numc TYPE numc3, + lv_xml_node_worksheet_pn TYPE string, + lv_xml_size TYPE i, + lv_value TYPE string, + lv_drawing_index TYPE i VALUE 1, + lv_index_str TYPE string. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'UTF-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node types + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_types + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_types_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + " rels node + lo_element = lo_document->create_simple_element( name = lc_xml_node_default + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_extension + value = lc_xml_node_rels_ext ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_rels_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " extension node + lo_element = lo_document->create_simple_element( name = lc_xml_node_default + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_extension + value = lc_xml_node_xml_ext ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_xml_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Theme node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_theme_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_theme_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Styles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_styles_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_styles_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Workbook node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_workb_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_workb_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Properties node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_props_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_props_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Worksheet node + lv_worksheets_num = excel->get_worksheets_size( ). + DO lv_worksheets_num TIMES. + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + + MOVE sy-index TO lv_worksheets_numc. + SHIFT lv_worksheets_numc LEFT DELETING LEADING '0'. + lv_xml_node_worksheet_pn = lc_xml_node_worksheet_pn. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_worksheet_pn WITH lv_worksheets_numc. + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_xml_node_worksheet_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_worksheet_ct ). + lo_element_root->append_child( new_child = lo_element ). + ENDDO. + + lo_iterator = me->excel->get_worksheets_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lo_nested_iterator = lo_worksheet->get_tables_iterator( ). + + WHILE lo_nested_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_nested_iterator->if_object_collection_iterator~get_next( ). + + lv_value = lo_table->get_name( ). + CONCATENATE '/xl/tables/' lv_value '.xml' INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_table_ct ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + + " Drawings + DATA: lo_drawings TYPE REF TO zcl_excel_drawings. + + lo_drawings = lo_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + lv_index_str = lv_drawing_index. + CONDENSE lv_index_str NO-GAPS. + CONCATENATE '/' me->c_xl_drawings INTO lv_value. + REPLACE '#' WITH lv_index_str INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_drawings_ct ). + lo_element_root->append_child( new_child = lo_element ). + + ADD 1 TO lv_drawing_index. + ENDIF. + ENDWHILE. + + " media mimes + DATA: lo_drawing TYPE REF TO zcl_excel_drawing, + lt_media_type TYPE TABLE OF mimetypes-extension, + lv_media_type TYPE mimetypes-extension, + lv_mime_type TYPE mimetypes-type. + + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_image ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) = abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_media_type = lo_drawing->get_media_type( ). + COLLECT lv_media_type INTO lt_media_type. + ENDWHILE. + + LOOP AT lt_media_type INTO lv_media_type. + CALL FUNCTION 'SDOK_MIMETYPE_GET' + EXPORTING + extension = lv_media_type + IMPORTING + mimetype = lv_mime_type. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_default + parent = lo_document ). + lv_value = lv_media_type. + lo_element->set_attribute_ns( name = lc_xml_attr_extension + value = lv_value ). + lv_value = lv_mime_type. + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDLOOP. + + " Charts + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_chart ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) = abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lv_index_str = lo_drawing->get_index( ). + CONDENSE lv_index_str. + lv_value = lc_xml_node_chart_pn. + REPLACE ALL OCCURRENCES OF '#' IN lv_value WITH lv_index_str. + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_chart_ct ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + + " Strings node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_strings_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_strings_ct ). + lo_element_root->append_child( new_child = lo_element ). + + " Strings node + lo_element = lo_document->create_simple_element( name = lc_xml_node_override + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_partname + value = lc_xml_node_core_pn ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_core_ct ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + method CREATE_DOCPROPS_APP. + + +** Constant node name + DATA: lc_xml_node_properties TYPE string VALUE 'Properties', + lc_xml_node_application TYPE string VALUE 'Application', + lc_xml_node_docsecurity TYPE string VALUE 'DocSecurity', + lc_xml_node_scalecrop TYPE string VALUE 'ScaleCrop', + lc_xml_node_headingpairs TYPE string VALUE 'HeadingPairs', + lc_xml_node_vector TYPE string VALUE 'vector', + lc_xml_node_variant TYPE string VALUE 'variant', + lc_xml_node_lpstr TYPE string VALUE 'lpstr', + lc_xml_node_i4 TYPE string VALUE 'i4', + lc_xml_node_titlesofparts TYPE string VALUE 'TitlesOfParts', + lc_xml_node_company TYPE string VALUE 'Company', + lc_xml_node_linksuptodate TYPE string VALUE 'LinksUpToDate', + lc_xml_node_shareddoc TYPE string VALUE 'SharedDoc', + lc_xml_node_hyperlinkschanged TYPE string VALUE 'HyperlinksChanged', + lc_xml_node_appversion TYPE string VALUE 'AppVersion', + " Namespace prefix + lc_vt_ns TYPE string VALUE 'vt', + lc_xml_node_props_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties', + lc_xml_node_props_vt_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes', + " Node attributes + lc_xml_attr_size TYPE string VALUE 'size', + lc_xml_attr_basetype TYPE string VALUE 'baseType'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_sub_element_vector TYPE REF TO if_ixml_element, + lo_sub_element_variant TYPE REF TO if_ixml_element, + lo_sub_element_lpstr TYPE REF TO if_ixml_element, + lo_sub_element_i4 TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: lv_value TYPE string. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node properties + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_properties + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_props_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:vt' + value = lc_xml_node_props_vt_ns ). + +********************************************************************** +* STEP 4: Create subnodes + " Application + lo_element = lo_document->create_simple_element( name = lc_xml_node_application + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~application. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " DocSecurity + lo_element = lo_document->create_simple_element( name = lc_xml_node_docsecurity + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~docsecurity. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " ScaleCrop + lo_element = lo_document->create_simple_element( name = lc_xml_node_scalecrop + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~scalecrop ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " HeadingPairs + lo_element = lo_document->create_simple_element( name = lc_xml_node_headingpairs + parent = lo_document ). + + + " * vector node + lo_sub_element_vector = lo_document->create_simple_element_ns( name = lc_xml_node_vector + prefix = lc_vt_ns + parent = lo_document ). + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_size + value = '2' ). + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_basetype + value = lc_xml_node_variant ). + + " ** variant node + lo_sub_element_variant = lo_document->create_simple_element_ns( name = lc_xml_node_variant + prefix = lc_vt_ns + parent = lo_document ). + + " *** lpstr node + lo_sub_element_lpstr = lo_document->create_simple_element_ns( name = lc_xml_node_lpstr + prefix = lc_vt_ns + parent = lo_document ). + lv_value = excel->get_worksheets_name( ). + lo_sub_element_lpstr->set_value( value = lv_value ). + lo_sub_element_variant->append_child( new_child = lo_sub_element_lpstr ). " lpstr node + + lo_sub_element_vector->append_child( new_child = lo_sub_element_variant ). " variant node + + " ** variant node + lo_sub_element_variant = lo_document->create_simple_element_ns( name = lc_xml_node_variant + prefix = lc_vt_ns + parent = lo_document ). + + " *** i4 node + lo_sub_element_i4 = lo_document->create_simple_element_ns( name = lc_xml_node_i4 + prefix = lc_vt_ns + parent = lo_document ). + lv_value = excel->get_worksheets_size( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_i4->set_value( value = lv_value ). + lo_sub_element_variant->append_child( new_child = lo_sub_element_i4 ). " lpstr node + + lo_sub_element_vector->append_child( new_child = lo_sub_element_variant ). " variant node + + lo_element->append_child( new_child = lo_sub_element_vector ). " vector node + + lo_element_root->append_child( new_child = lo_element ). " HeadingPairs + + + " TitlesOfParts + lo_element = lo_document->create_simple_element( name = lc_xml_node_titlesofparts + parent = lo_document ). + + + " * vector node + lo_sub_element_vector = lo_document->create_simple_element_ns( name = lc_xml_node_vector + prefix = lc_vt_ns + parent = lo_document ). + lv_value = excel->get_worksheets_size( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_size + value = lv_value ). + lo_sub_element_vector->set_attribute_ns( name = lc_xml_attr_basetype + value = lc_xml_node_lpstr ). + + lo_iterator = excel->get_worksheets_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + " ** lpstr node + lo_sub_element_lpstr = lo_document->create_simple_element_ns( name = lc_xml_node_lpstr + prefix = lc_vt_ns + parent = lo_document ). + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_value = lo_worksheet->get_title( ). + lo_sub_element_lpstr->set_value( value = lv_value ). + lo_sub_element_vector->append_child( new_child = lo_sub_element_lpstr ). " lpstr node + ENDWHILE. + + lo_element->append_child( new_child = lo_sub_element_vector ). " vector node + + lo_element_root->append_child( new_child = lo_element ). " TitlesOfParts + + + + " Company + IF excel->zif_excel_book_properties~company IS NOT INITIAL. + lo_element = lo_document->create_simple_element( name = lc_xml_node_company + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~company. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + " LinksUpToDate + lo_element = lo_document->create_simple_element( name = lc_xml_node_linksuptodate + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~linksuptodate ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " SharedDoc + lo_element = lo_document->create_simple_element( name = lc_xml_node_shareddoc + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~shareddoc ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " HyperlinksChanged + lo_element = lo_document->create_simple_element( name = lc_xml_node_hyperlinkschanged + parent = lo_document ). + lv_value = me->flag2bool( excel->zif_excel_book_properties~hyperlinkschanged ). + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " AppVersion + lo_element = lo_document->create_simple_element( name = lc_xml_node_appversion + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~appversion. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + method CREATE_DOCPROPS_CORE. + + +** Constant node name + DATA: lc_xml_node_coreproperties TYPE string VALUE 'coreProperties', + lc_xml_node_creator TYPE string VALUE 'creator', + lc_xml_node_description TYPE string VALUE 'description', + lc_xml_node_lastmodifiedby TYPE string VALUE 'lastModifiedBy', + lc_xml_node_created TYPE string VALUE 'created', + lc_xml_node_modified TYPE string VALUE 'modified', + " Node attributes + lc_xml_attr_type TYPE string VALUE 'type', + lc_xml_attr_target TYPE string VALUE 'dcterms:W3CDTF', + " Node namespace + lc_cp_ns TYPE string VALUE 'cp', + lc_dc_ns TYPE string VALUE 'dc', + lc_dcterms_ns TYPE string VALUE 'dcterms', +* lc_dcmitype_ns TYPE string VALUE 'dcmitype', + lc_xsi_ns TYPE string VALUE 'xsi', + lc_xml_node_cp_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties', + lc_xml_node_dc_ns TYPE string VALUE 'http://purl.org/dc/elements/1.1/', + lc_xml_node_dcterms_ns TYPE string VALUE 'http://purl.org/dc/terms/', + lc_xml_node_dcmitype_ns TYPE string VALUE 'http://purl.org/dc/dcmitype/', + lc_xml_node_xsi_ns TYPE string VALUE 'http://www.w3.org/2001/XMLSchema-instance'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_value TYPE string, + lv_date TYPE sydatum, + lv_time TYPE syuzeit. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node coreProperties + lo_element_root = lo_document->create_simple_element_ns( name = lc_xml_node_coreproperties + prefix = lc_cp_ns + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns:cp' + value = lc_xml_node_cp_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:dc' + value = lc_xml_node_dc_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:dcterms' + value = lc_xml_node_dcterms_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:dcmitype' + value = lc_xml_node_dcmitype_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:xsi' + value = lc_xml_node_xsi_ns ). + +********************************************************************** +* STEP 4: Create subnodes + " Creator node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_creator + prefix = lc_dc_ns + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~creator. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " Description node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_description + prefix = lc_dc_ns + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~description. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " lastModifiedBy node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_lastmodifiedby + prefix = lc_cp_ns + parent = lo_document ). + lv_value = excel->zif_excel_book_properties~lastmodifiedby. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " Created node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_created + prefix = lc_dcterms_ns + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + prefix = lc_xsi_ns + value = lc_xml_attr_target ). + + CONVERT TIME STAMP excel->zif_excel_book_properties~created TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time. + CONCATENATE lv_date lv_time INTO lv_value RESPECTING BLANKS. + REPLACE ALL OCCURRENCES OF REGEX '([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})' IN lv_value WITH '$1-$2-$3T$4:$5:$6Z'. +* lv_value = excel->zif_excel_book_properties~created. +* lv_value = '2010-07-04T14:58:53Z'. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " Modified node + lo_element = lo_document->create_simple_element_ns( name = lc_xml_node_modified + prefix = lc_dcterms_ns + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + prefix = lc_xsi_ns + value = lc_xml_attr_target ). + CONVERT TIME STAMP excel->zif_excel_book_properties~modified TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time. + CONCATENATE lv_date lv_time INTO lv_value RESPECTING BLANKS. + REPLACE ALL OCCURRENCES OF REGEX '([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})' IN lv_value WITH '$1-$2-$3T$4:$5:$6Z'. +* lv_value = excel->zif_excel_book_properties~modified. +* lv_value = '2010-07-04T14:58:53Z'. + lo_element->set_value( value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + + + + + + + METHOD create_dxf_style. + + CONSTANTS: lc_xml_node_dxf TYPE string VALUE 'dxf', + lc_xml_node_font TYPE string VALUE 'font', + lc_xml_node_b TYPE string VALUE 'b', "bold + lc_xml_node_i TYPE string VALUE 'i', "italic + lc_xml_node_u TYPE string VALUE 'u', "underline + lc_xml_node_strike TYPE string VALUE 'strike', "strikethrough + lc_xml_attr_val TYPE string VALUE 'val', + lc_xml_node_fill TYPE string VALUE 'fill', + lc_xml_node_patternfill TYPE string VALUE 'patternFill', + lc_xml_attr_patterntype TYPE string VALUE 'patternType', + lc_xml_node_fgcolor TYPE string VALUE 'fgColor', + lc_xml_node_bgcolor TYPE string VALUE 'bgColor', + y TYPE i VALUE 0. + + DATA: ls_styles_mapping TYPE zexcel_s_styles_mapping, + ls_cellxfs TYPE zexcel_s_cellxfs, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + lo_sub_element TYPE REF TO if_ixml_element, + lo_sub_element_2 TYPE REF TO if_ixml_element, + lv_index TYPE i, + ls_font TYPE zexcel_s_style_font, + lo_element_font TYPE REF TO if_ixml_element, + lv_value TYPE string, + ls_fill TYPE zexcel_s_style_fill, + lo_element_fill TYPE REF TO if_ixml_element, + x. + + CHECK iv_cell_style IS NOT INITIAL. + + READ TABLE me->styles_mapping INTO ls_styles_mapping WITH KEY guid = iv_cell_style. + ADD 1 TO ls_styles_mapping-style. " the numbering starts from 0 + READ TABLE it_cellxfs INTO ls_cellxfs INDEX ls_styles_mapping-style. + ADD 1 TO ls_cellxfs-fillid. " the numbering starts from 0 + + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY style = ls_styles_mapping-style. + IF sy-subrc EQ 0. + ls_style_cond_mapping-guid = iv_cell_style. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ELSE. + ls_style_cond_mapping-guid = iv_cell_style. + ls_style_cond_mapping-style = ls_styles_mapping-style. + ls_style_cond_mapping-dxf = cv_dfx_count. + APPEND ls_style_cond_mapping TO me->styles_cond_mapping. + ADD 1 TO cv_dfx_count. + + " dxf node + lo_sub_element = io_ixml_document->create_simple_element( name = lc_xml_node_dxf + parent = io_ixml_document ). + + "Conditional formatting font style correction by Alessandro Iannacci START + lv_index = ls_cellxfs-fontid + 1. + READ TABLE it_fonts INTO ls_font INDEX lv_index. + IF ls_font IS NOT INITIAL. + lo_element_font = io_ixml_document->create_simple_element( name = lc_xml_node_font + parent = io_ixml_document ). + IF ls_font-bold EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_b + parent = io_ixml_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-italic EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_i + parent = io_ixml_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-underline EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_u + parent = io_ixml_document ). + lv_value = ls_font-underline_mode. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_font-strikethrough EQ abap_true. + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_strike + parent = io_ixml_document ). + lo_element_font->append_child( new_child = lo_sub_element_2 ). + ENDIF. + "color + create_xl_styles_color_node( + io_document = io_ixml_document + io_parent = lo_element_font + is_color = ls_font-color ). + lo_sub_element->append_child( new_child = lo_element_font ). + ENDIF. + "---Conditional formatting font style correction by Alessandro Iannacci END + + + READ TABLE it_fills INTO ls_fill INDEX ls_cellxfs-fillid. + IF ls_fill IS NOT INITIAL. + " fill properties + lo_element_fill = io_ixml_document->create_simple_element( name = lc_xml_node_fill + parent = io_ixml_document ). + "pattern + lo_sub_element_2 = io_ixml_document->create_simple_element( name = lc_xml_node_patternfill + parent = io_ixml_document ). + lv_value = ls_fill-filltype. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = io_ixml_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + IF ls_fill-fgcolor-rgb IS INITIAL AND + ls_fill-fgcolor-indexed EQ zcl_excel_style_color=>c_indexed_not_set AND + ls_fill-fgcolor-theme EQ zcl_excel_style_color=>c_theme_not_set AND + ls_fill-fgcolor-tint IS INITIAL AND ls_fill-bgcolor-indexed EQ zcl_excel_style_color=>c_indexed_sys_foreground. + + " bgcolor + create_xl_styles_color_node( + io_document = io_ixml_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + ENDIF. + + lo_element_fill->append_child( new_child = lo_sub_element_2 ). "pattern + + lo_sub_element->append_child( new_child = lo_element_fill ). + ENDIF. + ENDIF. + + io_dxf_element->append_child( new_child = lo_sub_element ). +ENDMETHOD. + + + + method CREATE_RELATIONSHIPS. + + +** Constant node name + DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'Id', + lc_xml_attr_type TYPE string VALUE 'Type', + lc_xml_attr_target TYPE string VALUE 'Target', + " Node namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + " Node id + lc_xml_node_rId1_id TYPE string VALUE 'rId1', + lc_xml_node_rId2_id TYPE string VALUE 'rId2', + lc_xml_node_rId3_id TYPE string VALUE 'rId3', + " Node type + lc_xml_node_rId1_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', + lc_xml_node_rId2_tp TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + lc_xml_node_rId3_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', + " Node target + lc_xml_node_rId1_tg TYPE string VALUE 'xl/workbook.xml', + lc_xml_node_rId2_tg TYPE string VALUE 'docProps/core.xml', + lc_xml_node_rId3_tg TYPE string VALUE 'docProps/app.xml'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + " Theme node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lc_xml_node_rId3_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rId3_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rId3_tg ). + lo_element_root->append_child( new_child = lo_element ). + + " Styles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lc_xml_node_rId2_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rId2_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rId2_tg ). + lo_element_root->append_child( new_child = lo_element ). + + " rels node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lc_xml_node_rId1_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rId1_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rId1_tg ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + + method CREATE_XL_CHARTS. + + +** Constant node name + CONSTANTS: lc_xml_node_chartspace TYPE string VALUE 'c:chartSpace', + lc_xml_node_ns_c TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/chart', + lc_xml_node_ns_a TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/main', + lc_xml_node_ns_r TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + lc_xml_node_date1904 TYPE string VALUE 'c:date1904', + lc_xml_node_lang TYPE string VALUE 'c:lang', + lc_xml_node_roundedcorners TYPE string VALUE 'c:roundedCorners', + lc_xml_node_altcont TYPE string VALUE 'mc:AlternateContent', + lc_xml_node_altcont_ns_mc TYPE string VALUE 'http://schemas.openxmlformats.org/markup-compatibility/2006', + lc_xml_node_choice TYPE string VALUE 'mc:Choice', + lc_xml_node_choice_ns_requires TYPE string VALUE 'c14', + lc_xml_node_choice_ns_c14 TYPE string VALUE 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart', + lc_xml_node_style TYPE string VALUE 'c14:style', + lc_xml_node_fallback TYPE string VALUE 'mc:Fallback', + lc_xml_node_style2 TYPE string VALUE 'c:style', + + "---------------------------CHART + lc_xml_node_chart TYPE string VALUE 'c:chart', + lc_xml_node_autotitledeleted TYPE string VALUE 'c:autoTitleDeleted', + "plotArea + lc_xml_node_plotarea TYPE string VALUE 'c:plotArea', + lc_xml_node_layout TYPE string VALUE 'c:layout', + lc_xml_node_varycolors TYPE string VALUE 'c:varyColors', + lc_xml_node_ser TYPE string VALUE 'c:ser', + lc_xml_node_idx TYPE string VALUE 'c:idx', + lc_xml_node_order TYPE string VALUE 'c:order', + lc_xml_node_tx TYPE string VALUE 'c:tx', + lc_xml_node_v TYPE string VALUE 'c:v', + lc_xml_node_val TYPE string VALUE 'c:val', + lc_xml_node_cat TYPE string VALUE 'c:cat', + lc_xml_node_numref TYPE string VALUE 'c:numRef', + lc_xml_node_strref TYPE string VALUE 'c:strRef', + lc_xml_node_f TYPE string VALUE 'c:f', "this is the range + lc_xml_node_overlap TYPE string VALUE 'c:overlap', + "note: numcache avoided + lc_xml_node_dlbls TYPE string VALUE 'c:dLbls', + lc_xml_node_showlegendkey TYPE string VALUE 'c:showLegendKey', + lc_xml_node_showval TYPE string VALUE 'c:showVal', + lc_xml_node_showcatname TYPE string VALUE 'c:showCatName', + lc_xml_node_showsername TYPE string VALUE 'c:showSerName', + lc_xml_node_showpercent TYPE string VALUE 'c:showPercent', + lc_xml_node_showbubblesize TYPE string VALUE 'c:showBubbleSize', + "plotArea->pie + lc_xml_node_piechart TYPE string VALUE 'c:pieChart', + lc_xml_node_showleaderlines TYPE string VALUE 'c:showLeaderLines', + lc_xml_node_firstsliceang TYPE string VALUE 'c:firstSliceAng', + "plotArea->line + lc_xml_node_linechart TYPE string VALUE 'c:lineChart', + lc_xml_node_symbol TYPE string VALUE 'c:symbol', + lc_xml_node_marker TYPE string VALUE 'c:marker', + lc_xml_node_smooth TYPE string VALUE 'c:smooth', + "plotArea->bar + lc_xml_node_invertifnegative TYPE string VALUE 'c:invertIfNegative', + lc_xml_node_barchart TYPE string VALUE 'c:barChart', + lc_xml_node_bardir TYPE string VALUE 'c:barDir', + lc_xml_node_gapwidth TYPE string VALUE 'c:gapWidth', + "plotArea->line + plotArea->bar + lc_xml_node_grouping TYPE string VALUE 'c:grouping', + lc_xml_node_axid TYPE string VALUE 'c:axId', + lc_xml_node_catax TYPE string VALUE 'c:catAx', + lc_xml_node_valax TYPE string VALUE 'c:valAx', + lc_xml_node_scaling TYPE string VALUE 'c:scaling', + lc_xml_node_orientation TYPE string VALUE 'c:orientation', + lc_xml_node_delete TYPE string VALUE 'c:delete', + lc_xml_node_axpos TYPE string VALUE 'c:axPos', + lc_xml_node_numfmt TYPE string VALUE 'c:numFmt', + lc_xml_node_majorgridlines TYPE string VALUE 'c:majorGridlines', + lc_xml_node_majortickmark TYPE string VALUE 'c:majorTickMark', + lc_xml_node_minortickmark TYPE string VALUE 'c:minorTickMark', + lc_xml_node_ticklblpos TYPE string VALUE 'c:tickLblPos', + lc_xml_node_crossax TYPE string VALUE 'c:crossAx', + lc_xml_node_crosses TYPE string VALUE 'c:crosses', + lc_xml_node_auto TYPE string VALUE 'c:auto', + lc_xml_node_lblalgn TYPE string VALUE 'c:lblAlgn', + lc_xml_node_lbloffset TYPE string VALUE 'c:lblOffset', + lc_xml_node_nomultilvllbl TYPE string VALUE 'c:noMultiLvlLbl', + lc_xml_node_crossbetween TYPE string VALUE 'c:crossBetween', + "legend + lc_xml_node_legend TYPE string VALUE 'c:legend', + "legend->pie + lc_xml_node_legendpos TYPE string VALUE 'c:legendPos', +* lc_xml_node_layout TYPE string VALUE 'c:layout', "already exist + lc_xml_node_overlay TYPE string VALUE 'c:overlay', + lc_xml_node_txpr TYPE string VALUE 'c:txPr', + lc_xml_node_bodypr TYPE string VALUE 'a:bodyPr', + lc_xml_node_lststyle TYPE string VALUE 'a:lstStyle', + lc_xml_node_p TYPE string VALUE 'a:p', + lc_xml_node_ppr TYPE string VALUE 'a:pPr', + lc_xml_node_defrpr TYPE string VALUE 'a:defRPr', + lc_xml_node_endpararpr TYPE string VALUE 'a:endParaRPr', + "legend->bar + legend->line + lc_xml_node_plotvisonly TYPE string VALUE 'c:plotVisOnly', + lc_xml_node_dispblanksas TYPE string VALUE 'c:dispBlanksAs', + lc_xml_node_showdlblsovermax TYPE string VALUE 'c:showDLblsOverMax', + "---------------------------END OF CHART + + lc_xml_node_printsettings TYPE string VALUE 'c:printSettings', + lc_xml_node_headerfooter TYPE string VALUE 'c:headerFooter', + lc_xml_node_pagemargins TYPE string VALUE 'c:pageMargins', + lc_xml_node_pagesetup TYPE string VALUE 'c:pageSetup'. + + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element_cellanchor TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + DATA: lv_rel_id TYPE i. + + DATA lo_element TYPE REF TO if_ixml_element. + DATA lo_element2 TYPE REF TO if_ixml_element. + DATA lo_element3 TYPE REF TO if_ixml_element. + DATA lo_el_rootchart TYPE REF TO if_ixml_element. + DATA lo_element4 TYPE REF TO if_ixml_element. + DATA lo_element5 TYPE REF TO if_ixml_element. + DATA lo_element6 TYPE REF TO if_ixml_element. + DATA lo_element7 TYPE REF TO if_ixml_element. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_chartspace + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns:c' + value = lc_xml_node_ns_c ). + lo_element_root->set_attribute_ns( name = 'xmlns:a' + value = lc_xml_node_ns_a ). + lo_element_root->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_ns_r ). + +********************************************************************** +* STEP 4: Create chart + + DATA lo_chartb TYPE REF TO zcl_excel_graph_bars. + DATA lo_chartp TYPE REF TO zcl_excel_graph_pie. + DATA lo_chartl TYPE REF TO zcl_excel_graph_line. + DATA lo_chart TYPE REF TO zcl_excel_graph. + + DATA ls_serie TYPE zcl_excel_graph=>s_series. + DATA ls_ax TYPE zcl_excel_graph_bars=>s_ax. + DATA lv_str TYPE string. + + "Identify chart type + CASE io_drawing->graph_type. + WHEN zcl_excel_drawing=>c_graph_bars. + lo_chartb ?= io_drawing->graph. + WHEN zcl_excel_drawing=>c_graph_pie. + lo_chartp ?= io_drawing->graph. + WHEN zcl_excel_drawing=>c_graph_line. + lo_chartl ?= io_drawing->graph. + WHEN OTHERS. + ENDCASE. + + + lo_chart = io_drawing->graph. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_date1904 + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'val' + value = lo_chart->ns_1904val ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_lang + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'val' + value = lo_chart->ns_langval ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_roundedcorners + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'val' + value = lo_chart->ns_roundedcornersval ). + + lo_element = lo_document->create_simple_element( name = lc_xml_node_altcont + parent = lo_element_root ). + lo_element->set_attribute_ns( name = 'xmlns:mc' + value = lc_xml_node_altcont_ns_mc ). + + "Choice + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_choice + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'Requires' + value = lc_xml_node_choice_ns_requires ). + lo_element2->set_attribute_ns( name = 'xmlns:c14' + value = lc_xml_node_choice_ns_c14 ). + + "C14:style + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_style + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chart->ns_c14styleval ). + + "Fallback + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_fallback + parent = lo_element ). + + "C:style + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_style2 + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chart->ns_styleval ). + + "---------------------------CHART + lo_element = lo_document->create_simple_element( name = lc_xml_node_chart + parent = lo_element_root ). + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_autotitledeleted + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_autotitledeletedval ). + + "plotArea + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_plotarea + parent = lo_element ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + CASE io_drawing->graph_type. + WHEN zcl_excel_drawing=>c_graph_bars. + "----bar + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_barchart + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_bardir + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_bardirval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_grouping + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_groupingval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_varycolors + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_varycolorsval ). + + "series + LOOP AT lo_chartb->series INTO ls_serie. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ser + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_idx + parent = lo_element4 ). + IF ls_serie-idx IS NOT INITIAL. + lv_str = ls_serie-idx. + ELSE. + lv_str = sy-tabix - 1. + ENDIF. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_order + parent = lo_element4 ). + lv_str = ls_serie-order. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + IF ls_serie-sername IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_tx + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_element5 ). + lo_element6->set_value( value = ls_serie-sername ). + ENDIF. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_invertifnegative + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_serie-invertifnegative ). + IF ls_serie-lbl IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_cat + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_strref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-lbl ). + ENDIF. + IF ls_serie-ref IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_val + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_numref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-ref ). + ENDIF. + ENDLOOP. + "endseries + IF lo_chartb->ns_groupingval = zcl_excel_graph_bars=>c_groupingval_stacked. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_overlap + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = '100' ). + ENDIF. + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_dlbls + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showlegendkey + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showlegendkeyval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showval + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showvalval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showcatname + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showcatnameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showsername + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showsernameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showpercent + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showpercentval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showbubblesize + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartb->ns_showbubblesizeval ). + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_gapwidth + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartb->ns_gapwidthval ). + + "axes + lo_el_rootchart = lo_element3. + LOOP AT lo_chartb->axes INTO ls_ax. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_el_rootchart ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + CASE ls_ax-type. + WHEN zcl_excel_graph_bars=>c_catax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_catax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'formatCode' + value = ls_ax-formatcode ). + lo_element4->set_attribute_ns( name = 'sourceLinked' + value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_auto + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-auto ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lblalgn + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lblalgn ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lbloffset + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lbloffset ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_nomultilvllbl + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-nomultilvllbl ). + WHEN zcl_excel_graph_bars=>c_valax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_valax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majorgridlines + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'formatCode' + value = ls_ax-formatcode ). + lo_element4->set_attribute_ns( name = 'sourceLinked' + value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossbetween + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossbetween ). + WHEN OTHERS. + ENDCASE. + ENDLOOP. + "endaxes + + WHEN zcl_excel_drawing=>c_graph_pie. + "----pie + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_piechart + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_varycolors + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartp->ns_varycolorsval ). + + "series + LOOP AT lo_chartp->series INTO ls_serie. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ser + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_idx + parent = lo_element4 ). + IF ls_serie-idx IS NOT INITIAL. + lv_str = ls_serie-idx. + ELSE. + lv_str = sy-tabix - 1. + ENDIF. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_order + parent = lo_element4 ). + lv_str = ls_serie-order. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + IF ls_serie-sername IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_tx + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_element5 ). + lo_element6->set_value( value = ls_serie-sername ). + ENDIF. + IF ls_serie-lbl IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_cat + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_strref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-lbl ). + ENDIF. + IF ls_serie-ref IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_val + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_numref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-ref ). + ENDIF. + ENDLOOP. + "endseries + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_dlbls + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showlegendkey + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showlegendkeyval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showval + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showvalval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showcatname + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showcatnameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showsername + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showsernameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showpercent + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showpercentval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showbubblesize + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showbubblesizeval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showleaderlines + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartp->ns_showleaderlinesval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_firstsliceang + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartp->ns_firstsliceangval ). + WHEN zcl_excel_drawing=>c_graph_line. + "----line + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_linechart + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_grouping + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->ns_groupingval ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_varycolors + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->ns_varycolorsval ). + + "series + LOOP AT lo_chartl->series INTO ls_serie. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ser + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_idx + parent = lo_element4 ). + IF ls_serie-idx IS NOT INITIAL. + lv_str = ls_serie-idx. + ELSE. + lv_str = sy-tabix - 1. + ENDIF. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_order + parent = lo_element4 ). + lv_str = ls_serie-order. + CONDENSE lv_str. + lo_element5->set_attribute_ns( name = 'val' + value = lv_str ). + IF ls_serie-sername IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_tx + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_v + parent = lo_element5 ). + lo_element6->set_value( value = ls_serie-sername ). + ENDIF. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_marker + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_symbol + parent = lo_element5 ). + lo_element6->set_attribute_ns( name = 'val' + value = ls_serie-symbol ). + IF ls_serie-lbl IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_cat + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_strref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-lbl ). + ENDIF. + IF ls_serie-ref IS NOT INITIAL. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_val + parent = lo_element4 ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_numref + parent = lo_element5 ). + lo_element7 = lo_document->create_simple_element( name = lc_xml_node_f + parent = lo_element6 ). + lo_element7->set_value( value = ls_serie-ref ). + ENDIF. + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_smooth + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_serie-smooth ). + ENDLOOP. + "endseries + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_dlbls + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showlegendkey + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showlegendkeyval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showval + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showvalval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showcatname + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showcatnameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showsername + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showsernameval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showpercent + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showpercentval ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_showbubblesize + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = lo_chartl->ns_showbubblesizeval ). + + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_marker + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->NS_MARKERVAL ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_smooth + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = lo_chartl->NS_SMOOTHVAL ). + + "axes + lo_el_rootchart = lo_element3. + LOOP AT lo_chartl->axes INTO ls_ax. + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_el_rootchart ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + CASE ls_ax-type. + WHEN zcl_excel_graph_line=>c_catax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_catax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). +* lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt +* parent = lo_element3 ). +* lo_element4->set_attribute_ns( name = 'formatCode' +* value = ls_ax-formatcode ). +* lo_element4->set_attribute_ns( name = 'sourceLinked' +* value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_auto + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-auto ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lblalgn + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lblalgn ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lbloffset + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-lbloffset ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_nomultilvllbl + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-nomultilvllbl ). + WHEN zcl_excel_graph_line=>c_valax. + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_valax + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axid + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axid ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_scaling + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_orientation + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'val' + value = ls_ax-orientation ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_delete + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-delete ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_axpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-axpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majorgridlines + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'formatCode' + value = ls_ax-formatcode ). + lo_element4->set_attribute_ns( name = 'sourceLinked' + value = ls_ax-sourcelinked ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_majortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-majortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_minortickmark + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-minortickmark ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_ticklblpos + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-ticklblpos ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossax + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossax ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crosses + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crosses ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_crossbetween + parent = lo_element3 ). + lo_element4->set_attribute_ns( name = 'val' + value = ls_ax-crossbetween ). + WHEN OTHERS. + ENDCASE. + ENDLOOP. + "endaxes + + WHEN OTHERS. + ENDCASE. + + "legend + IF lo_chart->print_label EQ abap_true. + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_legend + parent = lo_element ). + CASE io_drawing->graph_type. + WHEN zcl_excel_drawing=>c_graph_bars. + "----bar + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_legendpos + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartb->ns_legendposval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_overlay + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartb->ns_overlayval ). + WHEN zcl_excel_drawing=>c_graph_line. + "----line + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_legendpos + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartl->ns_legendposval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_overlay + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartl->ns_overlayval ). + WHEN zcl_excel_drawing=>c_graph_pie. + "----pie + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_legendpos + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartp->ns_legendposval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_layout + parent = lo_element2 ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_overlay + parent = lo_element2 ). + lo_element3->set_attribute_ns( name = 'val' + value = lo_chartp->ns_overlayval ). + lo_element3 = lo_document->create_simple_element( name = lc_xml_node_txpr + parent = lo_element2 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_bodypr + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_lststyle + parent = lo_element3 ). + lo_element4 = lo_document->create_simple_element( name = lc_xml_node_p + parent = lo_element3 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_ppr + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'rtl' + value = lo_chartp->ns_pprrtl ). + lo_element6 = lo_document->create_simple_element( name = lc_xml_node_defrpr + parent = lo_element5 ). + lo_element5 = lo_document->create_simple_element( name = lc_xml_node_endpararpr + parent = lo_element4 ). + lo_element5->set_attribute_ns( name = 'lang' + value = lo_chartp->ns_endpararprlang ). + WHEN OTHERS. + ENDCASE. + ENDIF. + + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_plotvisonly + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_plotvisonlyval ). + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_dispblanksas + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_dispblanksasval ). + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_showdlblsovermax + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'val' + value = lo_chart->ns_showdlblsovermaxval ). + "---------------------------END OF CHART + + "printSettings + lo_element = lo_document->create_simple_element( name = lc_xml_node_printsettings + parent = lo_element_root ). + "headerFooter + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_headerfooter + parent = lo_element ). + "pageMargins + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_pagemargins + parent = lo_element ). + lo_element2->set_attribute_ns( name = 'b' + value = lo_chart->pagemargins-b ). + lo_element2->set_attribute_ns( name = 'l' + value = lo_chart->pagemargins-l ). + lo_element2->set_attribute_ns( name = 'r' + value = lo_chart->pagemargins-r ). + lo_element2->set_attribute_ns( name = 't' + value = lo_chart->pagemargins-t ). + lo_element2->set_attribute_ns( name = 'header' + value = lo_chart->pagemargins-header ). + lo_element2->set_attribute_ns( name = 'footer' + value = lo_chart->pagemargins-footer ). + "pageSetup + lo_element2 = lo_document->create_simple_element( name = lc_xml_node_pagesetup + parent = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + + method CREATE_XL_DRAWINGS. + + +** Constant node name + CONSTANTS: lc_xml_node_wsdr TYPE string VALUE 'xdr:wsDr', + lc_xml_node_ns_xdr TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing', + lc_xml_node_ns_a TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/main'. + + CONSTANTS: lc_on TYPE string VALUE '1', + lc_off TYPE string VALUE '0'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element_cellanchor TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_drawings TYPE REF TO zcl_excel_drawings, + lo_drawing TYPE REF TO zcl_excel_drawing. + DATA: lv_rel_id TYPE i. + + + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_wsdr + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns:xdr' + value = lc_xml_node_ns_xdr ). + lo_element_root->set_attribute_ns( name = 'xmlns:a' + value = lc_xml_node_ns_a ). + +********************************************************************** +* STEP 4: Create drawings + + CLEAR: lv_rel_id. + + lo_drawings = io_worksheet->get_drawings( ). + + lo_iterator = lo_drawings->get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + ADD 1 TO lv_rel_id. + lo_element_cellanchor = me->create_xl_drawing_anchor( + io_drawing = lo_drawing + io_document = lo_document + ip_index = lv_rel_id ). + + lo_element_root->append_child( new_child = lo_element_cellanchor ). + + ENDWHILE. + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + + method CREATE_XL_DRAWINGS_RELS. + +** Constant node name + DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'Id', + lc_xml_attr_type TYPE string VALUE 'Type', + lc_xml_attr_target TYPE string VALUE 'Target', + " Node namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + lc_xml_node_rid_image_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + lc_xml_node_rid_chart_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_drawings TYPE REF TO zcl_excel_drawings, + lo_drawing TYPE REF TO zcl_excel_drawing. + + DATA: lv_value TYPE string, + lv_counter TYPE i. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + " Add sheet Relationship nodes here + lv_counter = 0. + lo_drawings = io_worksheet->get_drawings( ). + lo_iterator = lo_drawings->get_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + ADD 1 TO lv_counter. + + lv_value = lv_counter. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + + lv_value = lo_drawing->get_media_name( ). + CASE lo_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. + CONCATENATE '../media/' lv_value INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_image_tp ). + + WHEN zcl_excel_drawing=>type_chart. + CONCATENATE '../charts/' lv_value INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_chart_tp ). + + ENDCASE. + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + + + + method CREATE_XL_DRAWING_ANCHOR. + +** Constant node name + CONSTANTS: lc_xml_node_onecellanchor TYPE string VALUE 'xdr:oneCellAnchor', + lc_xml_node_twocellanchor TYPE string VALUE 'xdr:twoCellAnchor', + lc_xml_node_from TYPE string VALUE 'xdr:from', + lc_xml_node_to TYPE string VALUE 'xdr:to', + lc_xml_node_pic TYPE string VALUE 'xdr:pic', + lc_xml_node_ext TYPE string VALUE 'xdr:ext', + lc_xml_node_clientdata TYPE string VALUE 'xdr:clientData', + + lc_xml_node_col TYPE string VALUE 'xdr:col', + lc_xml_node_coloff TYPE string VALUE 'xdr:colOff', + lc_xml_node_row TYPE string VALUE 'xdr:row', + lc_xml_node_rowoff TYPE string VALUE 'xdr:rowOff', + + lc_xml_node_nvpicpr TYPE string VALUE 'xdr:nvPicPr', + lc_xml_node_cnvpr TYPE string VALUE 'xdr:cNvPr', + lc_xml_node_cnvpicpr TYPE string VALUE 'xdr:cNvPicPr', + lc_xml_node_piclocks TYPE string VALUE 'a:picLocks', + + lc_xml_node_sppr TYPE string VALUE 'xdr:spPr', + lc_xml_node_apgeom TYPE string VALUE 'a:prstGeom', + lc_xml_node_aavlst TYPE string VALUE 'a:avLst', + + lc_xml_node_graphicframe TYPE string VALUE 'xdr:graphicFrame', + lc_xml_node_nvgraphicframepr TYPE string VALUE 'xdr:nvGraphicFramePr', + lc_xml_node_cnvgraphicframepr TYPE string VALUE 'xdr:cNvGraphicFramePr', + lc_xml_node_graphicframelocks TYPE string VALUE 'a:graphicFrameLocks', + lc_xml_node_xfrm TYPE string VALUE 'xdr:xfrm', + lc_xml_node_aoff TYPE string VALUE 'a:off', + lc_xml_node_aext TYPE string VALUE 'a:ext', + lc_xml_node_agraphic TYPE string VALUE 'a:graphic', + lc_xml_node_agraphicdata TYPE string VALUE 'a:graphicData', + + lc_xml_node_ns_c TYPE string VALUE 'http://schemas.openxmlformats.org/drawingml/2006/chart', + lc_xml_node_cchart TYPE string VALUE 'c:chart', + + lc_xml_node_blipfill TYPE string VALUE 'xdr:blipFill', + lc_xml_node_ablip TYPE string VALUE 'a:blip', + lc_xml_node_astretch TYPE string VALUE 'a:stretch', + lc_xml_node_ns_r TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'. + + + CONSTANTS: lc_on TYPE string VALUE '1', + lc_off TYPE string VALUE '0'. + + DATA: lo_element_graphicframe TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_element2 TYPE REF TO if_ixml_element, + lo_element3 TYPE REF TO if_ixml_element, + lo_element_from TYPE REF TO if_ixml_element, + lo_element_to TYPE REF TO if_ixml_element, + lo_element_ext TYPE REF TO if_ixml_element, + lo_element_pic TYPE REF TO if_ixml_element, + lo_element_clientdata TYPE REF TO if_ixml_element, + + ls_position TYPE zexcel_drawing_position, + + lv_col TYPE string, " zexcel_cell_column, + lv_row TYPE string, " zexcel_cell_row. + lv_col_offset TYPE string, + lv_row_offset TYPE string, + lv_value TYPE string. + + ls_position = io_drawing->get_position( ). + + IF ls_position-anchor = 'ONE'. + ep_anchor = io_document->create_simple_element( name = lc_xml_node_onecellanchor + parent = io_document ). + ELSE. + ep_anchor = io_document->create_simple_element( name = lc_xml_node_twocellanchor + parent = io_document ). + ENDIF. + +* from cell ****************************** + lo_element_from = io_document->create_simple_element( name = lc_xml_node_from + parent = io_document ). + + lv_col = ls_position-from-col. + lv_row = ls_position-from-row. + lv_col_offset = ls_position-from-col_offset. + lv_row_offset = ls_position-from-row_offset. + CONDENSE lv_col NO-GAPS. + CONDENSE lv_row NO-GAPS. + CONDENSE lv_col_offset NO-GAPS. + CONDENSE lv_row_offset NO-GAPS. + + lo_element = io_document->create_simple_element( name = lc_xml_node_col + parent = io_document ). + lo_element->set_value( value = lv_col ). + lo_element_from->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_coloff + parent = io_document ). + lo_element->set_value( value = lv_col_offset ). + lo_element_from->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_row + parent = io_document ). + lo_element->set_value( value = lv_row ). + lo_element_from->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_rowoff + parent = io_document ). + lo_element->set_value( value = lv_row_offset ). + lo_element_from->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_from ). + + IF ls_position-anchor = 'ONE'. + +* ext ****************************** + lo_element_ext = io_document->create_simple_element( name = lc_xml_node_ext + parent = io_document ). + + lv_value = io_drawing->get_width_emu_str( ). + lo_element_ext->set_attribute_ns( name = 'cx' + value = lv_value ). + lv_value = io_drawing->get_height_emu_str( ). + lo_element_ext->set_attribute_ns( name = 'cy' + value = lv_value ). + ep_anchor->append_child( new_child = lo_element_ext ). + + ELSEIF ls_position-anchor = 'TWO'. + +* to cell ****************************** + lo_element_to = io_document->create_simple_element( name = lc_xml_node_to + parent = io_document ). + + lv_col = ls_position-to-col. + lv_row = ls_position-to-row. + lv_col_offset = ls_position-to-col_offset. + lv_row_offset = ls_position-to-row_offset. + CONDENSE lv_col NO-GAPS. + CONDENSE lv_row NO-GAPS. + CONDENSE lv_col_offset NO-GAPS. + CONDENSE lv_row_offset NO-GAPS. + + lo_element = io_document->create_simple_element( name = lc_xml_node_col + parent = io_document ). + lo_element->set_value( value = lv_col ). + lo_element_to->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_coloff + parent = io_document ). + lo_element->set_value( value = lv_col_offset ). + lo_element_to->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_row + parent = io_document ). + lo_element->set_value( value = lv_row ). + lo_element_to->append_child( new_child = lo_element ). + + lo_element = io_document->create_simple_element( name = lc_xml_node_rowoff + parent = io_document ). + lo_element->set_value( value = lv_row_offset ). + lo_element_to->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_to ). + + ENDIF. + + CASE io_drawing->get_type( ). + WHEN zcl_excel_drawing=>type_image. +* pic ********************************** + lo_element_pic = io_document->create_simple_element( name = lc_xml_node_pic + parent = io_document ). +* nvPicPr + lo_element = io_document->create_simple_element( name = lc_xml_node_nvpicpr + parent = io_document ). +* cNvPr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvpr + parent = io_document ). + lv_value = sy-index. + CONDENSE lv_value. + lo_element2->set_attribute_ns( name = 'id' + value = lv_value ). + lo_element2->set_attribute_ns( name = 'name' + value = io_drawing->title ). + lo_element->append_child( new_child = lo_element2 ). + +* cNvPicPr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvpicpr + parent = io_document ). + +* picLocks + lo_element3 = io_document->create_simple_element( name = lc_xml_node_piclocks + parent = io_document ). + lo_element3->set_attribute_ns( name = 'noChangeAspect' + value = '1' ). + + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_pic->append_child( new_child = lo_element ). + +* blipFill + lv_value = ip_index. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = io_document->create_simple_element( name = lc_xml_node_blipfill + parent = io_document ). + lo_element2 = io_document->create_simple_element( name = lc_xml_node_ablip + parent = io_document ). + lo_element2->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_ns_r ). + lo_element2->set_attribute_ns( name = 'r:embed' + value = lv_value ). + lo_element->append_child( new_child = lo_element2 ). + + lo_element2 = io_document->create_simple_element( name = lc_xml_node_astretch + parent = io_document ). + lo_element->append_child( new_child = lo_element2 ). + + lo_element_pic->append_child( new_child = lo_element ). + +* spPr + lo_element = io_document->create_simple_element( name = lc_xml_node_sppr + parent = io_document ). + + lo_element2 = io_document->create_simple_element( name = lc_xml_node_apgeom + parent = io_document ). + lo_element2->set_attribute_ns( name = 'prst' + value = 'rect' ). + lo_element3 = io_document->create_simple_element( name = lc_xml_node_aavlst + parent = io_document ). + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + + lo_element_pic->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_pic ). + WHEN zcl_excel_drawing=>type_chart. +* graphicFrame ********************************** + lo_element_graphicframe = io_document->create_simple_element( name = lc_xml_node_graphicframe + parent = io_document ). +* nvGraphicFramePr + lo_element = io_document->create_simple_element( name = lc_xml_node_nvgraphicframepr + parent = io_document ). +* cNvPr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvpr + parent = io_document ). + lv_value = sy-index. + CONDENSE lv_value. + lo_element2->set_attribute_ns( name = 'id' + value = lv_value ). + lo_element2->set_attribute_ns( name = 'name' + value = io_drawing->title ). + lo_element->append_child( new_child = lo_element2 ). +* cNvGraphicFramePr + lo_element2 = io_document->create_simple_element( name = lc_xml_node_cnvgraphicframepr + parent = io_document ). + lo_element3 = io_document->create_simple_element( name = lc_xml_node_graphicframelocks + parent = io_document ). + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_graphicframe->append_child( new_child = lo_element ). + +* xfrm + lo_element = io_document->create_simple_element( name = lc_xml_node_xfrm + parent = io_document ). +* off + lo_element2 = io_document->create_simple_element( name = lc_xml_node_aoff + parent = io_document ). + lo_element2->set_attribute_ns( name = 'y' value = '0' ). + lo_element2->set_attribute_ns( name = 'x' value = '0' ). + lo_element->append_child( new_child = lo_element2 ). +* ext + lo_element2 = io_document->create_simple_element( name = lc_xml_node_aext + parent = io_document ). + lo_element2->set_attribute_ns( name = 'cy' value = '0' ). + lo_element2->set_attribute_ns( name = 'cx' value = '0' ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_graphicframe->append_child( new_child = lo_element ). + +* graphic + lo_element = io_document->create_simple_element( name = lc_xml_node_agraphic + parent = io_document ). +* graphicData + lo_element2 = io_document->create_simple_element( name = lc_xml_node_agraphicdata + parent = io_document ). + lo_element2->set_attribute_ns( name = 'uri' value = lc_xml_node_ns_c ). + +* chart + lo_element3 = io_document->create_simple_element( name = lc_xml_node_cchart + parent = io_document ). + + lo_element3->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_ns_r ). + lo_element3->set_attribute_ns( name = 'xmlns:c' + value = lc_xml_node_ns_c ). + + lv_value = ip_index. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element3->set_attribute_ns( name = 'r:id' + value = lv_value ). + lo_element2->append_child( new_child = lo_element3 ). + lo_element->append_child( new_child = lo_element2 ). + lo_element_graphicframe->append_child( new_child = lo_element ). + ep_anchor->append_child( new_child = lo_element_graphicframe ). + + ENDCASE. + +* client data *************************** + lo_element_clientdata = io_document->create_simple_element( name = lc_xml_node_clientdata + parent = io_document ). + ep_anchor->append_child( new_child = lo_element_clientdata ). + + endmethod. + + + + method CREATE_XL_RELATIONSHIPS. + + +** Constant node name + DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'Id', + lc_xml_attr_type TYPE string VALUE 'Type', + lc_xml_attr_target TYPE string VALUE 'Target', + " Node namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#', + " Node type + lc_xml_node_rid_sheet_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', + lc_xml_node_rid_theme_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', + lc_xml_node_rid_styles_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + lc_xml_node_rid_shared_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', + " Node target + lc_xml_node_ridx_tg TYPE string VALUE 'worksheets/sheet#.xml', + lc_xml_node_rid_shared_tg TYPE string VALUE 'sharedStrings.xml', + lc_xml_node_rid_styles_tg TYPE string VALUE 'styles.xml', + lc_xml_node_rid_theme_tg TYPE string VALUE 'theme/theme1.xml'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_xml_node_ridx_tg TYPE string, + lv_xml_node_ridx_id TYPE string, + lv_size TYPE i, + lv_syindex(3) TYPE c. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + lv_size = excel->get_worksheets_size( ). + + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lv_size = lv_size + 1. + lv_syindex = lv_size. + shift lv_syindex RIGHT DELETING TRAILING space. + shift lv_syindex left DELETING leading space. + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + replace all occurrences of '#' in lv_xml_node_ridx_id with lv_syindex. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_xml_node_ridx_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_theme_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_theme_tg ). + lo_element_root->append_child( new_child = lo_element ). + + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lv_size = lv_size + 1. + lv_syindex = lv_size. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_xml_node_ridx_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_styles_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_styles_tg ). + lo_element_root->append_child( new_child = lo_element ). + + + + lv_size = excel->get_worksheets_size( ). + + DO lv_size TIMES. + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + lv_xml_node_ridx_tg = lc_xml_node_ridx_tg. + lv_syindex = sy-index. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_tg WITH lv_syindex. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_xml_node_ridx_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_sheet_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_xml_node_ridx_tg ). + lo_element_root->append_child( new_child = lo_element ). + ENDDO. + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + ADD 3 TO lv_size. + lv_syindex = lv_size. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_xml_node_ridx_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_shared_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_shared_tg ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + endmethod. + + + + METHOD create_xl_sharedstrings. + + +** Constant node name + DATA: lc_xml_node_sst TYPE string VALUE 'sst', + lc_xml_node_si TYPE string VALUE 'si', + lc_xml_node_t TYPE string VALUE 't', + " Node attributes + lc_xml_attr_count TYPE string VALUE 'count', + lc_xml_attr_uniquecount TYPE string VALUE 'uniqueCount', + " Node namespace + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_sub_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: lt_cell_data TYPE zexcel_t_cell_data_unsorted, + ls_shared_string TYPE zexcel_s_shared_string, + lv_value TYPE string, + lv_count_str TYPE string, + lv_uniquecount_str TYPE string, + lv_sytabix TYPE sytabix, + lv_count TYPE i, + lv_uniquecount TYPE i. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data, + <fs_sheet_string> TYPE zexcel_s_shared_string. + +********************************************************************** +* STEP 1: Collect strings from each worksheet + lo_iterator = excel->get_worksheets_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + APPEND LINES OF lo_worksheet->sheet_content TO lt_cell_data. + ENDWHILE. + + DELETE lt_cell_data WHERE cell_formula IS NOT INITIAL. " delete formula content + + DESCRIBE TABLE lt_cell_data LINES lv_count. + MOVE lv_count TO lv_count_str. + + SHIFT lv_count_str RIGHT DELETING TRAILING space. + SHIFT lv_count_str LEFT DELETING LEADING space. + + SORT lt_cell_data BY cell_value. + DELETE ADJACENT DUPLICATES FROM lt_cell_data COMPARING cell_value. + + DESCRIBE TABLE lt_cell_data LINES lv_uniquecount. + MOVE lv_uniquecount TO lv_uniquecount_str. + + SHIFT lv_uniquecount_str RIGHT DELETING TRAILING space. + SHIFT lv_uniquecount_str LEFT DELETING LEADING space. + + clear lv_count. + LOOP AT lt_cell_data ASSIGNING <fs_sheet_content> where data_type = 's'. +* lv_sytabix = sy-tabix - 1. + lv_sytabix = lv_count. + MOVE lv_sytabix TO ls_shared_string-string_no. + MOVE <fs_sheet_content>-cell_value TO ls_shared_string-string_value. + MOVE <fs_sheet_content>-data_type TO ls_shared_string-string_type. + APPEND ls_shared_string TO shared_strings. + add 1 to lv_count. + ENDLOOP. + + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_sst + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_count + value = lv_count_str ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_uniquecount + value = lv_uniquecount_str ). + +********************************************************************** +* STEP 4: Create subnode + LOOP AT shared_strings ASSIGNING <fs_sheet_string>. + lo_element = lo_document->create_simple_element( name = lc_xml_node_si + parent = lo_document ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_t + parent = lo_document ). +* if <fs_sheet_string>-string_type EQ 's_leading_blanks'. + IF <fs_sheet_string>-string_value IS NOT INITIAL AND <fs_sheet_string>-string_value(1) EQ ` `. + lo_sub_element->set_attribute( name = 'space' namespace = 'xml' value = 'preserve' ). + ENDIF. + lo_sub_element->set_value( value = <fs_sheet_string>-string_value ). + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + ENDLOOP. + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + + + + + METHOD create_xl_sheet. +*--------------------------------------------------------------------* +* issue #330 - Adding ColorScale conditional formatting +* - Ivan Femia, 2014-08-25 +*--------------------------------------------------------------------* + + TYPES: BEGIN OF colors, + colorrgb TYPE zexcel_color, + END OF colors. + +*--------------------------------------------------------------------* +* issue #237 - Error writing column-style +* - Stefan Schmoecker, 2012-11-01 +*--------------------------------------------------------------------* + + TYPES: BEGIN OF cfvo, + value TYPE zexcel_conditional_value, + type TYPE zexcel_conditional_type, + END OF cfvo. + +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 1 - start +*--------------------------------------------------------------------* + TYPES: BEGIN OF lty_table_area, + left TYPE i, + right TYPE i, + top TYPE i, + bottom TYPE i, + END OF lty_table_area. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 1 - end +*--------------------------------------------------------------------* +** Constants + CONSTANTS: + lc_dummy_cell_content TYPE zexcel_s_cell_data-cell_value VALUE '})~~~ This is a dummy value for ABAP2XLSX and you should never find this in a real excelsheet Ihope'. + + +** Constant node name + DATA: lc_xml_node_worksheet TYPE string VALUE 'worksheet', + lc_xml_node_sheetpr TYPE string VALUE 'sheetPr', + lc_xml_node_tabcolor TYPE string VALUE 'tabColor', + lc_xml_node_outlinepr TYPE string VALUE 'outlinePr', + lc_xml_node_dimension TYPE string VALUE 'dimension', + lc_xml_node_sheetviews TYPE string VALUE 'sheetViews', + lc_xml_node_sheetview TYPE string VALUE 'sheetView', + lc_xml_node_selection TYPE string VALUE 'selection', + lc_xml_node_pane TYPE string VALUE 'pane', + lc_xml_node_sheetformatpr TYPE string VALUE 'sheetFormatPr', + lc_xml_node_cols TYPE string VALUE 'cols', + lc_xml_node_col TYPE string VALUE 'col', +* lc_xml_node_sheetdata TYPE string VALUE 'sheetData', +* lc_xml_node_row TYPE string VALUE 'row', +* lc_xml_node_c TYPE string VALUE 'c', +* lc_xml_node_v TYPE string VALUE 'v', +* lc_xml_node_f TYPE string VALUE 'f', + lc_xml_node_sheetprotection TYPE string VALUE 'sheetProtection', + lc_xml_node_pagemargins TYPE string VALUE 'pageMargins', + lc_xml_node_pagesetup TYPE string VALUE 'pageSetup', + lc_xml_node_pagesetuppr TYPE string VALUE 'pageSetUpPr', + lc_xml_node_condformatting TYPE string VALUE 'conditionalFormatting', + lc_xml_node_cfrule TYPE string VALUE 'cfRule', + lc_xml_node_color TYPE string VALUE 'color', " Databar by Albert Lladanosa + lc_xml_node_databar TYPE string VALUE 'dataBar', " Databar by Albert Lladanosa + lc_xml_node_colorscale TYPE string VALUE 'colorScale', + lc_xml_node_iconset TYPE string VALUE 'iconSet', + lc_xml_node_cfvo TYPE string VALUE 'cfvo', + lc_xml_node_formula TYPE string VALUE 'formula', + lc_xml_node_datavalidations TYPE string VALUE 'dataValidations', + lc_xml_node_datavalidation TYPE string VALUE 'dataValidation', + lc_xml_node_formula1 TYPE string VALUE 'formula1', + lc_xml_node_formula2 TYPE string VALUE 'formula2', + lc_xml_node_mergecell TYPE string VALUE 'mergeCell', + lc_xml_node_mergecells TYPE string VALUE 'mergeCells', + lc_xml_node_drawing TYPE string VALUE 'drawing', + lc_xml_node_headerfooter TYPE string VALUE 'headerFooter', + lc_xml_node_oddheader TYPE string VALUE 'oddHeader', + lc_xml_node_oddfooter TYPE string VALUE 'oddFooter', + lc_xml_node_evenheader TYPE string VALUE 'evenHeader', + lc_xml_node_evenfooter TYPE string VALUE 'evenFooter', + lc_xml_node_autofilter TYPE string VALUE 'autoFilter', + lc_xml_node_filtercolumn TYPE string VALUE 'filterColumn', + lc_xml_node_filters TYPE string VALUE 'filters', + lc_xml_node_filter TYPE string VALUE 'filter', + " Node attributes + lc_xml_attr_ref TYPE string VALUE 'ref', + lc_xml_attr_summarybelow TYPE string VALUE 'summaryBelow', + lc_xml_attr_summaryright TYPE string VALUE 'summaryRight', + lc_xml_attr_tabselected TYPE string VALUE 'tabSelected', + lc_xml_attr_showzeros TYPE string VALUE 'showZeros', + lc_xml_attr_zoomscale TYPE string VALUE 'zoomScale', + lc_xml_attr_zoomscalenormal TYPE string VALUE 'zoomScaleNormal', + lc_xml_attr_zoomscalepageview TYPE string VALUE 'zoomScalePageLayoutView', + lc_xml_attr_zoomscalesheetview TYPE string VALUE 'zoomScaleSheetLayoutView', + lc_xml_attr_workbookviewid TYPE string VALUE 'workbookViewId', + lc_xml_attr_showgridlines TYPE string VALUE 'showGridLines', + lc_xml_attr_gridlines TYPE string VALUE 'gridLines', + lc_xml_attr_showrowcolheaders TYPE string VALUE 'showRowColHeaders', + lc_xml_attr_activecell TYPE string VALUE 'activeCell', + lc_xml_attr_sqref TYPE string VALUE 'sqref', + lc_xml_attr_min TYPE string VALUE 'min', + lc_xml_attr_max TYPE string VALUE 'max', + lc_xml_attr_hidden TYPE string VALUE 'hidden', + lc_xml_attr_width TYPE string VALUE 'width', + lc_xml_attr_defaultwidth TYPE string VALUE '9.10', + lc_xml_attr_style TYPE string VALUE 'style', + lc_xml_attr_true TYPE string VALUE 'true', + lc_xml_attr_bestfit TYPE string VALUE 'bestFit', + lc_xml_attr_customheight TYPE string VALUE 'customHeight', + lc_xml_attr_customwidth TYPE string VALUE 'customWidth', + lc_xml_attr_collapsed TYPE string VALUE 'collapsed', + lc_xml_attr_defaultrowheight TYPE string VALUE 'defaultRowHeight', + lc_xml_attr_defaultcolwidth TYPE string VALUE 'defaultColWidth', + lc_xml_attr_outlinelevelrow TYPE string VALUE 'x14ac:outlineLevelRow', + lc_xml_attr_outlinelevelcol TYPE string VALUE 'x14ac:outlineLevelCol', + lc_xml_attr_outlinelevel TYPE string VALUE 'outlineLevel', +* lc_xml_attr_r TYPE string VALUE 'r', +* lc_xml_attr_s TYPE string VALUE 's', +* lc_xml_attr_spans TYPE string VALUE 'spans', +* lc_xml_attr_t TYPE string VALUE 't', + lc_xml_attr_password TYPE string VALUE 'password', + lc_xml_attr_sheet TYPE string VALUE 'sheet', + lc_xml_attr_objects TYPE string VALUE 'objects', + lc_xml_attr_scenarios TYPE string VALUE 'scenarios', + lc_xml_attr_autofilter TYPE string VALUE 'autoFilter', + lc_xml_attr_deletecolumns TYPE string VALUE 'deleteColumns', + lc_xml_attr_deleterows TYPE string VALUE 'deleteRows', + lc_xml_attr_formatcells TYPE string VALUE 'formatCells', + lc_xml_attr_formatcolumns TYPE string VALUE 'formatColumns', + lc_xml_attr_formatrows TYPE string VALUE 'formatRows', + lc_xml_attr_insertcolumns TYPE string VALUE 'insertColumns', + lc_xml_attr_inserthyperlinks TYPE string VALUE 'insertHyperlinks', + lc_xml_attr_insertrows TYPE string VALUE 'insertRows', + lc_xml_attr_pivottables TYPE string VALUE 'pivotTables', + lc_xml_attr_selectlockedcells TYPE string VALUE 'selectLockedCells', + lc_xml_attr_selectunlockedcell TYPE string VALUE 'selectUnlockedCells', + lc_xml_attr_sort TYPE string VALUE 'sort', + lc_xml_attr_left TYPE string VALUE 'left', + lc_xml_attr_right TYPE string VALUE 'right', + lc_xml_attr_top TYPE string VALUE 'top', + lc_xml_attr_bottom TYPE string VALUE 'bottom', + lc_xml_attr_header TYPE string VALUE 'header', + lc_xml_attr_footer TYPE string VALUE 'footer', + lc_xml_attr_type TYPE string VALUE 'type', + lc_xml_attr_iconset TYPE string VALUE 'iconSet', + lc_xml_attr_showvalue TYPE string VALUE 'showValue', + lc_xml_attr_val TYPE string VALUE 'val', + lc_xml_attr_dxfid TYPE string VALUE 'dxfId', + lc_xml_attr_priority TYPE string VALUE 'priority', + lc_xml_attr_operator TYPE string VALUE 'operator', + lc_xml_attr_allowblank TYPE string VALUE 'allowBlank', + lc_xml_attr_showinputmessage TYPE string VALUE 'showInputMessage', + lc_xml_attr_showerrormessage TYPE string VALUE 'showErrorMessage', + lc_xml_attr_showdropdown TYPE string VALUE 'showDropDown', + lc_xml_attr_errortitle TYPE string VALUE 'errorTitle', + lc_xml_attr_error TYPE string VALUE 'error', + lc_xml_attr_prompttitle TYPE string VALUE 'promptTitle', + lc_xml_attr_prompt TYPE string VALUE 'prompt', + lc_xml_attr_count TYPE string VALUE 'count', + lc_xml_attr_blackandwhite TYPE string VALUE 'blackAndWhite', + lc_xml_attr_cellcomments TYPE string VALUE 'cellComments', + lc_xml_attr_copies TYPE string VALUE 'copies', + lc_xml_attr_draft TYPE string VALUE 'draft', + lc_xml_attr_errors TYPE string VALUE 'errors', + lc_xml_attr_firstpagenumber TYPE string VALUE 'firstPageNumber', + lc_xml_attr_fittopage TYPE string VALUE 'fitToPage', + lc_xml_attr_fittoheight TYPE string VALUE 'fitToHeight', + lc_xml_attr_fittowidth TYPE string VALUE 'fitToWidth', + lc_xml_attr_horizontaldpi TYPE string VALUE 'horizontalDpi', + lc_xml_attr_orientation TYPE string VALUE 'orientation', + lc_xml_attr_pageorder TYPE string VALUE 'pageOrder', + lc_xml_attr_paperheight TYPE string VALUE 'paperHeight', + lc_xml_attr_papersize TYPE string VALUE 'paperSize', + lc_xml_attr_paperwidth TYPE string VALUE 'paperWidth', + lc_xml_attr_scale TYPE string VALUE 'scale', + lc_xml_attr_usefirstpagenumber TYPE string VALUE 'useFirstPageNumber', + lc_xml_attr_useprinterdefaults TYPE string VALUE 'usePrinterDefaults', + lc_xml_attr_verticaldpi TYPE string VALUE 'verticalDpi', + lc_xml_attr_differentoddeven TYPE string VALUE 'differentOddEven', + lc_xml_attr_colid TYPE string VALUE 'colId', + lc_xml_attr_filtermode TYPE string VALUE 'filterMode', + lc_xml_attr_tabcolor_rgb TYPE string VALUE 'rgb', + lc_xml_attr_tabcolor_theme TYPE string VALUE 'theme', + " Node namespace + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + lc_xml_node_r_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + lc_xml_node_comp_ns TYPE string VALUE 'http://schemas.openxmlformats.org/markup-compatibility/2006', + lc_xml_node_comp_pref TYPE string VALUE 'x14ac', + lc_xml_node_ig_ns TYPE string VALUE 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_element_2 TYPE REF TO if_ixml_element, + lo_element_3 TYPE REF TO if_ixml_element, + lo_element_4 TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_table TYPE REF TO zcl_excel_table, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + lo_row_dim_empty TYPE REF TO zcl_excel_worksheet_rowdimensi, + default_col_dimension TYPE REF TO zcl_excel_worksheet_columndime, + default_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + + DATA: lv_value TYPE string, + lt_range_merge TYPE string_table, + lv_merge TYPE string, + lv_column_p TYPE zexcel_cell_column_alpha, + lv_column TYPE zexcel_cell_column, + lv_cell_value TYPE zexcel_cell_value, + lv_style_guid TYPE zexcel_cell_style, + lv_flag TYPE c, + ls_databar TYPE zexcel_conditional_databar, " Databar by Albert Lladanosa + ls_colorscale TYPE zexcel_conditional_colorscale, + ls_iconset TYPE zexcel_conditional_iconset, + ls_cellis TYPE zexcel_conditional_cellis, + ls_expression TYPE zexcel_conditional_expression, + ls_conditional_top10 TYPE zexcel_conditional_top10, + ls_conditional_above_avg TYPE zexcel_conditional_above_avg, + lt_cfvo TYPE TABLE OF cfvo, + ls_cfvo TYPE cfvo, + lt_colors TYPE TABLE OF colors, + ls_colors TYPE colors, + lv_cell_row_s TYPE string, + ls_last_row TYPE zexcel_s_cell_data, + ls_style_mapping TYPE zexcel_s_styles_mapping, + lv_freeze_cell_row TYPE zexcel_cell_row, + lv_freeze_cell_column TYPE zexcel_cell_column, + lv_freeze_cell_column_alpha TYPE zexcel_cell_column_alpha, + column_dimensions TYPE zexcel_t_worksheet_columndime, + row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + lv_relation_id TYPE i VALUE 0, + outline_level_row TYPE i VALUE 0, + outline_level_col TYPE i VALUE 0, + lv_current_row TYPE i, + lv_next_row TYPE i, + ls_sheet_content LIKE LINE OF io_worksheet->sheet_content, + ls_sheet_content_empty LIKE LINE OF io_worksheet->sheet_content, + lv_last_row TYPE i, + lts_row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + lts_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + col_count TYPE int4, + merge_count TYPE int4, + write_current_row TYPE boolean, + lt_values TYPE zexcel_t_autofilter_values, + ls_values TYPE zexcel_s_autofilter_values, +* lv_guid TYPE uuid, + lo_autofilters TYPE REF TO zcl_excel_autofilters, + lo_autofilter TYPE REF TO zcl_excel_autofilter, + l_autofilter_hidden TYPE flag, + ls_area TYPE zexcel_s_autofilter_area, + lv_ref TYPE string, + lv_style_index TYPE i. " issue #237 + + + + FIELD-SYMBOLS: <ls_sheet_content> TYPE zexcel_s_cell_data, + <fs_range_merge> LIKE LINE OF lt_range_merge, + <column_dimension> TYPE zexcel_s_worksheet_columndime, + <row_dimension> TYPE zexcel_s_worksheet_rowdimensio, + <ls_row_outline> LIKE LINE OF lts_row_outlines. + +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 2 - start +*--------------------------------------------------------------------* + DATA: lt_table_areas TYPE SORTED TABLE OF lty_table_area WITH NON-UNIQUE KEY left right top bottom, + ls_table_area LIKE LINE OF lt_table_areas. +*--------------------------------------------------------------------* +* issue #220 - If cell in tables-area don't use default from row or column or sheet - Declarations 2 - end +*--------------------------------------------------------------------* + + + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_worksheet + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_r_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:mc' + value = lc_xml_node_comp_ns ). + lo_element_root->set_attribute_ns( name = 'mc:Ignorable' + value = lc_xml_node_comp_pref ). + lo_element_root->set_attribute_ns( name = 'xmlns:x14ac' + value = lc_xml_node_ig_ns ). + + +********************************************************************** +* STEP 4: Create subnodes + " sheetPr + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetpr + parent = lo_document ). + " TODO tabColor + IF io_worksheet->tabcolor IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_tabcolor + parent = lo_element ). +* Theme not supported yet - start with RGB + lv_value = io_worksheet->tabcolor-rgb. + lo_element_2->set_attribute_ns( name = lc_xml_attr_tabcolor_rgb + value = lv_value ). + ENDIF. + + " outlinePr + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_outlinepr + parent = lo_document ). + + lv_value = io_worksheet->zif_excel_sheet_properties~summarybelow. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_summarybelow + value = lv_value ). + + lv_value = io_worksheet->zif_excel_sheet_properties~summaryright. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_summaryright + value = lv_value ). + + lo_element->append_child( new_child = lo_element_2 ). + + IF io_worksheet->sheet_setup->fit_to_page IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_pagesetuppr + parent = lo_document ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_fittopage + value = `1` ). + lo_element->append_child( new_child = lo_element_2 ). " pageSetupPr node + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). + + " dimension node + lo_element = lo_document->create_simple_element( name = lc_xml_node_dimension + parent = lo_document ). + lv_value = io_worksheet->get_dimension_range( ). + lo_element->set_attribute_ns( name = lc_xml_attr_ref + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " sheetViews node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetviews + parent = lo_document ). + " sheetView node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_sheetview + parent = lo_document ). + IF io_worksheet->zif_excel_sheet_properties~show_zeros EQ abap_false. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showzeros + value = '0' ). + ENDIF. + IF iv_active = abap_true + OR io_worksheet->zif_excel_sheet_properties~selected EQ abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_tabselected + value = '1' ). + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_tabselected + value = '0' ). + ENDIF. + " Zoom scale + IF io_worksheet->zif_excel_sheet_properties~zoomscale GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscale + value = lv_value ). + IF io_worksheet->zif_excel_sheet_properties~zoomscale_normal NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_normal GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_normal = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_normal LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_normal = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale_normal. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscalenormal + value = lv_value ). + ENDIF. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale_pagelayoutview. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscalepageview + value = lv_value ). + ENDIF. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview NE 0. + IF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview GT 400. + io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview = 400. + ELSEIF io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview LT 10. + io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview = 10. + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_properties~zoomscale_sheetlayoutview. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_zoomscalesheetview + value = lv_value ). + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_workbookviewid + value = '0' ). + " showGridLines attribute + IF io_worksheet->show_gridlines = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showgridlines + value = '1' ). + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showgridlines + value = '0' ). + ENDIF. + + " showRowColHeaders attribute + IF io_worksheet->show_rowcolheaders = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showrowcolheaders + value = '1' ). + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showrowcolheaders + value = '0' ). + ENDIF. + + + " freeze panes + io_worksheet->get_freeze_cell( IMPORTING ep_row = lv_freeze_cell_row + ep_column = lv_freeze_cell_column ). + + IF lv_freeze_cell_row IS NOT INITIAL AND lv_freeze_cell_column IS NOT INITIAL. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_pane + parent = lo_element_2 ). + + IF lv_freeze_cell_row > 1. + lv_value = lv_freeze_cell_row - 1. + CONDENSE lv_value. + lo_element_3->set_attribute_ns( name = 'ySplit' + value = lv_value ). + ENDIF. + + IF lv_freeze_cell_column > 1. + lv_value = lv_freeze_cell_column - 1. + CONDENSE lv_value. + lo_element_3->set_attribute_ns( name = 'xSplit' + value = lv_value ). + ENDIF. + + lv_freeze_cell_column_alpha = zcl_excel_common=>convert_column2alpha( ip_column = lv_freeze_cell_column ). + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_freeze_cell_row ). + CONCATENATE lv_freeze_cell_column_alpha lv_value INTO lv_value. + lo_element_3->set_attribute_ns( name = 'topLeftCell' + value = lv_value ). + + lo_element_3->set_attribute_ns( name = 'activePane' + value = 'bottomRight' ). + + lo_element_3->set_attribute_ns( name = 'state' + value = 'frozen' ). + + lo_element_2->append_child( new_child = lo_element_3 ). + ENDIF. + " selection node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_selection + parent = lo_document ). + lv_value = io_worksheet->get_active_cell( ). + lo_element_3->set_attribute_ns( name = lc_xml_attr_activecell + value = lv_value ). + + lo_element_3->set_attribute_ns( name = lc_xml_attr_sqref + value = lv_value ). + + lo_element_2->append_child( new_child = lo_element_3 ). " sheetView node + + lo_element->append_child( new_child = lo_element_2 ). " sheetView node + + lo_element_root->append_child( new_child = lo_element ). " sheetViews node + + + column_dimensions[] = io_worksheet->get_column_dimensions( ). + " Calculate col + IF NOT column_dimensions IS INITIAL. + io_worksheet->calculate_column_widths( ). + column_dimensions[] = io_worksheet->get_column_dimensions( ). + ENDIF. + row_dimensions[] = io_worksheet->get_row_dimensions( ). + " sheetFormatPr node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetformatpr + parent = lo_document ). + " defaultRowHeight + default_row_dimension = io_worksheet->get_default_row_dimension( ). + IF default_row_dimension IS BOUND. + IF default_row_dimension->get_row_height( ) >= 0. + lo_element->set_attribute_ns( name = lc_xml_attr_customheight + value = lc_xml_attr_true ). + lv_value = default_row_dimension->get_row_height( ). + ELSE. + lv_value = '12.75'. + ENDIF. + ELSE. + lv_value = '12.75'. + ENDIF. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_defaultrowheight + value = lv_value ). + " defaultColWidth + default_col_dimension = io_worksheet->get_default_column_dimension( ). + IF default_col_dimension IS BOUND. + IF default_col_dimension->get_width( ) >= 0. + lv_value = default_col_dimension->get_width( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_defaultcolwidth + value = lv_value ). + ENDIF. + ENDIF. + " outlineLevelRow +* Excel is recalculating the outlinelevel on startup from the outline levels found in the rows +* If we place anything incorrect here it gets corrected, if don't place anything it gets added +* So no need to calculate the outlinelevel here ( at least for rows - probably for columns as well but I haven't tested yet +* LOOP AT row_dimensions ASSIGNING <row_dimension>. +* IF <row_dimension>-row_dimension->get_outline_level( ) > outline_level_row. +* outline_level_row = <row_dimension>-row_dimension->get_outline_level( ). +* ENDIF. +* ENDLOOP. +* lv_value = outline_level_row. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element->set_attribute_ns( name = lc_xml_attr_outlinelevelrow +* value = lv_value ). + " outlineLevelCol + LOOP AT column_dimensions ASSIGNING <column_dimension>. + IF <column_dimension>-column_dimension->get_outline_level( ) > outline_level_col. + outline_level_col = <column_dimension>-column_dimension->get_outline_level( ). + ENDIF. + ENDLOOP. + lv_value = outline_level_col. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_outlinelevelcol + value = lv_value ). +* lv_value = 0. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element->set_attribute_ns( name = lc_xml_attr_dydescent +* value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). " sheetFormatPr node + + IF io_worksheet->zif_excel_sheet_properties~get_style( ) IS NOT INITIAL OR NOT column_dimensions IS INITIAL. + " cols node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cols + parent = lo_document ). + " This code have to be enhanced in order to manage also column style properties + " Now it is an out/out + IF NOT column_dimensions IS INITIAL. + LOOP AT column_dimensions ASSIGNING <column_dimension>. + " col node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_col + parent = lo_document ). + lv_value = <column_dimension>-column_dimension->get_column_index( ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_min + value = lv_value ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_max + value = lv_value ). + " Width + IF <column_dimension>-column_dimension->get_width( ) < 0. + lo_element_2->set_attribute_ns( name = lc_xml_attr_width + value = lc_xml_attr_defaultwidth ). + ELSE. + lv_value = <column_dimension>-column_dimension->get_width( ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_width + value = lv_value ). + ENDIF. + " Column visibility + IF <column_dimension>-column_dimension->get_visible( ) = abap_false. + lo_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = lc_xml_attr_true ). + ENDIF. + " Auto size? + IF <column_dimension>-column_dimension->get_auto_size( ) = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_bestfit + value = lc_xml_attr_true ). + ENDIF. + " Custom width? + IF default_col_dimension IS BOUND. + IF <column_dimension>-column_dimension->get_width( ) + <> default_col_dimension->get_width( ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_customwidth + value = lc_xml_attr_true ). + + ENDIF. + ELSE. + lo_element_2->set_attribute_ns( name = lc_xml_attr_customwidth + value = lc_xml_attr_true ). + ENDIF. + " Collapsed + IF <column_dimension>-column_dimension->get_collapsed( ) = abap_true. + lo_element_2->set_attribute_ns( name = lc_xml_attr_collapsed + value = lc_xml_attr_true ). + ENDIF. + " outlineLevel + IF <column_dimension>-column_dimension->get_outline_level( ) > 0. + lv_value = <column_dimension>-column_dimension->get_outline_level( ). + + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_outlinelevel + value = lv_value ). + ENDIF. + " Style +* lv_value = <column_dimension>-column_dimension->get_xf_index( ). "del issue #157 - set column style + lv_style_guid = <column_dimension>-column_dimension->get_column_style_guid( ). "ins issue #157 - set column style +* lv_value = me->excel->get_style_index_in_styles( lv_style_guid ). "del issue #237 + CLEAR ls_style_mapping. + READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. +* lv_style_index = ls_style_mapping-style. "del issue #295 +* IF lv_style_index > 0. "ins issue #237 - del issue #295 +* lv_value = lv_style_index - 1. "ins issue #237 - del issue #295 + IF sy-subrc = 0. "ins issue #295 + lv_value = ls_style_mapping-style. "ins issue #295 + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. "ins issue #237 + + lo_element->append_child( new_child = lo_element_2 ). " col node + ENDLOOP. +* ELSE. "del issue #157 - set sheet style ( add missing columns +* IF io_worksheet->zif_excel_sheet_properties~get_style( ) IS NOT INITIAL. "del issue #157 - set sheet style ( add missing columns +* Begin of insertion issue #157 - set sheet style ( add missing columns + ENDIF. +* Always pass through this coding + IF io_worksheet->zif_excel_sheet_properties~get_style( ) IS NOT INITIAL. + DATA: lts_sorted_columns TYPE SORTED TABLE OF zexcel_cell_column WITH UNIQUE KEY table_line. + TYPES: BEGIN OF ty_missing_columns, + first_column TYPE zexcel_cell_column, + last_column TYPE zexcel_cell_column, + END OF ty_missing_columns. + DATA: t_missing_columns TYPE STANDARD TABLE OF ty_missing_columns WITH NON-UNIQUE DEFAULT KEY, + missing_column LIKE LINE OF t_missing_columns. + +* First collect columns that were already handled before. The rest has to be inserted now + LOOP AT column_dimensions ASSIGNING <column_dimension>. + lv_column = zcl_excel_common=>convert_column2int( <column_dimension>-column ). + INSERT lv_column INTO TABLE lts_sorted_columns. + ENDLOOP. + +* Now find all columns that were missing so far + missing_column-first_column = 1. + LOOP AT lts_sorted_columns INTO lv_column. + IF lv_column > missing_column-first_column. + missing_column-last_column = lv_column - 1. + APPEND missing_column TO t_missing_columns. + ENDIF. + missing_column-first_column = lv_column + 1. + ENDLOOP. + missing_column-last_column = zcl_excel_common=>c_excel_sheet_max_col. + APPEND missing_column TO t_missing_columns. +* Now apply stylesetting ( and other defaults - I copy it from above. Whoever programmed that seems to know what to do :o) + LOOP AT t_missing_columns INTO missing_column. +* End of insertion issue #157 - set column style + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_col + parent = lo_document ). +* lv_value = zcl_excel_common=>c_excel_sheet_min_col."del issue #157 - set sheet style ( add missing columns + lv_value = missing_column-first_column. "ins issue #157 - set sheet style ( add missing columns + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_min + value = lv_value ). +* lv_value = zcl_excel_common=>c_excel_sheet_max_col."del issue #157 - set sheet style ( add missing columns + lv_value = missing_column-last_column. "ins issue #157 - set sheet style ( add missing columns + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_max + value = lv_value ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_width + value = lc_xml_attr_defaultwidth ). + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. + lv_value = ls_style_mapping-style. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). " col node + ENDLOOP. "ins issue #157 - set sheet style ( add missing columns + + ENDIF. +*--------------------------------------------------------------------* +* issue #367 add feature hide columns from +*--------------------------------------------------------------------* + IF io_worksheet->zif_excel_sheet_properties~hide_columns_from IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_col + parent = lo_document ). + lv_value = zcl_excel_common=>convert_column2int( io_worksheet->zif_excel_sheet_properties~hide_columns_from ). + CONDENSE lv_value NO-GAPS. + lo_element_2->set_attribute_ns( name = lc_xml_attr_min + value = lv_value ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_max + value = '16384' ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = '1' ). + lo_element->append_child( new_child = lo_element_2 ). " col node + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). " cols node + ENDIF. + +*--------------------------------------------------------------------* +* Sheet content - use own method to create this +*--------------------------------------------------------------------* + lo_element = create_xl_sheet_sheet_data( io_worksheet = io_worksheet + io_document = lo_document + it_column_dimensions = column_dimensions ) . +* " sheetData node +* lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetdata +* parent = lo_document ). +* " Get column count +* col_count = io_worksheet->get_highest_column( ). +* " Get autofilter +** lv_guid = io_worksheet->get_guid( ) . + lo_autofilters = excel->get_autofilters_reference( ). + lo_autofilter = lo_autofilters->get( io_worksheet = io_worksheet ) . +* IF lo_autofilter IS BOUND. +* lt_values = lo_autofilter->get_values( ) . +* ls_area = lo_autofilter->get_filter_area( ) . +* l_autofilter_hidden = abap_true. " First defautl is not showing +* ENDIF. +**--------------------------------------------------------------------* +** issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 1 - start +**--------------------------------------------------------------------* +** Build table to hold all table-areas attached to this sheet +* lo_iterator = io_worksheet->get_tables_iterator( ). +* WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. +* lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). +* ls_table_area-left = zcl_excel_common=>convert_column2int( lo_table->settings-top_left_column ). +* ls_table_area-right = lo_table->get_right_column_integer( ). +* ls_table_area-top = lo_table->settings-top_left_row. +* ls_table_area-bottom = lo_table->get_bottom_row_integer( ). +* INSERT ls_table_area INTO TABLE lt_table_areas. +* ENDWHILE. +**--------------------------------------------------------------------* +** issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 1 - end +**--------------------------------------------------------------------* +** We have problems when the first rows or trailing rows are not set but we have rowinformation +** to solve this we add dummycontent into first and last line that will not be set +** Set first line if necessary +* READ TABLE io_worksheet->sheet_content TRANSPORTING NO FIELDS WITH KEY cell_row = 1. +* IF sy-subrc <> 0. +* ls_sheet_content_empty-cell_row = 1. +* ls_sheet_content_empty-cell_column = 1. +* ls_sheet_content_empty-cell_value = lc_dummy_cell_content. +* INSERT ls_sheet_content_empty INTO TABLE io_worksheet->sheet_content. +* ENDIF. +** Set last line if necessary +** Last row with cell content +* lv_last_row = io_worksheet->get_highest_row( ). +** Last line with row-information set directly ( like line height, hidden-status ... ) +* lts_row_dimensions = io_worksheet->get_row_dimensions( ). +* SORT lts_row_dimensions BY row DESCENDING. +* READ TABLE lts_row_dimensions INDEX 1 ASSIGNING <row_dimension>. +* IF sy-subrc = 0 AND <row_dimension>-row > lv_last_row. +* lv_last_row = <row_dimension>-row. +* ENDIF. +** Last line with row-information set indirectly by row outline +* lts_row_outlines = io_worksheet->get_row_outlines( ). +* LOOP AT lts_row_outlines ASSIGNING <ls_row_outline>. +* IF <ls_row_outline>-collapsed = 'X'. +* lv_current_row = <ls_row_outline>-row_to + 1. " collapsed-status may be set on following row +* ELSE. +* lv_current_row = <ls_row_outline>-row_to. " collapsed-status may be set on following row +* ENDIF. +* IF lv_current_row > lv_last_row. +* lv_last_row = lv_current_row. +* ENDIF. +* ENDLOOP. +* READ TABLE io_worksheet->sheet_content TRANSPORTING NO FIELDS WITH KEY cell_row = lv_last_row. +* IF sy-subrc <> 0. +* ls_sheet_content_empty-cell_row = lv_last_row. +* ls_sheet_content_empty-cell_column = 1. +* ls_sheet_content_empty-cell_value = lc_dummy_cell_content. +* INSERT ls_sheet_content_empty INTO TABLE io_worksheet->sheet_content. +* ENDIF. +* +* CLEAR ls_sheet_content. +* LOOP AT io_worksheet->sheet_content INTO ls_sheet_content. +* IF lt_values IS INITIAL. " no values attached to autofilter " issue #368 autofilter filtering too much +* CLEAR l_autofilter_hidden. +* ELSE. +* READ TABLE lt_values INTO ls_values WITH KEY column = ls_last_row-cell_column. +* IF sy-subrc = 0 AND ls_values-value = ls_last_row-cell_value. +* CLEAR l_autofilter_hidden. +* ENDIF. +* ENDIF. +* CLEAR ls_style_mapping. +** Create row element +** issues #346,#154, #195 - problems when we have information in row_dimension but no cell content in that row +** Get next line that may have to be added. If we have empty lines this is the next line after previous cell content +** Otherwise it is the line of the current cell content +* lv_current_row = ls_last_row-cell_row + 1. +* IF lv_current_row > ls_sheet_content-cell_row. +* lv_current_row = ls_sheet_content-cell_row. +* ENDIF. +** Fill in empty lines if necessary - assign an emtpy sheet content +* lv_next_row = lv_current_row. +* WHILE lv_next_row <= ls_sheet_content-cell_row. +* lv_current_row = lv_next_row. +* lv_next_row = lv_current_row + 1. +* IF lv_current_row = ls_sheet_content-cell_row. " cell value found in this row +* ASSIGN ls_sheet_content TO <ls_sheet_content>. +* ELSE. +** Check if empty row is really necessary - this is basically the case when we have information in row_dimension +* lo_row_dim_empty = io_worksheet->get_row_dimension( lv_current_row ). +* CHECK lo_row_dim_empty->get_row_height( ) >= 0 OR +* lo_row_dim_empty->get_collapsed( io_worksheet ) = abap_true OR +* lo_row_dim_empty->get_outline_level( io_worksheet ) > 0 OR +* lo_row_dim_empty->get_xf_index( ) <> 0. +* " Dummyentry A1 +* ls_sheet_content_empty-cell_row = lv_current_row. +* ls_sheet_content_empty-cell_column = 1. +* ASSIGN ls_sheet_content_empty TO <ls_sheet_content>. +* ENDIF. +* +* IF ls_last_row-cell_row NE <ls_sheet_content>-cell_row. +* IF lo_autofilter IS BOUND. +* IF ls_area-row_start >= ls_last_row-cell_row OR " One less for header +* ls_area-row_end < ls_last_row-cell_row . +* CLEAR l_autofilter_hidden. +* ENDIF. +* ELSE. +* CLEAR l_autofilter_hidden. +* ENDIF. +* IF ls_last_row-cell_row IS NOT INITIAL. +* " Row visibility of previos row. +* IF row_dimension->get_visible( io_worksheet ) = abap_false OR +* l_autofilter_hidden = abap_true. +* lo_element_2->set_attribute_ns( name = 'hidden' value = 'true'). +* ENDIF. +* lo_element->append_child( new_child = lo_element_2 ). " row node +* ENDIF. +* " Add new row +* lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_row +* parent = lo_document ). +* " r +* lv_value = <ls_sheet_content>-cell_row. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* +* lo_element_2->set_attribute_ns( name = lc_xml_attr_r +* value = lv_value ). +* " Spans +* lv_value = col_count. +* CONCATENATE '1:' lv_value INTO lv_value. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element_2->set_attribute_ns( name = lc_xml_attr_spans +* value = lv_value ). +* row_dimension = io_worksheet->get_row_dimension( <ls_sheet_content>-cell_row ). +* " Do we need the row dimension attributes? +* IF row_dimension->get_row_height( ) >= 0 OR +* row_dimension->get_collapsed( io_worksheet ) = abap_true OR +* row_dimension->get_outline_level( io_worksheet ) > 0 OR +* row_dimension->get_xf_index( ) <> 0 OR +* l_autofilter_hidden = abap_true. +* " Row dimensions +* IF row_dimension->get_row_height( ) >= 0. +* lo_element_2->set_attribute_ns( name = 'customHeight' value = '1'). +* lv_value = row_dimension->get_row_height( ). +* lo_element_2->set_attribute_ns( name = 'ht' value = lv_value ). +* ENDIF. +* " Collapsed +* IF row_dimension->get_collapsed( io_worksheet ) = abap_true. +* lo_element_2->set_attribute_ns( name = 'collapsed' value = 'true'). +* ENDIF. +* " Outline level +* IF row_dimension->get_outline_level( io_worksheet ) > 0. +* lv_value = row_dimension->get_outline_level( io_worksheet ). +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element_2->set_attribute_ns( name = 'outlineLevel' value = lv_value ). +* ENDIF. +* " Style +* IF row_dimension->get_xf_index( ) <> 0. +* lv_value = row_dimension->get_xf_index( ). +* lo_element_2->set_attribute_ns( name = 's' value = lv_value ). +* lo_element_2->set_attribute_ns( name = 'customFormat' value = '1'). +* ENDIF. +* ENDIF. +* IF lt_values IS INITIAL. " no values attached to autofilter " issue #368 autofilter filtering too much +* CLEAR l_autofilter_hidden. +* ELSE. +* l_autofilter_hidden = abap_true. " First default is not showing +* ENDIF. +* ELSE. +* +* ENDIF. +* ENDWHILE. +* +* lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_c +* parent = lo_document ). +* +* lo_element_3->set_attribute_ns( name = lc_xml_attr_r +* value = <ls_sheet_content>-cell_coords ). +* +** begin of change issue #157 - allow column cellstyle +** if no cellstyle is set, look into column, then into sheet +* IF <ls_sheet_content>-cell_style IS NOT INITIAL. +* lv_style_guid = <ls_sheet_content>-cell_style. +* ELSE. +**--------------------------------------------------------------------* +** issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 2 - start +**--------------------------------------------------------------------* +** Check if cell in any of the table areas +* LOOP AT lt_table_areas TRANSPORTING NO FIELDS WHERE top <= <ls_sheet_content>-cell_row +* AND bottom >= <ls_sheet_content>-cell_row +* AND left <= <ls_sheet_content>-cell_column +* AND right >= <ls_sheet_content>-cell_column. +* EXIT. +* ENDLOOP. +* IF sy-subrc = 0. +* CLEAR lv_style_guid. " No style --> EXCEL will use built-in-styles as declared in the tables-section +* ELSE. +**--------------------------------------------------------------------* +** issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 2 - end +**--------------------------------------------------------------------* +* lv_column_p = zcl_excel_common=>convert_column2alpha( <ls_sheet_content>-cell_column ). +* READ TABLE column_dimensions WITH KEY column = lv_column_p ASSIGNING <column_dimension>. +* IF sy-subrc = 0. +* lv_style_guid = <column_dimension>-column_dimension->get_column_style_guid( ). +* IF lv_style_guid IS INITIAL. +* lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). +* ENDIF. +* ELSE. +* lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). +* ENDIF. +**--------------------------------------------------------------------* +** issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 3 - start +**--------------------------------------------------------------------* +* ENDIF. +**--------------------------------------------------------------------* +** issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 3 - end +**--------------------------------------------------------------------* +* ENDIF. +** IF <ls_sheet_content>-cell_style IS NOT INITIAL. +** READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = <ls_sheet_content>-cell_style. +* IF lv_style_guid IS NOT INITIAL. +* READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. +** end of change issue #157 - allow column cellstyles +* lv_value = ls_style_mapping-style. +* SHIFT lv_value RIGHT DELETING TRAILING space. +* SHIFT lv_value LEFT DELETING LEADING space. +* lo_element_3->set_attribute_ns( name = lc_xml_attr_s +* value = lv_value ). +* ENDIF. +* +* " For cells with formula ignore the value - Excel will calculate it +* IF <ls_sheet_content>-cell_formula IS NOT INITIAL. +* " fomula node +* lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_f +* parent = lo_document ). +* lv_value = <ls_sheet_content>-cell_formula. +* CONDENSE lv_value. +* lo_element_4->set_value( value = lv_value ). +* lo_element_3->append_child( new_child = lo_element_4 ). " fomula node +* ELSEIF <ls_sheet_content>-cell_value IS NOT INITIAL "cell can have just style or formula +* AND <ls_sheet_content>-cell_value <> lc_dummy_cell_content. +* IF <ls_sheet_content>-data_type IS NOT INITIAL. +* IF <ls_sheet_content>-data_type EQ 's_leading_blanks'. +* lo_element_3->set_attribute_ns( name = lc_xml_attr_t +* value = 's' ). +* ELSE. +* lo_element_3->set_attribute_ns( name = lc_xml_attr_t +* value = <ls_sheet_content>-data_type ). +* ENDIF. +* ENDIF. +* +* " value node +* lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_v +* parent = lo_document ). +* +* IF <ls_sheet_content>-data_type EQ 's' OR <ls_sheet_content>-data_type EQ 's_leading_blanks'. +* lv_value = me->get_shared_string_index( <ls_sheet_content>-cell_value ). +* CONDENSE lv_value. +* lo_element_4->set_value( value = lv_value ). +* ELSE. +* lv_value = <ls_sheet_content>-cell_value. +* CONDENSE lv_value. +* lo_element_4->set_value( value = lv_value ). +* ENDIF. +* +* lo_element_3->append_child( new_child = lo_element_4 ). " value node +* ENDIF. +* +* lo_element_2->append_child( new_child = lo_element_3 ). " column node +* ls_last_row = <ls_sheet_content>. +* ENDLOOP. +* IF sy-subrc = 0. +* READ TABLE lt_values INTO ls_values WITH KEY column = ls_last_row-cell_column. +* IF sy-subrc = 0 AND ls_values-value = ls_last_row-cell_value. +* CLEAR l_autofilter_hidden. +* ENDIF. +* IF lo_autofilter IS BOUND. +* IF ls_area-row_start >= ls_last_row-cell_row OR " One less for header +* ls_area-row_end < ls_last_row-cell_row . +* CLEAR l_autofilter_hidden. +* ENDIF. +* ELSE. +* CLEAR l_autofilter_hidden. +* ENDIF. +* " Row visibility of previos row. +* IF row_dimension->get_visible( ) = abap_false OR +* l_autofilter_hidden = abap_true. +* lo_element_2->set_attribute_ns( name = 'hidden' value = 'true'). +* ENDIF. +* lo_element->append_child( new_child = lo_element_2 ). " row node +* ENDIF. +* DELETE io_worksheet->sheet_content WHERE cell_value = lc_dummy_cell_content. " Get rid of dummyentries + + lo_element_root->append_child( new_child = lo_element ). " sheetData node + + IF lo_autofilter IS BOUND. +* Create node autofilter + lo_element = lo_document->create_simple_element( name = lc_xml_node_autofilter + parent = lo_document ). + lv_ref = lo_autofilter->get_filter_range( ) . + CONDENSE lv_ref NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_ref + value = lv_ref ). + lt_values = lo_autofilter->get_values( ) . + IF lt_values IS NOT INITIAL. +* If we filter we need to set the filter mode to 1. + lo_element_2 = lo_document->find_from_name( name = lc_xml_node_sheetpr ). + lo_element_2->set_attribute_ns( name = lc_xml_attr_filtermode + value = '1' ). +* Create node filtercolumn + CLEAR lv_column. + LOOP AT lt_values INTO ls_values. + IF ls_values-column <> lv_column. + IF lv_column IS NOT INITIAL. + lo_element_2->append_child( new_child = lo_element_3 ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_filtercolumn + parent = lo_element ). + lv_column = ls_values-column - lo_autofilter->filter_area-col_start. + lv_value = lv_column. + CONDENSE lv_value NO-GAPS. + lo_element_2->set_attribute_ns( name = lc_xml_attr_colid + value = lv_value ). + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_filters + parent = lo_element_2 ). + lv_column = ls_values-column. + ENDIF. + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_filter + parent = lo_element_3 ). + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = ls_values-value ). + lo_element_3->append_child( new_child = lo_element_4 ). " value node + ENDLOOP. + lo_element_2->append_child( new_child = lo_element_3 ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + IF io_worksheet->zif_excel_sheet_protection~protected EQ abap_true. + " sheetProtection node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheetprotection + parent = lo_document ). + MOVE io_worksheet->zif_excel_sheet_protection~password TO lv_value. + IF lv_value IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_password + value = lv_value ). + ENDIF. + lv_value = io_worksheet->zif_excel_sheet_protection~auto_filter. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_autofilter + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~delete_columns. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_deletecolumns + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~delete_rows. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_deleterows + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~format_cells. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_formatcells + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~format_columns. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_formatcolumns + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~format_rows. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_formatrows + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~insert_columns. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_insertcolumns + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~insert_hyperlinks. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_inserthyperlinks + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~insert_rows. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_insertrows + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~objects. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_objects + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~pivot_tables. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_pivottables + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~scenarios. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_scenarios + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~select_locked_cells. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_selectlockedcells + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~select_unlocked_cells. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_selectunlockedcell + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~sheet. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_sheet + value = lv_value ). + lv_value = io_worksheet->zif_excel_sheet_protection~sort. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_sort + value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + " Merged cells + lt_range_merge = io_worksheet->get_merge( ). + IF lt_range_merge IS NOT INITIAL. + lo_element = lo_document->create_simple_element( name = lc_xml_node_mergecells + parent = lo_document ). + DESCRIBE TABLE lt_range_merge LINES merge_count. + lv_value = merge_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + LOOP AT lt_range_merge ASSIGNING <fs_range_merge>. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_mergecell + parent = lo_document ). + + lo_element_2->set_attribute_ns( name = lc_xml_attr_ref + value = <fs_range_merge> ). + lo_element->append_child( new_child = lo_element_2 ). + lo_element_root->append_child( new_child = lo_element ). + io_worksheet->delete_merge( ). + ENDLOOP. + ENDIF. + + " Conditional formatting node + lo_iterator = io_worksheet->get_cond_styles_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style_conditional ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF lo_style_conditional->rule IS INITIAL. + CONTINUE. + ENDIF. + lo_element = lo_document->create_simple_element( name = lc_xml_node_condformatting + parent = lo_document ). + lv_value = lo_style_conditional->get_dimension_range( ) . + lo_element->set_attribute_ns( name = lc_xml_attr_sqref + value = lv_value ). + + " cfRule node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_cfrule + parent = lo_document ). + lv_value = lo_style_conditional->rule. + lo_element_2->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = lo_style_conditional->priority. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_priority + value = lv_value ). + + CASE lo_style_conditional->rule. + " Start >> Databar by Albert Lladanosa + WHEN zcl_excel_style_conditional=>c_rule_databar. + + ls_databar = lo_style_conditional->mode_databar. + + CLEAR lt_cfvo. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_databar + parent = lo_document ). + + MOVE ls_databar-cfvo1_value TO ls_cfvo-value. + MOVE ls_databar-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + MOVE ls_databar-cfvo2_value TO ls_cfvo-value. + MOVE ls_databar-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + LOOP AT lt_cfvo INTO ls_cfvo. + " cfvo node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_cfvo + parent = lo_document ). + lv_value = ls_cfvo-type. + lo_element_4->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = ls_cfvo-value. + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " cfvo node + ENDLOOP. + + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_color + parent = lo_document ). + lv_value = ls_databar-colorrgb. + lo_element_4->set_attribute_ns( name = lc_xml_attr_tabcolor_rgb + value = lv_value ). + + lo_element_3->append_child( new_child = lo_element_4 ). " color node + + lo_element_2->append_child( new_child = lo_element_3 ). " databar node + " End << Databar by Albert Lladanosa + + WHEN zcl_excel_style_conditional=>c_rule_colorscale. + + ls_colorscale = lo_style_conditional->mode_colorscale. + + CLEAR: lt_cfvo, lt_colors. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_colorscale + parent = lo_document ). + + MOVE ls_colorscale-cfvo1_value TO ls_cfvo-value. + MOVE ls_colorscale-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + MOVE ls_colorscale-cfvo2_value TO ls_cfvo-value. + MOVE ls_colorscale-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + MOVE ls_colorscale-cfvo3_value TO ls_cfvo-value. + MOVE ls_colorscale-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + + APPEND ls_colorscale-colorrgb1 TO lt_colors. + APPEND ls_colorscale-colorrgb2 TO lt_colors. + APPEND ls_colorscale-colorrgb3 TO lt_colors. + + LOOP AT lt_cfvo INTO ls_cfvo. + + IF ls_cfvo IS INITIAL. + CONTINUE. + ENDIF. + + " cfvo node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_cfvo + parent = lo_document ). + lv_value = ls_cfvo-type. + lo_element_4->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = ls_cfvo-value. + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " cfvo node + ENDLOOP. + LOOP AT lt_colors INTO ls_colors. + + IF ls_colors IS INITIAL. + CONTINUE. + ENDIF. + + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_color + parent = lo_document ). + lv_value = ls_colors-colorrgb. + lo_element_4->set_attribute_ns( name = lc_xml_attr_tabcolor_rgb + value = lv_value ). + + lo_element_3->append_child( new_child = lo_element_4 ). " color node + ENDLOOP. + + lo_element_2->append_child( new_child = lo_element_3 ). " databar node + + WHEN zcl_excel_style_conditional=>c_rule_iconset. + + ls_iconset = lo_style_conditional->mode_iconset. + + CLEAR lt_cfvo. + " iconset node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_iconset + parent = lo_document ). + IF ls_iconset-iconset NE zcl_excel_style_conditional=>c_iconset_3trafficlights. + lv_value = ls_iconset-iconset. + lo_element_3->set_attribute_ns( name = lc_xml_attr_iconset + value = lv_value ). + ENDIF. + + " Set the showValue attribute + lv_value = ls_iconset-showvalue. + lo_element_3->set_attribute_ns( name = lc_xml_attr_showvalue + value = lv_value ). + + CASE ls_iconset-iconset. + WHEN zcl_excel_style_conditional=>c_iconset_3trafficlights2 OR + zcl_excel_style_conditional=>c_iconset_3arrows OR + zcl_excel_style_conditional=>c_iconset_3arrowsgray OR + zcl_excel_style_conditional=>c_iconset_3flags OR + zcl_excel_style_conditional=>c_iconset_3signs OR + zcl_excel_style_conditional=>c_iconset_3symbols OR + zcl_excel_style_conditional=>c_iconset_3symbols2 OR + zcl_excel_style_conditional=>c_iconset_3trafficlights OR + zcl_excel_style_conditional=>c_iconset_3trafficlights2. + MOVE ls_iconset-cfvo1_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo2_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo3_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + WHEN zcl_excel_style_conditional=>c_iconset_4arrows OR + zcl_excel_style_conditional=>c_iconset_4arrowsgray OR + zcl_excel_style_conditional=>c_iconset_4rating OR + zcl_excel_style_conditional=>c_iconset_4redtoblack OR + zcl_excel_style_conditional=>c_iconset_4trafficlights. + MOVE ls_iconset-cfvo1_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo2_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo3_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo4_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo4_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + WHEN zcl_excel_style_conditional=>c_iconset_5arrows OR + zcl_excel_style_conditional=>c_iconset_5arrowsgray OR + zcl_excel_style_conditional=>c_iconset_5quarters OR + zcl_excel_style_conditional=>c_iconset_5rating. + MOVE ls_iconset-cfvo1_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo1_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo2_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo2_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo3_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo3_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo4_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo4_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + MOVE ls_iconset-cfvo5_value TO ls_cfvo-value. + MOVE ls_iconset-cfvo5_type TO ls_cfvo-type. + APPEND ls_cfvo TO lt_cfvo. + WHEN OTHERS. + CLEAR lt_cfvo. + ENDCASE. + + LOOP AT lt_cfvo INTO ls_cfvo. + " cfvo node + lo_element_4 = lo_document->create_simple_element( name = lc_xml_node_cfvo + parent = lo_document ). + lv_value = ls_cfvo-type. + lo_element_4->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + lv_value = ls_cfvo-value. + lo_element_4->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " cfvo node + ENDLOOP. + + + lo_element_2->append_child( new_child = lo_element_3 ). " iconset node + + WHEN zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis = lo_style_conditional->mode_cellis. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_cellis-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + lv_value = ls_cellis-operator. + lo_element_2->set_attribute_ns( name = lc_xml_attr_operator + value = lv_value ). + " formula node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lv_value = ls_cellis-formula. + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " formula node + IF ls_cellis-formula2 IS NOT INITIAL. + lv_value = ls_cellis-formula2. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " 2nd formula node + ENDIF. + + WHEN zcl_excel_style_conditional=>c_rule_expression. + ls_expression = lo_style_conditional->mode_expression. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_expression-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + " formula node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula + parent = lo_document ). + lv_value = ls_expression-formula. + lo_element_3->set_value( value = lv_value ). + lo_element_2->append_child( new_child = lo_element_3 ). " formula node + +* begin of ins issue #366 - missing conditional rules: top10 + WHEN zcl_excel_style_conditional=>c_rule_top10. + ls_conditional_top10 = lo_style_conditional->mode_top10. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_conditional_top10-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + lv_value = ls_conditional_top10-topxx_count. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = 'rank' + value = lv_value ). + IF ls_conditional_top10-bottom = 'X'. + lo_element_2->set_attribute_ns( name = 'bottom' + value = '1' ). + ENDIF. + IF ls_conditional_top10-percent = 'X'. + lo_element_2->set_attribute_ns( name = 'percent' + value ='1' ). + ENDIF. + + WHEN zcl_excel_style_conditional=>c_rule_above_average. + ls_conditional_above_avg = lo_style_conditional->mode_above_average. + READ TABLE me->styles_cond_mapping INTO ls_style_cond_mapping WITH KEY guid = ls_conditional_above_avg-cell_style. + lv_value = ls_style_cond_mapping-dxf. + CONDENSE lv_value. + lo_element_2->set_attribute_ns( name = lc_xml_attr_dxfid + value = lv_value ). + + IF ls_conditional_above_avg-above_average IS INITIAL. " = below average + lo_element_2->set_attribute_ns( name = 'aboveAverage' + value = '0' ). + ENDIF. + IF ls_conditional_above_avg-equal_average = 'X'. " = equal average also + lo_element_2->set_attribute_ns( name = 'equalAverage' + value = '1' ). + ENDIF. + IF ls_conditional_above_avg-standard_deviation <> 0. " standard deviation instead of value + lv_value = ls_conditional_above_avg-standard_deviation. + lo_element_2->set_attribute_ns( name = 'stdDev' + value = lv_value ). + ENDIF. + +* end of ins issue #366 - missing conditional rules: top10 + + ENDCASE. + + lo_element->append_child( new_child = lo_element_2 ). " cfRule node + + lo_element_root->append_child( new_child = lo_element ). " Conditional formatting node + ENDWHILE. + + IF io_worksheet->get_data_validations_size( ) GT 0. + " dataValidations node + lo_element = lo_document->create_simple_element( name = lc_xml_node_datavalidations + parent = lo_document ). + " Conditional formatting node + lo_iterator = io_worksheet->get_data_validations_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_data_validation ?= lo_iterator->if_object_collection_iterator~get_next( ). + " dataValidation node + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_datavalidation + parent = lo_document ). + lv_value = lo_data_validation->type. + lo_element_2->set_attribute_ns( name = lc_xml_attr_type + value = lv_value ). + IF NOT lo_data_validation->operator IS INITIAL. + lv_value = lo_data_validation->operator. + lo_element_2->set_attribute_ns( name = lc_xml_attr_operator + value = lv_value ). + ENDIF. + IF lo_data_validation->allowblank EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_allowblank + value = lv_value ). + IF lo_data_validation->showinputmessage EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showinputmessage + value = lv_value ). + IF lo_data_validation->showerrormessage EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showerrormessage + value = lv_value ). + IF lo_data_validation->showdropdown EQ abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_showdropdown + value = lv_value ). + IF NOT lo_data_validation->errortitle IS INITIAL. + lv_value = lo_data_validation->errortitle. + lo_element_2->set_attribute_ns( name = lc_xml_attr_errortitle + value = lv_value ). + ENDIF. + IF NOT lo_data_validation->error IS INITIAL. + lv_value = lo_data_validation->error. + lo_element_2->set_attribute_ns( name = lc_xml_attr_error + value = lv_value ). + ENDIF. + IF NOT lo_data_validation->prompttitle IS INITIAL. + lv_value = lo_data_validation->prompttitle. + lo_element_2->set_attribute_ns( name = lc_xml_attr_prompttitle + value = lv_value ). + ENDIF. + IF NOT lo_data_validation->prompt IS INITIAL. + lv_value = lo_data_validation->prompt. + lo_element_2->set_attribute_ns( name = lc_xml_attr_prompt + value = lv_value ). + ENDIF. + lv_cell_row_s = lo_data_validation->cell_row. + CONDENSE lv_cell_row_s. + CONCATENATE lo_data_validation->cell_column lv_cell_row_s INTO lv_value. + IF lo_data_validation->cell_row_to IS NOT INITIAL. + lv_cell_row_s = lo_data_validation->cell_row_to. + CONDENSE lv_cell_row_s. + CONCATENATE lv_value ':' lo_data_validation->cell_column_to lv_cell_row_s INTO lv_value. + ENDIF. + lo_element_2->set_attribute_ns( name = lc_xml_attr_sqref + value = lv_value ). + " formula1 node + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula1 + parent = lo_document ). + lv_value = lo_data_validation->formula1. + lo_element_3->set_value( value = lv_value ). + + lo_element_2->append_child( new_child = lo_element_3 ). " formula1 node + " formula2 node + IF NOT lo_data_validation->formula2 IS INITIAL. + lo_element_3 = lo_document->create_simple_element( name = lc_xml_node_formula2 + parent = lo_document ). + lv_value = lo_data_validation->formula2. + lo_element_3->set_value( value = lv_value ). + + lo_element_2->append_child( new_child = lo_element_3 ). " formula2 node + ENDIF. + + lo_element->append_child( new_child = lo_element_2 ). " dataValidation node + ENDWHILE. + lo_element_root->append_child( new_child = lo_element ). " dataValidations node + ENDIF. + + " Hyperlinks + DATA: lv_hyperlinks_count TYPE i, + lo_link TYPE REF TO zcl_excel_hyperlink. + + lv_hyperlinks_count = io_worksheet->get_hyperlinks_size( ). + IF lv_hyperlinks_count > 0. + lo_element = lo_document->create_simple_element( name = 'hyperlinks' + parent = lo_document ). + + lo_iterator = io_worksheet->get_hyperlinks_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_link ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lo_element_2 = lo_document->create_simple_element( name = 'hyperlink' + parent = lo_element ). + + lv_value = lo_link->get_ref( ). + lo_element_2->set_attribute_ns( name = 'ref' + value = lv_value ). + + IF lo_link->is_internal( ) = abap_true. + lv_value = lo_link->get_url( ). + lo_element_2->set_attribute_ns( name = 'location' + value = lv_value ). + ELSE. + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element_2->set_attribute_ns( name = 'r:id' + value = lv_value ). + + ENDIF. + + lo_element->append_child( new_child = lo_element_2 ). + ENDWHILE. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + + " PrintOptions + IF io_worksheet->print_gridlines = abap_true OR + io_worksheet->sheet_setup->vertical_centered = abap_true OR + io_worksheet->sheet_setup->horizontal_centered = abap_true. + lo_element = lo_document->create_simple_element( name = 'printOptions' + parent = lo_document ). + + IF io_worksheet->print_gridlines = abap_true. + lo_element->set_attribute_ns( name = lc_xml_attr_gridlines + value = 'true' ). + ENDIF. + + IF io_worksheet->sheet_setup->horizontal_centered = abap_true. + lo_element->set_attribute_ns( name = 'horizontalCentered' + value = 'true' ). + ENDIF. + + IF io_worksheet->sheet_setup->vertical_centered = abap_true. + lo_element->set_attribute_ns( name = 'verticalCentered' + value = 'true' ). + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + " pageMargins node + lo_element = lo_document->create_simple_element( name = lc_xml_node_pagemargins + parent = lo_document ). + + lv_value = io_worksheet->sheet_setup->margin_left. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_left + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_right. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_right + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_top. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_top + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_bottom. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_bottom + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_header. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_header + value = lv_value ). + lv_value = io_worksheet->sheet_setup->margin_footer. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_footer + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). " pageMargins node + +* pageSetup node + lo_element = lo_document->create_simple_element( name = lc_xml_node_pagesetup + parent = lo_document ). + + IF io_worksheet->sheet_setup->black_and_white IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_blackandwhite + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->cell_comments IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_cellcomments + value = io_worksheet->sheet_setup->cell_comments ). + ENDIF. + + IF io_worksheet->sheet_setup->copies IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->copies. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_copies + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->draft IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_draft + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->errors IS NOT INITIAL. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_errors + value = io_worksheet->sheet_setup->errors ). + ENDIF. + + IF io_worksheet->sheet_setup->first_page_number IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->first_page_number. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_firstpagenumber + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->fit_to_page IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->fit_to_height. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_fittoheight + value = lv_value ). + lv_value = io_worksheet->sheet_setup->fit_to_width. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_fittowidth + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->horizontal_dpi IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->horizontal_dpi. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_horizontaldpi + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->orientation IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->orientation. + lo_element->set_attribute_ns( name = lc_xml_attr_orientation + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->page_order IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_pageorder + value = io_worksheet->sheet_setup->page_order ). + ENDIF. + + IF io_worksheet->sheet_setup->paper_height IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->paper_height. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_paperheight + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->paper_size IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->paper_size. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_papersize + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->paper_width IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->paper_width. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_paperwidth + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->scale IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->scale. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_scale + value = lv_value ). + ENDIF. + + IF io_worksheet->sheet_setup->use_first_page_num IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_usefirstpagenumber + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->use_printer_defaults IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_useprinterdefaults + value = `1` ). + ENDIF. + + IF io_worksheet->sheet_setup->vertical_dpi IS NOT INITIAL. + lv_value = io_worksheet->sheet_setup->vertical_dpi. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_verticaldpi + value = lv_value ). + ENDIF. + + lo_element_root->append_child( new_child = lo_element ). " pageSetup node + +* { headerFooter necessary? > + IF io_worksheet->sheet_setup->odd_header IS NOT INITIAL + OR io_worksheet->sheet_setup->odd_footer IS NOT INITIAL + OR io_worksheet->sheet_setup->diff_oddeven_headerfooter = abap_true. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_headerfooter + parent = lo_document ). + + " Different header/footer for odd/even pages? + IF io_worksheet->sheet_setup->diff_oddeven_headerfooter = abap_true. + lo_element->set_attribute_ns( name = lc_xml_attr_differentoddeven + value = '1' ). + ENDIF. + + " OddHeader + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_odd_header = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_oddheader + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + " OddFooter + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_odd_footer = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_oddfooter + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + " evenHeader + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_even_header = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_evenheader + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + " evenFooter + CLEAR: lv_value. + io_worksheet->sheet_setup->get_header_footer_string( IMPORTING ep_even_footer = lv_value ) . + IF lv_value IS NOT INITIAL. + lo_element_2 = lo_document->create_simple_element( name = lc_xml_node_evenfooter + parent = lo_document ). + lo_element_2->set_value( value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + ENDIF. + + + lo_element_root->append_child( new_child = lo_element ). " headerFooter + + ENDIF. + +* issue #377 pagebreaks + TRY. + create_xl_sheet_pagebreaks( io_document = lo_document + io_parent = lo_element_root + io_worksheet = io_worksheet ) . + CATCH zcx_excel. " Ignore Hyperlink reading errors - pass everything we were able to identify + ENDTRY. + +* drawing + DATA: lo_drawings TYPE REF TO zcl_excel_drawings. + + lo_drawings = io_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + lo_element = lo_document->create_simple_element( name = lc_xml_node_drawing + parent = lo_document ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element->set_attribute( name = 'r:id' + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + +* tables + DATA lv_table_count TYPE i. + + lv_table_count = io_worksheet->get_tables_size( ). + IF lv_table_count > 0. + lo_element = lo_document->create_simple_element( name = 'tableParts' + parent = lo_document ). + lv_value = lv_table_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = 'count' + value = lv_value ). + + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element_2 = lo_document->create_simple_element( name = 'tablePart' + parent = lo_element ). + lo_element_2->set_attribute_ns( name = 'r:id' + value = lv_value ). + lo_element->append_child( new_child = lo_element_2 ). + + ENDWHILE. + + lo_element_root->append_child( new_child = lo_element ). + + ENDIF. + + + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + +* REPLACE FIRST OCCURRENCE OF me->mv_sheet_data_xstring_dummy IN ep_content WITH me->mv_sheet_data_xstring IN BYTE MODE. + +ENDMETHOD. + + + + + + + METHOD create_xl_sheet_pagebreaks. + DATA: lo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks, + lt_pagebreaks TYPE zcl_excel_worksheet_pagebreaks=>tt_pagebreak_at, + lt_rows TYPE HASHED TABLE OF int4 WITH UNIQUE KEY table_line, + lt_columns TYPE HASHED TABLE OF int4 WITH UNIQUE KEY table_line, + + lo_node_rowbreaks TYPE REF TO if_ixml_element, + lo_node_colbreaks TYPE REF TO if_ixml_element, + lo_node_break TYPE REF TO if_ixml_element, + + lv_value TYPE string. + + + FIELD-SYMBOLS: <ls_pagebreak> LIKE LINE OF lt_pagebreaks. + + lo_pagebreaks = io_worksheet->get_pagebreaks( ). + CHECK lo_pagebreaks IS BOUND. + + lt_pagebreaks = lo_pagebreaks->get_all_pagebreaks( ). + CHECK lt_pagebreaks IS NOT INITIAL. " No need to proceed if don't have any pagebreaks. + + lo_node_rowbreaks = io_document->create_simple_element( name = 'rowBreaks' + parent = io_document ). + + lo_node_colbreaks = io_document->create_simple_element( name = 'colBreaks' + parent = io_document ). + + + LOOP AT lt_pagebreaks ASSIGNING <ls_pagebreak>. + +* Count how many rows and columns need to be broken + INSERT <ls_pagebreak>-cell_row INTO TABLE lt_rows. + IF sy-subrc = 0. " New + lv_value = <ls_pagebreak>-cell_row. + CONDENSE lv_value. + + lo_node_break = io_document->create_simple_element( name = 'brk' + parent = io_document ). + lo_node_break->set_attribute( name = 'id' value = lv_value ). + lo_node_break->set_attribute( name = 'man' value = '1' ). " Manual break + lo_node_break->set_attribute( name = 'max' value = '16383' ). " Max columns + + lo_node_rowbreaks->append_child( new_child = lo_node_break ). + ENDIF. + + INSERT <ls_pagebreak>-cell_column INTO TABLE lt_columns. + IF sy-subrc = 0. " New + lv_value = <ls_pagebreak>-cell_column. + CONDENSE lv_value. + + lo_node_break = io_document->create_simple_element( name = 'brk' + parent = io_document ). + lo_node_break->set_attribute( name = 'id' value = lv_value ). + lo_node_break->set_attribute( name = 'man' value = '1' ). " Manual break + lo_node_break->set_attribute( name = 'max' value = '1048575' ). " Max rows + + lo_node_colbreaks->append_child( new_child = lo_node_break ). + ENDIF. + + + ENDLOOP. + + lv_value = lines( lt_rows ). + CONDENSE lv_value. + lo_node_rowbreaks->set_attribute( name = 'count' value = lv_value ). + lo_node_rowbreaks->set_attribute( name = 'manualBreakCount' value = lv_value ). + + lv_value = lines( lt_rows ). + CONDENSE lv_value. + lo_node_colbreaks->set_attribute( name = 'count' value = lv_value ). + lo_node_colbreaks->set_attribute( name = 'manualBreakCount' value = lv_value ). + + + + + io_parent->append_child( new_child = lo_node_rowbreaks ). + io_parent->append_child( new_child = lo_node_colbreaks ). + +ENDMETHOD. + + + + + + METHOD create_xl_sheet_rels. + + +** Constant node name + DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'Id', + lc_xml_attr_type TYPE string VALUE 'Type', + lc_xml_attr_target TYPE string VALUE 'Target', + lc_xml_attr_target_mode TYPE string VALUE 'TargetMode', + lc_xml_val_external TYPE string VALUE 'External', + " Node namespace + lc_xml_node_rels_ns TYPE string VALUE 'http://schemas.openxmlformats.org/package/2006/relationships', + lc_xml_node_rid_table_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table', + lc_xml_node_rid_printer_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings', + lc_xml_node_rid_drawing_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', + lc_xml_node_rid_link_tp TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table, + lo_link TYPE REF TO zcl_excel_hyperlink. + + DATA: lv_value TYPE string, + lv_relation_id TYPE i, + lv_index_str TYPE string. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_relationships + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_rels_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + " Add sheet Relationship nodes here + lv_relation_id = 0. + lo_iterator = io_worksheet->get_hyperlinks_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_link ?= lo_iterator->if_object_collection_iterator~get_next( ). + CHECK lo_link->is_internal( ) = abap_false. " issue #340 - don't put internal links here + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_link_tp ). + + lv_value = lo_link->get_url( ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_target_mode + value = lc_xml_val_external ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + +* drawing + DATA: lo_drawings TYPE REF TO zcl_excel_drawings. + + lo_drawings = io_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_drawing_tp ). + + lv_index_str = iv_drawing_index. + CONDENSE lv_index_str NO-GAPS. + MOVE me->c_xl_drawings TO lv_value. + REPLACE 'xl' WITH '..' INTO lv_value. + REPLACE '#' WITH lv_index_str INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ADD 1 TO lv_relation_id. + + lv_value = lv_relation_id. + CONDENSE lv_value. + CONCATENATE 'rId' lv_value INTO lv_value. + + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_table_tp ). + + lv_value = lo_table->get_name( ). + CONCATENATE '../tables/' lv_value '.xml' INTO lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDWHILE. + +* IF io_worksheet->get_print_settings( )->is_empty( ) = abap_false. +* ADD 1 TO lv_relation_id. +* lv_value = lv_relation_id. +* CONDENSE lv_value. +* CONCATENATE 'rId' lv_value INTO lv_value. +* +* lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship +* parent = lo_document ). +* lo_element->set_attribute_ns( name = lc_xml_attr_id +* value = lv_value ). +* lo_element->set_attribute_ns( name = lc_xml_attr_type +* value = lc_xml_node_rid_printer_tp ). +* +* lv_index_str = iv_printer_index. +* CONDENSE lv_index_str NO-GAPS. +* MOVE me->c_xl_printersettings TO lv_value. +* REPLACE 'xl' WITH '..' INTO lv_value. +* REPLACE '#' WITH lv_index_str INTO lv_value. +* lo_element->set_attribute_ns( name = lc_xml_attr_target +* value = lv_value ). +* +* lo_element_root->append_child( new_child = lo_element ). +* ENDIF. + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + + + + + METHOD create_xl_sheet_sheet_data. + + TYPES: BEGIN OF lty_table_area, + left TYPE i, + right TYPE i, + top TYPE i, + bottom TYPE i, + END OF lty_table_area. + + CONSTANTS: lc_dummy_cell_content TYPE zexcel_s_cell_data-cell_value VALUE '})~~~ This is a dummy value for ABAP2XLSX and you should never find this in a real excelsheet Ihope'. + + CONSTANTS: lc_xml_node_sheetdata TYPE string VALUE 'sheetData', " SheetData tag + lc_xml_node_row TYPE string VALUE 'row', " Row tag + lc_xml_attr_r TYPE string VALUE 'r', " Cell: row-attribute + lc_xml_attr_spans TYPE string VALUE 'spans', " Cell: spans-attribute + lc_xml_node_c TYPE string VALUE 'c', " Cell tag + lc_xml_node_v TYPE string VALUE 'v', " Cell: value + lc_xml_node_f TYPE string VALUE 'f', " Cell: formula + lc_xml_attr_s TYPE string VALUE 's', " Cell: style + lc_xml_attr_t TYPE string VALUE 't'. " Cell: type + + DATA: col_count TYPE int4, + lo_autofilters TYPE REF TO zcl_excel_autofilters, + lo_autofilter TYPE REF TO zcl_excel_autofilter, + l_autofilter_hidden TYPE flag, + lt_values TYPE zexcel_t_autofilter_values, + ls_values TYPE zexcel_s_autofilter_values, + ls_area TYPE zexcel_s_autofilter_area, + + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table, + lt_table_areas TYPE SORTED TABLE OF lty_table_area WITH NON-UNIQUE KEY left right top bottom, + ls_table_area LIKE LINE OF lt_table_areas, + + ls_sheet_content LIKE LINE OF io_worksheet->sheet_content, + ls_sheet_content_empty LIKE LINE OF io_worksheet->sheet_content, + lv_current_row TYPE i, + lv_next_row TYPE i, + lv_last_row TYPE i, + + lts_row_dimensions TYPE zexcel_t_worksheet_rowdimensio, + lo_row_dim_empty TYPE REF TO zcl_excel_worksheet_rowdimensi, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + lts_row_outlines TYPE zcl_excel_worksheet=>mty_ts_outlines_row, + + ls_last_row TYPE zexcel_s_cell_data, + ls_style_mapping TYPE zexcel_s_styles_mapping, + + lo_element_2 TYPE REF TO if_ixml_element, + lo_element_3 TYPE REF TO if_ixml_element, + lo_element_4 TYPE REF TO if_ixml_element, + + lv_value TYPE string, + lv_style_guid TYPE zexcel_cell_style, + lv_column_p TYPE zexcel_cell_column_alpha, + + xxx. + + FIELD-SYMBOLS: <ls_sheet_content> TYPE zexcel_s_cell_data, + <column_dimension> TYPE zexcel_s_worksheet_columndime, + <row_dimension> TYPE zexcel_s_worksheet_rowdimensio, + <ls_row_outline> LIKE LINE OF lts_row_outlines. + + + DATA: lv_xstring_partial TYPE xstring, + lv_xstring TYPE xstring. + + " sheetData node + rv_ixml_sheet_data_root = io_document->create_simple_element( name = lc_xml_node_sheetdata + parent = io_document ). + me->mv_sheet_data_xstring_dummy = render_ixml_element_no_header( rv_ixml_sheet_data_root ). + + " Get column count + col_count = io_worksheet->get_highest_column( ). + " Get autofilter +*lv_guid = io_worksheet->get_guid( ) . + lo_autofilters = excel->get_autofilters_reference( ). + lo_autofilter = lo_autofilters->get( io_worksheet = io_worksheet ) . + IF lo_autofilter IS BOUND. + lt_values = lo_autofilter->get_values( ) . + ls_area = lo_autofilter->get_filter_area( ) . + l_autofilter_hidden = abap_true. " First defautl is not showing + ENDIF. +*--------------------------------------------------------------------* +*issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 1 - start +*--------------------------------------------------------------------* +*Build table to hold all table-areas attached to this sheet + lo_iterator = io_worksheet->get_tables_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_iterator->if_object_collection_iterator~get_next( ). + ls_table_area-left = zcl_excel_common=>convert_column2int( lo_table->settings-top_left_column ). + ls_table_area-right = lo_table->get_right_column_integer( ). + ls_table_area-top = lo_table->settings-top_left_row. + ls_table_area-bottom = lo_table->get_bottom_row_integer( ). + INSERT ls_table_area INTO TABLE lt_table_areas. + ENDWHILE. +*--------------------------------------------------------------------* +*issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 1 - end +*--------------------------------------------------------------------* +*We have problems when the first rows or trailing rows are not set but we have rowinformation +*to solve this we add dummycontent into first and last line that will not be set +*Set first line if necessary + READ TABLE io_worksheet->sheet_content TRANSPORTING NO FIELDS WITH KEY cell_row = 1. + IF sy-subrc <> 0. + ls_sheet_content_empty-cell_row = 1. + ls_sheet_content_empty-cell_column = 1. + ls_sheet_content_empty-cell_value = lc_dummy_cell_content. + INSERT ls_sheet_content_empty INTO TABLE io_worksheet->sheet_content. + ENDIF. +*Set last line if necessary +*Last row with cell content + lv_last_row = io_worksheet->get_highest_row( ). +*Last line with row-information set directly ( like line height, hidden-status ... ) + lts_row_dimensions = io_worksheet->get_row_dimensions( ). + SORT lts_row_dimensions BY row DESCENDING. + READ TABLE lts_row_dimensions INDEX 1 ASSIGNING <row_dimension>. + IF sy-subrc = 0 AND <row_dimension>-row > lv_last_row. + lv_last_row = <row_dimension>-row. + ENDIF. +*Last line with row-information set indirectly by row outline + lts_row_outlines = io_worksheet->get_row_outlines( ). + LOOP AT lts_row_outlines ASSIGNING <ls_row_outline>. + IF <ls_row_outline>-collapsed = 'X'. + lv_current_row = <ls_row_outline>-row_to + 1. " collapsed-status may be set on following row + ELSE. + lv_current_row = <ls_row_outline>-row_to. " collapsed-status may be set on following row + ENDIF. + IF lv_current_row > lv_last_row. + lv_last_row = lv_current_row. + ENDIF. + ENDLOOP. + READ TABLE io_worksheet->sheet_content TRANSPORTING NO FIELDS WITH KEY cell_row = lv_last_row. + IF sy-subrc <> 0. + ls_sheet_content_empty-cell_row = lv_last_row. + ls_sheet_content_empty-cell_column = 1. + ls_sheet_content_empty-cell_value = lc_dummy_cell_content. + INSERT ls_sheet_content_empty INTO TABLE io_worksheet->sheet_content. + ENDIF. + + CLEAR ls_sheet_content. + LOOP AT io_worksheet->sheet_content INTO ls_sheet_content. + IF lt_values IS INITIAL. " no values attached to autofilter " issue #368 autofilter filtering too much + CLEAR l_autofilter_hidden. + ELSE. + READ TABLE lt_values INTO ls_values WITH KEY column = ls_last_row-cell_column. + IF sy-subrc = 0 AND ls_values-value = ls_last_row-cell_value. + CLEAR l_autofilter_hidden. + ENDIF. + ENDIF. + CLEAR ls_style_mapping. +*Create row element +*issues #346,#154, #195 - problems when we have information in row_dimension but no cell content in that row +*Get next line that may have to be added. If we have empty lines this is the next line after previous cell content +*Otherwise it is the line of the current cell content + lv_current_row = ls_last_row-cell_row + 1. + IF lv_current_row > ls_sheet_content-cell_row. + lv_current_row = ls_sheet_content-cell_row. + ENDIF. +*Fill in empty lines if necessary - assign an emtpy sheet content + lv_next_row = lv_current_row. + WHILE lv_next_row <= ls_sheet_content-cell_row. + lv_current_row = lv_next_row. + lv_next_row = lv_current_row + 1. + IF lv_current_row = ls_sheet_content-cell_row. " cell value found in this row + ASSIGN ls_sheet_content TO <ls_sheet_content>. + ELSE. +*Check if empty row is really necessary - this is basically the case when we have information in row_dimension + lo_row_dim_empty = io_worksheet->get_row_dimension( lv_current_row ). + CHECK lo_row_dim_empty->get_row_height( ) >= 0 OR + lo_row_dim_empty->get_collapsed( io_worksheet ) = abap_true OR + lo_row_dim_empty->get_outline_level( io_worksheet ) > 0 OR + lo_row_dim_empty->get_xf_index( ) <> 0. + " Dummyentry A1 + ls_sheet_content_empty-cell_row = lv_current_row. + ls_sheet_content_empty-cell_column = 1. + ASSIGN ls_sheet_content_empty TO <ls_sheet_content>. + ENDIF. + + IF ls_last_row-cell_row NE <ls_sheet_content>-cell_row. + IF lo_autofilter IS BOUND. + IF ls_area-row_start >= ls_last_row-cell_row OR " One less for header + ls_area-row_end < ls_last_row-cell_row . + CLEAR l_autofilter_hidden. + ENDIF. + ELSE. + CLEAR l_autofilter_hidden. + ENDIF. + IF ls_last_row-cell_row IS NOT INITIAL. + " Row visibility of previos row. + IF row_dimension->get_visible( io_worksheet ) = abap_false OR + l_autofilter_hidden = abap_true. + lo_element_2->set_attribute_ns( name = 'hidden' value = 'true'). + ENDIF. +* lv_xstring_partial = render_ixml_element_no_header( lo_element_2 ). +* CONCATENATE lv_xstring lv_xstring_partial +* INTO lv_xstring IN BYTE MODE. + rv_ixml_sheet_data_root->append_child( new_child = lo_element_2 ). " row node + ENDIF. + " Add new row + lo_element_2 = io_document->create_simple_element( name = lc_xml_node_row + parent = io_document ). + " r + lv_value = <ls_sheet_content>-cell_row. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + + lo_element_2->set_attribute_ns( name = lc_xml_attr_r + value = lv_value ). + " Spans + lv_value = col_count. + CONCATENATE '1:' lv_value INTO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = lc_xml_attr_spans + value = lv_value ). + row_dimension = io_worksheet->get_row_dimension( <ls_sheet_content>-cell_row ). + " Do we need the row dimension attributes? + IF row_dimension->get_row_height( ) >= 0 OR + row_dimension->get_collapsed( io_worksheet ) = abap_true OR + row_dimension->get_outline_level( io_worksheet ) > 0 OR + row_dimension->get_xf_index( ) <> 0 OR + l_autofilter_hidden = abap_true. + " Row dimensions + IF row_dimension->get_row_height( ) >= 0. + lo_element_2->set_attribute_ns( name = 'customHeight' value = '1'). + lv_value = row_dimension->get_row_height( ). + lo_element_2->set_attribute_ns( name = 'ht' value = lv_value ). + ENDIF. + " Collapsed + IF row_dimension->get_collapsed( io_worksheet ) = abap_true. + lo_element_2->set_attribute_ns( name = 'collapsed' value = 'true'). + ENDIF. + " Outline level + IF row_dimension->get_outline_level( io_worksheet ) > 0. + lv_value = row_dimension->get_outline_level( io_worksheet ). + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_2->set_attribute_ns( name = 'outlineLevel' value = lv_value ). + ENDIF. + " Style + IF row_dimension->get_xf_index( ) <> 0. + lv_value = row_dimension->get_xf_index( ). + lo_element_2->set_attribute_ns( name = 's' value = lv_value ). + lo_element_2->set_attribute_ns( name = 'customFormat' value = '1'). + ENDIF. + ENDIF. + IF lt_values IS INITIAL. " no values attached to autofilter " issue #368 autofilter filtering too much + CLEAR l_autofilter_hidden. + ELSE. + l_autofilter_hidden = abap_true. " First default is not showing + ENDIF. + ELSE. + + ENDIF. + ENDWHILE. + + lo_element_3 = io_document->create_simple_element( name = lc_xml_node_c + parent = io_document ). + + lo_element_3->set_attribute_ns( name = lc_xml_attr_r + value = <ls_sheet_content>-cell_coords ). + +*begin of change issue #157 - allow column cellstyle +*if no cellstyle is set, look into column, then into sheet + IF <ls_sheet_content>-cell_style IS NOT INITIAL. + lv_style_guid = <ls_sheet_content>-cell_style. + ELSE. +*--------------------------------------------------------------------* +*issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 2 - start +*--------------------------------------------------------------------* +*Check if cell in any of the table areas + LOOP AT lt_table_areas TRANSPORTING NO FIELDS WHERE top <= <ls_sheet_content>-cell_row + AND bottom >= <ls_sheet_content>-cell_row + AND left <= <ls_sheet_content>-cell_column + AND right >= <ls_sheet_content>-cell_column. + EXIT. + ENDLOOP. + IF sy-subrc = 0. + CLEAR lv_style_guid. " No style --> EXCEL will use built-in-styles as declared in the tables-section + ELSE. +*--------------------------------------------------------------------* +*issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 2 - end +*--------------------------------------------------------------------* + lv_column_p = zcl_excel_common=>convert_column2alpha( <ls_sheet_content>-cell_column ). + READ TABLE it_column_dimensions WITH KEY column = lv_column_p ASSIGNING <column_dimension>. + IF sy-subrc = 0. + lv_style_guid = <column_dimension>-column_dimension->get_column_style_guid( ). + IF lv_style_guid IS INITIAL. + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. + ELSE. + lv_style_guid = io_worksheet->zif_excel_sheet_properties~get_style( ). + ENDIF. +*--------------------------------------------------------------------* +*issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 3 - start +*--------------------------------------------------------------------* + ENDIF. +*--------------------------------------------------------------------* +*issue #220 - If cell in tables-area don't use default from row or column or sheet - Coding 3 - end +*--------------------------------------------------------------------* + ENDIF. +* IF <ls_sheet_content>-cell_style IS NOT INITIAL. +* READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = <ls_sheet_content>-cell_style. + IF lv_style_guid IS NOT INITIAL. + READ TABLE styles_mapping INTO ls_style_mapping WITH KEY guid = lv_style_guid. +*end of change issue #157 - allow column cellstyles + lv_value = ls_style_mapping-style. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_3->set_attribute_ns( name = lc_xml_attr_s + value = lv_value ). + ENDIF. + + " For cells with formula ignore the value - Excel will calculate it + IF <ls_sheet_content>-cell_formula IS NOT INITIAL. + " fomula node + lo_element_4 = io_document->create_simple_element( name = lc_xml_node_f + parent = io_document ). + lv_value = <ls_sheet_content>-cell_formula. + CONDENSE lv_value. + lo_element_4->set_value( value = lv_value ). + lo_element_3->append_child( new_child = lo_element_4 ). " fomula node + ELSEIF <ls_sheet_content>-cell_value IS NOT INITIAL "cell can have just style or formula + AND <ls_sheet_content>-cell_value <> lc_dummy_cell_content. + IF <ls_sheet_content>-data_type IS NOT INITIAL. + IF <ls_sheet_content>-data_type EQ 's_leading_blanks'. + lo_element_3->set_attribute_ns( name = lc_xml_attr_t + value = 's' ). + ELSE. + lo_element_3->set_attribute_ns( name = lc_xml_attr_t + value = <ls_sheet_content>-data_type ). + ENDIF. + ENDIF. + + " value node + lo_element_4 = io_document->create_simple_element( name = lc_xml_node_v + parent = io_document ). + + IF <ls_sheet_content>-data_type EQ 's' OR <ls_sheet_content>-data_type EQ 's_leading_blanks'. + lv_value = me->get_shared_string_index( <ls_sheet_content>-cell_value ). + CONDENSE lv_value. + lo_element_4->set_value( value = lv_value ). + ELSE. + lv_value = <ls_sheet_content>-cell_value. + CONDENSE lv_value. + lo_element_4->set_value( value = lv_value ). + ENDIF. + + lo_element_3->append_child( new_child = lo_element_4 ). " value node + ENDIF. + + lo_element_2->append_child( new_child = lo_element_3 ). " column node + ls_last_row = <ls_sheet_content>. + ENDLOOP. + IF sy-subrc = 0. + READ TABLE lt_values INTO ls_values WITH KEY column = ls_last_row-cell_column. + IF sy-subrc = 0 AND ls_values-value = ls_last_row-cell_value. + CLEAR l_autofilter_hidden. + ENDIF. + IF lo_autofilter IS BOUND. + IF ls_area-row_start >= ls_last_row-cell_row OR " One less for header + ls_area-row_end < ls_last_row-cell_row . + CLEAR l_autofilter_hidden. + ENDIF. + ELSE. + CLEAR l_autofilter_hidden. + ENDIF. + " Row visibility of previos row. + IF row_dimension->get_visible( ) = abap_false OR + l_autofilter_hidden = abap_true. + lo_element_2->set_attribute_ns( name = 'hidden' value = 'true'). + ENDIF. +* lv_xstring_partial = render_ixml_element_no_header( lo_element_2 ). +* CONCATENATE lv_xstring lv_xstring_partial +* INTO lv_xstring IN BYTE MODE. + rv_ixml_sheet_data_root->append_child( new_child = lo_element_2 ). " row node + ENDIF. + DELETE io_worksheet->sheet_content WHERE cell_value = lc_dummy_cell_content. " Get rid of dummyentries + +* +* +* me->mv_sheet_data_xstring = render_ixml_element_no_header( rv_ixml_sheet_data_root ). +* +* +** Für den Dummystringersatz jetzt alles zurück auf Anfang +* rv_ixml_sheet_data_root = io_document->create_simple_element( name = lc_xml_node_sheetdata +* parent = io_document ). +* me->mv_sheet_data_xstring_dummy = render_ixml_element_no_header( rv_ixml_sheet_data_root ). +* +* DATA: lv_sheetdata_tag_start TYPE xstring, +* lv_sheetdata_tag_end TYPE xstring. +* +* lv_sheetdata_tag_start = cl_bcs_convert=>string_to_xstring( '<sheetData>' ). +* lv_sheetdata_tag_end = cl_bcs_convert=>string_to_xstring( '</sheetData>' ). +* CONCATENATE lv_sheetdata_tag_start lv_xstring lv_sheetdata_tag_end +* INTO lv_xstring IN BYTE MODE. +* me->mv_sheet_data_xstring = lv_xstring. + +ENDMETHOD. + + + + METHOD create_xl_styles. +*--------------------------------------------------------------------* +* ToDos: +* 2do§1 dxfs-cellstyles are used in conditional formats: +* CellIs, Expression, top10 ( forthcoming above average as well ) +* create own method to write dsfx-cellstyle to be reuseable by all these +*--------------------------------------------------------------------* + + +** Constant node name + CONSTANTS: lc_xml_node_stylesheet TYPE string VALUE 'styleSheet', + " font + lc_xml_node_fonts TYPE string VALUE 'fonts', + lc_xml_node_font TYPE string VALUE 'font', + lc_xml_node_b TYPE string VALUE 'b', "bold + lc_xml_node_i TYPE string VALUE 'i', "italic + lc_xml_node_u TYPE string VALUE 'u', "underline + lc_xml_node_strike TYPE string VALUE 'strike', "strikethrough + lc_xml_node_sz TYPE string VALUE 'sz', + lc_xml_node_color TYPE string VALUE 'color', + lc_xml_node_name TYPE string VALUE 'name', + lc_xml_node_family TYPE string VALUE 'family', + lc_xml_node_scheme TYPE string VALUE 'scheme', + " fill + lc_xml_node_fills TYPE string VALUE 'fills', + lc_xml_node_fill TYPE string VALUE 'fill', + lc_xml_node_patternfill TYPE string VALUE 'patternFill', + lc_xml_node_fgcolor TYPE string VALUE 'fgColor', + lc_xml_node_bgcolor TYPE string VALUE 'bgColor', + lc_xml_node_gradientfill TYPE string VALUE 'gradientFill', + lc_xml_node_stop TYPE string VALUE 'stop', + " borders + lc_xml_node_borders TYPE string VALUE 'borders', + lc_xml_node_border TYPE string VALUE 'border', + lc_xml_node_left TYPE string VALUE 'left', + lc_xml_node_right TYPE string VALUE 'right', + lc_xml_node_top TYPE string VALUE 'top', + lc_xml_node_bottom TYPE string VALUE 'bottom', + lc_xml_node_diagonal TYPE string VALUE 'diagonal', + " numfmt + lc_xml_node_numfmts TYPE string VALUE 'numFmts', + lc_xml_node_numfmt TYPE string VALUE 'numFmt', + " Styles + lc_xml_node_cellstylexfs TYPE string VALUE 'cellStyleXfs', + lc_xml_node_xf TYPE string VALUE 'xf', + lc_xml_node_cellxfs TYPE string VALUE 'cellXfs', + lc_xml_node_cellstyles TYPE string VALUE 'cellStyles', + lc_xml_node_cellstyle TYPE string VALUE 'cellStyle', + lc_xml_node_dxfs TYPE string VALUE 'dxfs', + lc_xml_node_dxf TYPE string VALUE 'dxf', + lc_xml_node_tablestyles TYPE string VALUE 'tableStyles', + " Colors + lc_xml_node_colors TYPE string VALUE 'colors', + lc_xml_node_indexedcolors TYPE string VALUE 'indexedColors', + lc_xml_node_rgbcolor TYPE string VALUE 'rgbColor', + lc_xml_node_mrucolors TYPE string VALUE 'mruColors', + " Alignment + lc_xml_node_alignment TYPE string VALUE 'alignment', + " Protection + lc_xml_node_protection TYPE string VALUE 'protection', + " Node attributes + lc_xml_attr_count TYPE string VALUE 'count', + lc_xml_attr_val TYPE string VALUE 'val', + lc_xml_attr_theme TYPE string VALUE 'theme', + lc_xml_attr_rgb TYPE string VALUE 'rgb', + lc_xml_attr_indexed TYPE string VALUE 'indexed', + lc_xml_attr_tint TYPE string VALUE 'tint', + lc_xml_attr_style TYPE string VALUE 'style', + lc_xml_attr_position TYPE string VALUE 'position', + lc_xml_attr_degree TYPE string VALUE 'degree', + lc_xml_attr_patterntype TYPE string VALUE 'patternType', + lc_xml_attr_numfmtid TYPE string VALUE 'numFmtId', + lc_xml_attr_fontid TYPE string VALUE 'fontId', + lc_xml_attr_fillid TYPE string VALUE 'fillId', + lc_xml_attr_borderid TYPE string VALUE 'borderId', + lc_xml_attr_xfid TYPE string VALUE 'xfId', + lc_xml_attr_applynumberformat TYPE string VALUE 'applyNumberFormat', + lc_xml_attr_applyprotection TYPE string VALUE 'applyProtection', + lc_xml_attr_applyfont TYPE string VALUE 'applyFont', + lc_xml_attr_applyfill TYPE string VALUE 'applyFill', + lc_xml_attr_applyborder TYPE string VALUE 'applyBorder', + lc_xml_attr_name TYPE string VALUE 'name', + lc_xml_attr_builtinid TYPE string VALUE 'builtinId', + lc_xml_attr_defaulttablestyle TYPE string VALUE 'defaultTableStyle', + lc_xml_attr_defaultpivotstyle TYPE string VALUE 'defaultPivotStyle', + lc_xml_attr_applyalignment TYPE string VALUE 'applyAlignment', + lc_xml_attr_horizontal TYPE string VALUE 'horizontal', + lc_xml_attr_formatcode TYPE string VALUE 'formatCode', + lc_xml_attr_vertical TYPE string VALUE 'vertical', + lc_xml_attr_wraptext TYPE string VALUE 'wrapText', + lc_xml_attr_textrotation TYPE string VALUE 'textRotation', + lc_xml_attr_shrinktofit TYPE string VALUE 'shrinkToFit', + lc_xml_attr_indent TYPE string VALUE 'indent', + lc_xml_attr_locked TYPE string VALUE 'locked', + lc_xml_attr_hidden TYPE string VALUE 'hidden', + lc_xml_attr_diagonalup TYPE string VALUE 'diagonalUp', + lc_xml_attr_diagonaldown TYPE string VALUE 'diagonalDown', + " Node namespace + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + lc_xml_attr_type TYPE string VALUE 'type', + lc_xml_attr_bottom TYPE string VALUE 'bottom', + lc_xml_attr_top TYPE string VALUE 'top', + lc_xml_attr_right TYPE string VALUE 'right', + lc_xml_attr_left TYPE string VALUE 'left'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element_fonts TYPE REF TO if_ixml_element, + lo_element_font TYPE REF TO if_ixml_element, + lo_element_fills TYPE REF TO if_ixml_element, + lo_element_fill TYPE REF TO if_ixml_element, + lo_element_borders TYPE REF TO if_ixml_element, + lo_element_border TYPE REF TO if_ixml_element, + lo_element_numfmts TYPE REF TO if_ixml_element, + lo_element_numfmt TYPE REF TO if_ixml_element, + lo_element_cellxfs TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_sub_element TYPE REF TO if_ixml_element, + lo_sub_element_2 TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_iterator2 TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_style TYPE REF TO zcl_excel_style. + + + DATA: lt_fonts TYPE zexcel_t_style_font, + ls_font TYPE zexcel_s_style_font, + lt_fills TYPE zexcel_t_style_fill, + ls_fill TYPE zexcel_s_style_fill, + lt_borders TYPE zexcel_t_style_border, + ls_border TYPE zexcel_s_style_border, + lt_numfmts TYPE zexcel_t_style_numfmt, + ls_numfmt TYPE zexcel_s_style_numfmt, + lt_protections TYPE zexcel_t_style_protection, + ls_protection TYPE zexcel_s_style_protection, + lt_alignments TYPE zexcel_t_style_alignment, + ls_alignment TYPE zexcel_s_style_alignment, + lt_cellxfs TYPE zexcel_t_cellxfs, + ls_cellxfs TYPE zexcel_s_cellxfs, + ls_styles_mapping TYPE zexcel_s_styles_mapping, + ls_style_cond_mapping TYPE zexcel_s_styles_cond_mapping, + ls_cellis TYPE zexcel_conditional_cellis, + ls_expression TYPE zexcel_conditional_expression, + ls_conditional_top10 TYPE zexcel_conditional_top10, + + lt_colors TYPE zexcel_t_style_color_argb, + ls_color LIKE LINE OF lt_colors. + + DATA: lv_value TYPE string, + lv_dfx_count TYPE i, + lv_fonts_count TYPE i, + lv_fills_count TYPE i, + lv_borders_count TYPE i, + lv_cellxfs_count TYPE i, + lv_index TYPE i, + lv_align_flag TYPE c. + + TYPES: BEGIN OF ts_built_in_format, + num_format TYPE zexcel_number_format, + id TYPE sytabix, + END OF ts_built_in_format. + + DATA: lt_built_in_num_formats TYPE HASHED TABLE OF ts_built_in_format WITH UNIQUE KEY num_format, + ls_built_in_num_format LIKE LINE OF lt_built_in_num_formats. + FIELD-SYMBOLS: <ls_built_in_format> LIKE LINE OF lt_built_in_num_formats, + <ls_reader_built_in> LIKE LINE OF zcl_excel_style_number_format=>mt_built_in_num_formats. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +*********************************************************************** +* STEP 3: Create main node relationships + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_stylesheet + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + +********************************************************************** +* STEP 4: Create subnodes + + lo_element_fonts = lo_document->create_simple_element( name = lc_xml_node_fonts + parent = lo_document ). + + lo_element_fills = lo_document->create_simple_element( name = lc_xml_node_fills + parent = lo_document ). + + lo_element_borders = lo_document->create_simple_element( name = lc_xml_node_borders + parent = lo_document ). + + lo_element_cellxfs = lo_document->create_simple_element( name = lc_xml_node_cellxfs + parent = lo_document ). + + lo_element_numfmts = lo_document->create_simple_element( name = lc_xml_node_numfmts + parent = lo_document ). + +* Prepare built-in number formats. + LOOP AT zcl_excel_style_number_format=>mt_built_in_num_formats ASSIGNING <ls_reader_built_in>. + ls_built_in_num_format-id = <ls_reader_built_in>-id. + ls_built_in_num_format-num_format = <ls_reader_built_in>-format->format_code. + INSERT ls_built_in_num_format INTO TABLE lt_built_in_num_formats. + ENDLOOP. +* Compress styles + lo_iterator = excel->get_styles_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style ?= lo_iterator->if_object_collection_iterator~get_next( ). + ls_font = lo_style->font->get_structure( ). + ls_fill = lo_style->fill->get_structure( ). + ls_border = lo_style->borders->get_structure( ). + ls_alignment = lo_style->alignment->get_structure( ). + ls_protection = lo_style->protection->get_structure( ). + ls_numfmt = lo_style->number_format->get_structure( ). + + CLEAR ls_cellxfs. + + +* Compress fonts + READ TABLE lt_fonts FROM ls_font TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-fontid = sy-tabix. + ELSE. + APPEND ls_font TO lt_fonts. + DESCRIBE TABLE lt_fonts LINES ls_cellxfs-fontid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-fontid. + +* Compress alignment + READ TABLE lt_alignments FROM ls_alignment TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-alignmentid = sy-tabix. + ELSE. + APPEND ls_alignment TO lt_alignments. + DESCRIBE TABLE lt_alignments LINES ls_cellxfs-alignmentid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-alignmentid. + +* Compress fills + READ TABLE lt_fills FROM ls_fill TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-fillid = sy-tabix. + ELSE. + APPEND ls_fill TO lt_fills. + DESCRIBE TABLE lt_fills LINES ls_cellxfs-fillid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-fillid. + +* Compress borders + READ TABLE lt_borders FROM ls_border TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-borderid = sy-tabix. + ELSE. + APPEND ls_border TO lt_borders. + DESCRIBE TABLE lt_borders LINES ls_cellxfs-borderid. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-borderid. + +* Compress protection + IF ls_protection-locked EQ c_on AND ls_protection-hidden EQ c_off. + ls_cellxfs-applyprotection = 0. + ELSE. + READ TABLE lt_protections FROM ls_protection TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-protectionid = sy-tabix. + ELSE. + APPEND ls_protection TO lt_protections. + DESCRIBE TABLE lt_protections LINES ls_cellxfs-protectionid. + ENDIF. + ls_cellxfs-applyprotection = 1. + ENDIF. + SUBTRACT 1 FROM ls_cellxfs-protectionid. + +* Compress number formats + + "----------- + IF ls_numfmt-numfmt NE zcl_excel_style_number_format=>c_format_date_std." and ls_numfmt-NUMFMT ne 'STD_NDEC'. " ALE Changes on going + "--- + IF ls_numfmt IS NOT INITIAL. +* issue #389 - Problem with built-in format ( those are not being taken account of ) +* There are some internal number formats built-in into EXCEL +* Use these instead of duplicating the entries here, since they seem to be language-dependant and adjust to user settings in excel + READ TABLE lt_built_in_num_formats ASSIGNING <ls_built_in_format> WITH TABLE KEY num_format = ls_numfmt-numfmt. + IF sy-subrc = 0. + ls_cellxfs-numfmtid = <ls_built_in_format>-id. + ELSE. + READ TABLE lt_numfmts FROM ls_numfmt TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_cellxfs-numfmtid = sy-tabix. + ELSE. + APPEND ls_numfmt TO lt_numfmts. + DESCRIBE TABLE lt_numfmts LINES ls_cellxfs-numfmtid. + ENDIF. + ADD zcl_excel_common=>c_excel_numfmt_offset TO ls_cellxfs-numfmtid. " Add OXML offset for custom styles + ENDIF. + ls_cellxfs-applynumberformat = 1. + ELSE. + ls_cellxfs-applynumberformat = 0. + ENDIF. + "----------- " ALE changes on going + ELSE. + ls_cellxfs-applynumberformat = 1. + IF ls_numfmt-numfmt EQ zcl_excel_style_number_format=>c_format_date_std. + ls_cellxfs-numfmtid = 14. +* elseif ls_numfmt-NUMFMT eq 'STD_NDEC'. +* ls_cellxfs-numfmtid = 2. + ENDIF. + ENDIF. + "--- + + IF ls_cellxfs-fontid NE 0. + ls_cellxfs-applyfont = 1. + ELSE. + ls_cellxfs-applyfont = 0. + ENDIF. + IF ls_cellxfs-alignmentid NE 0. + ls_cellxfs-applyalignment = 1. + ELSE. + ls_cellxfs-applyalignment = 0. + ENDIF. + IF ls_cellxfs-fillid NE 0. + ls_cellxfs-applyfill = 1. + ELSE. + ls_cellxfs-applyfill = 0. + ENDIF. + IF ls_cellxfs-borderid NE 0. + ls_cellxfs-applyborder = 1. + ELSE. + ls_cellxfs-applyborder = 0. + ENDIF. + +* Remap styles + READ TABLE lt_cellxfs FROM ls_cellxfs TRANSPORTING NO FIELDS. + IF sy-subrc EQ 0. + ls_styles_mapping-style = sy-tabix. + ELSE. + APPEND ls_cellxfs TO lt_cellxfs. + DESCRIBE TABLE lt_cellxfs LINES ls_styles_mapping-style. + ENDIF. + SUBTRACT 1 FROM ls_styles_mapping-style. + ls_styles_mapping-guid = lo_style->get_guid( ). + APPEND ls_styles_mapping TO me->styles_mapping. + ENDWHILE. + + " create numfmt elements + LOOP AT lt_numfmts INTO ls_numfmt. + lo_element_numfmt = lo_document->create_simple_element( name = lc_xml_node_numfmt + parent = lo_document ). + lv_value = sy-tabix + zcl_excel_common=>c_excel_numfmt_offset. + CONDENSE lv_value. + lo_element_numfmt->set_attribute_ns( name = lc_xml_attr_numfmtid + value = lv_value ). + lv_value = ls_numfmt-numfmt. +* REPLACE ALL OCCURRENCES OF '.' IN lv_value WITH '\.'. + lo_element_numfmt->set_attribute_ns( name = lc_xml_attr_formatcode + value = lv_value ). + lo_element_numfmts->append_child( new_child = lo_element_numfmt ). + ENDLOOP. + + " create font elements + LOOP AT lt_fonts INTO ls_font. + lo_element_font = lo_document->create_simple_element( name = lc_xml_node_font + parent = lo_document ). + IF ls_font-bold EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_b + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + IF ls_font-italic EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_i + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + IF ls_font-underline EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_u + parent = lo_document ). + lv_value = ls_font-underline_mode. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + IF ls_font-strikethrough EQ abap_true. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_strike + parent = lo_document ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + "size + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_sz + parent = lo_document ). + lv_value = ls_font-size. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + "color + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_element_font + is_color = ls_font-color ). + + "name + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_name + parent = lo_document ). + lv_value = ls_font-name. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + "family + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_family + parent = lo_document ). + lv_value = ls_font-family. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + "scheme + IF ls_font-scheme IS NOT INITIAL. + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_scheme + parent = lo_document ). + lv_value = ls_font-scheme. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_val + value = lv_value ). + lo_element_font->append_child( new_child = lo_sub_element ). + ENDIF. + lo_element_fonts->append_child( new_child = lo_element_font ). + ENDLOOP. + + " create fill elements + LOOP AT lt_fills INTO ls_fill. + lo_element_fill = lo_document->create_simple_element( name = lc_xml_node_fill + parent = lo_document ). + + IF ls_fill-gradtype IS NOT INITIAL. + "gradient + + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_gradientfill + parent = lo_document ). + IF ls_fill-gradtype-degree IS NOT INITIAL. + lv_value = ls_fill-gradtype-degree. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_degree value = lv_value ). + ENDIF. + IF ls_fill-gradtype-type IS NOT INITIAL. + lv_value = ls_fill-gradtype-type. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_type value = lv_value ). + ENDIF. + IF ls_fill-gradtype-bottom IS NOT INITIAL. + lv_value = ls_fill-gradtype-bottom. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_bottom value = lv_value ). + ENDIF. + IF ls_fill-gradtype-top IS NOT INITIAL. + lv_value = ls_fill-gradtype-top. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_top value = lv_value ). + ENDIF. + IF ls_fill-gradtype-right IS NOT INITIAL. + lv_value = ls_fill-gradtype-right. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_right value = lv_value ). + ENDIF. + IF ls_fill-gradtype-left IS NOT INITIAL. + lv_value = ls_fill-gradtype-left. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_left value = lv_value ). + ENDIF. + + IF ls_fill-gradtype-position3 IS NOT INITIAL. + "create <stop> elements for gradients, we can have 2 or 3 stops in each gradient + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + lv_value = ls_fill-gradtype-position1. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position value = lv_value ). + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + + lv_value = ls_fill-gradtype-position2. + + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position + value = lv_value ). + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + + lv_value = ls_fill-gradtype-position3. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position + value = lv_value ). + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + ELSE. + "create <stop> elements for gradients, we can have 2 or 3 stops in each gradient + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + lv_value = ls_fill-gradtype-position1. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position value = lv_value ). + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_stop + parent = lo_sub_element ). + + lv_value = ls_fill-gradtype-position2. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_position + value = lv_value ). + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element_2 + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_color ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + + + + + ELSE. + "pattern + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_patternfill + parent = lo_document ). + lv_value = ls_fill-filltype. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_patterntype + value = lv_value ). + " fgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_fill-fgcolor + iv_color_elem_name = lc_xml_node_fgcolor ). + + IF ls_fill-fgcolor-rgb IS INITIAL AND + ls_fill-fgcolor-indexed EQ zcl_excel_style_color=>c_indexed_not_set AND + ls_fill-fgcolor-theme EQ zcl_excel_style_color=>c_theme_not_set AND + ls_fill-fgcolor-tint IS INITIAL AND ls_fill-bgcolor-indexed EQ zcl_excel_style_color=>c_indexed_sys_foreground. + + " bgcolor + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_fill-bgcolor + iv_color_elem_name = lc_xml_node_bgcolor ). + + ENDIF. + ENDIF. + + lo_element_fill->append_child( new_child = lo_sub_element )."pattern + lo_element_fills->append_child( new_child = lo_element_fill ). + ENDLOOP. + + " create border elements + LOOP AT lt_borders INTO ls_border. + lo_element_border = lo_document->create_simple_element( name = lc_xml_node_border + parent = lo_document ). + + IF ls_border-diagonalup IS NOT INITIAL. + lv_value = ls_border-diagonalup. + CONDENSE lv_value. + lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonalup + value = lv_value ). + ENDIF. + + IF ls_border-diagonaldown IS NOT INITIAL. + lv_value = ls_border-diagonaldown. + CONDENSE lv_value. + lo_element_border->set_attribute_ns( name = lc_xml_attr_diagonaldown + value = lv_value ). + ENDIF. + + "left + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_left + parent = lo_document ). + IF ls_border-left_style IS NOT INITIAL. + lv_value = ls_border-left_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-left_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "right + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_right + parent = lo_document ). + IF ls_border-right_style IS NOT INITIAL. + lv_value = ls_border-right_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-right_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "top + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_top + parent = lo_document ). + IF ls_border-top_style IS NOT INITIAL. + lv_value = ls_border-top_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-top_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "bottom + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_bottom + parent = lo_document ). + IF ls_border-bottom_style IS NOT INITIAL. + lv_value = ls_border-bottom_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-bottom_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + + "diagonal + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_diagonal + parent = lo_document ). + IF ls_border-diagonal_style IS NOT INITIAL. + lv_value = ls_border-diagonal_style. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_style + value = lv_value ). + ENDIF. + + create_xl_styles_color_node( + io_document = lo_document + io_parent = lo_sub_element + is_color = ls_border-diagonal_color ). + + lo_element_border->append_child( new_child = lo_sub_element ). + lo_element_borders->append_child( new_child = lo_element_border ). + ENDLOOP. + + " update attribute "count" + DESCRIBE TABLE lt_fonts LINES lv_fonts_count. + MOVE lv_fonts_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_fonts->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_fills LINES lv_fills_count. + MOVE lv_fills_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_fills->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_borders LINES lv_borders_count. + MOVE lv_borders_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_borders->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + DESCRIBE TABLE lt_cellxfs LINES lv_cellxfs_count. + MOVE lv_cellxfs_count TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element_cellxfs->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + + " Append to root node + lo_element_root->append_child( new_child = lo_element_numfmts ). + lo_element_root->append_child( new_child = lo_element_fonts ). + lo_element_root->append_child( new_child = lo_element_fills ). + lo_element_root->append_child( new_child = lo_element_borders ). + + " cellstylexfs node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstylexfs + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '1' ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_xf + parent = lo_document ). + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_numfmtid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_fontid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_fillid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_borderid + value = c_off ). + + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + + LOOP AT lt_cellxfs INTO ls_cellxfs. + lo_element = lo_document->create_simple_element( name = lc_xml_node_xf + parent = lo_document ). + MOVE ls_cellxfs-numfmtid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_numfmtid + value = lv_value ). + MOVE ls_cellxfs-fontid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_fontid + value = lv_value ). + MOVE ls_cellxfs-fillid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_fillid + value = lv_value ). + MOVE ls_cellxfs-borderid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_borderid + value = lv_value ). + MOVE ls_cellxfs-xfid TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_xfid + value = lv_value ). + IF ls_cellxfs-applynumberformat EQ 1. + MOVE ls_cellxfs-applynumberformat TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applynumberformat + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyfont EQ 1. + MOVE ls_cellxfs-applyfont TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyfont + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyfill EQ 1. + MOVE ls_cellxfs-applyfill TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyfill + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyborder EQ 1. + MOVE ls_cellxfs-applyborder TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyborder + value = lv_value ). + ENDIF. + IF ls_cellxfs-applyalignment EQ 1. " depends on each style not for all the sheet + MOVE ls_cellxfs-applyalignment TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_element->set_attribute_ns( name = lc_xml_attr_applyalignment + value = lv_value ). + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_alignment + parent = lo_document ). + ADD 1 TO ls_cellxfs-alignmentid. "Table index starts from 1 + READ TABLE lt_alignments INTO ls_alignment INDEX ls_cellxfs-alignmentid. + SUBTRACT 1 FROM ls_cellxfs-alignmentid. + IF ls_alignment-horizontal IS NOT INITIAL. + MOVE ls_alignment-horizontal TO lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_horizontal + value = lv_value ). + ENDIF. + IF ls_alignment-vertical IS NOT INITIAL. + MOVE ls_alignment-vertical TO lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_vertical + value = lv_value ). + ENDIF. + IF ls_alignment-wraptext EQ abap_true. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_wraptext + value = c_on ). + ENDIF. + IF ls_alignment-textrotation IS NOT INITIAL. + MOVE ls_alignment-textrotation TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_textrotation + value = lv_value ). + ENDIF. + IF ls_alignment-shrinktofit EQ abap_true. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_shrinktofit + value = c_on ). + ENDIF. + IF ls_alignment-indent IS NOT INITIAL. + MOVE ls_alignment-indent TO lv_value. + SHIFT lv_value RIGHT DELETING TRAILING space. + SHIFT lv_value LEFT DELETING LEADING space. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_indent + value = lv_value ). + ENDIF. + + lo_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + IF ls_cellxfs-applyprotection EQ 1. + MOVE ls_cellxfs-applyprotection TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_applyprotection + value = lv_value ). + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_protection + parent = lo_document ). + ADD 1 TO ls_cellxfs-protectionid. "Table index starts from 1 + READ TABLE lt_protections INTO ls_protection INDEX ls_cellxfs-protectionid. + SUBTRACT 1 FROM ls_cellxfs-protectionid. + IF ls_protection-locked IS NOT INITIAL. + MOVE ls_protection-locked TO lv_value. + CONDENSE lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_locked + value = lv_value ). + ENDIF. + IF ls_protection-hidden IS NOT INITIAL. + MOVE ls_protection-hidden TO lv_value. + CONDENSE lv_value. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_hidden + value = lv_value ). + ENDIF. + lo_element->append_child( new_child = lo_sub_element_2 ). + ENDIF. + lo_element_cellxfs->append_child( new_child = lo_element ). + ENDLOOP. + + lo_element_root->append_child( new_child = lo_element_cellxfs ). + + " cellStyles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_cellstyles + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '1' ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_cellstyle + parent = lo_document ). + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = 'Normal' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_xfid + value = c_off ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_builtinid + value = c_off ). + + lo_element->append_child( new_child = lo_sub_element ). + lo_element_root->append_child( new_child = lo_element ). + + " dxfs node + lo_element = lo_document->create_simple_element( name = lc_xml_node_dxfs + parent = lo_document ). + + lo_iterator = me->excel->get_worksheets_iterator( ). + " get sheets + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + " Conditional formatting styles into exch sheet + lo_iterator2 = lo_worksheet->get_cond_styles_iterator( ). + WHILE lo_iterator2->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style_conditional ?= lo_iterator2->if_object_collection_iterator~get_next( ). + CASE lo_style_conditional->rule. +* begin of change issue #366 - missing conditional rules: top10, move dfx-styles to own method + WHEN zcl_excel_style_conditional=>c_rule_cellis. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_cellis-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). + + WHEN zcl_excel_style_conditional=>c_rule_expression. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_expression-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). + + + + WHEN zcl_excel_style_conditional=>c_rule_top10. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_top10-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). + + WHEN zcl_excel_style_conditional=>c_rule_above_average. + me->create_dxf_style( EXPORTING + iv_cell_style = lo_style_conditional->mode_above_average-cell_style + io_dxf_element = lo_element + io_ixml_document = lo_document + it_cellxfs = lt_cellxfs + it_fonts = lt_fonts + it_fills = lt_fills + CHANGING + cv_dfx_count = lv_dfx_count ). +* begin of change issue #366 - missing conditional rules: top10, move dfx-styles to own method + + WHEN OTHERS. + CONTINUE. + ENDCASE. + ENDWHILE. + ENDWHILE. + + lv_value = lv_dfx_count. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + + " tableStyles node + lo_element = lo_document->create_simple_element( name = lc_xml_node_tablestyles + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_count + value = '0' ). + lo_element->set_attribute_ns( name = lc_xml_attr_defaulttablestyle + value = zcl_excel_table=>builtinstyle_medium9 ). + lo_element->set_attribute_ns( name = lc_xml_attr_defaultpivotstyle + value = zcl_excel_table=>builtinstyle_pivot_light16 ). + lo_element_root->append_child( new_child = lo_element ). + + "write legacy color palette in case any indexed color was changed + IF excel->legacy_palette->is_modified( ) = abap_true. + lo_element = lo_document->create_simple_element( name = lc_xml_node_colors + parent = lo_document ). + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_indexedcolors + parent = lo_document ). + lo_element->append_child( new_child = lo_sub_element ). + + lt_colors = excel->legacy_palette->get_colors( ). + LOOP AT lt_colors INTO ls_color. + lo_sub_element_2 = lo_document->create_simple_element( name = lc_xml_node_rgbcolor + parent = lo_document ). + lv_value = ls_color. + lo_sub_element_2->set_attribute_ns( name = lc_xml_attr_rgb + value = lv_value ). + lo_sub_element->append_child( new_child = lo_sub_element_2 ). + ENDLOOP. + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + + + + + METHOD create_xl_styles_color_node. + DATA: lo_sub_element TYPE REF TO if_ixml_element, + lv_value TYPE string. + + CONSTANTS: lc_xml_attr_theme TYPE string VALUE 'theme', + lc_xml_attr_rgb TYPE string VALUE 'rgb', + lc_xml_attr_indexed TYPE string VALUE 'indexed', + lc_xml_attr_tint TYPE string VALUE 'tint'. + + "add node only if at least one attribute is set + CHECK is_color-rgb IS NOT INITIAL OR + is_color-indexed <> zcl_excel_style_color=>c_indexed_not_set OR + is_color-theme <> zcl_excel_style_color=>c_theme_not_set OR + is_color-tint IS NOT INITIAL. + + lo_sub_element = io_document->create_simple_element( + name = iv_color_elem_name + parent = io_parent ). + + IF is_color-rgb IS NOT INITIAL. + lv_value = is_color-rgb. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_rgb + value = lv_value ). + ENDIF. + + IF is_color-indexed <> zcl_excel_style_color=>c_indexed_not_set. + lv_value = zcl_excel_common=>number_to_excel_string( is_color-indexed ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_indexed + value = lv_value ). + ENDIF. + + IF is_color-theme <> zcl_excel_style_color=>c_theme_not_set. + lv_value = zcl_excel_common=>number_to_excel_string( is_color-theme ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_theme + value = lv_value ). + ENDIF. + + IF is_color-tint IS NOT INITIAL. + lv_value = zcl_excel_common=>number_to_excel_string( is_color-tint ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_tint + value = lv_value ). + ENDIF. + + io_parent->append_child( new_child = lo_sub_element ). +ENDMETHOD. + + + + + METHOD create_xl_table. + + DATA: lc_xml_node_table TYPE string VALUE 'table', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'id', + lc_xml_attr_name TYPE string VALUE 'name', + lc_xml_attr_display_name TYPE string VALUE 'displayName', + lc_xml_attr_ref TYPE string VALUE 'ref', + lc_xml_attr_totals TYPE string VALUE 'totalsRowShown', + " Node namespace + lc_xml_node_table_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_element2 TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + + lv_table_name TYPE string, + lv_id TYPE i, + lv_match TYPE i, + lv_syindex TYPE char3, + lv_ref TYPE string, + lv_value TYPE string, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lv_num_columns TYPE i, + ls_fieldcat TYPE zexcel_s_fieldcatalog. + + +********************************************************************** +* STEP 1: Create xml + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node table + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_table + parent = lo_document ). + + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_table_ns ). + + lv_id = io_table->get_id( ). + lv_value = zcl_excel_common=>number_to_excel_string( ip_value = lv_id ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_id + value = lv_value ). + + FIND ALL OCCURRENCES OF REGEX '[^_a-zA-Z0-9]' IN io_table->settings-table_name IGNORING CASE MATCH COUNT lv_match. + IF io_table->settings-table_name IS NOT INITIAL AND lv_match EQ 0. + lv_table_name = io_table->settings-table_name. + ELSE. + lv_table_name = io_table->get_name( ). + ENDIF. + lo_element_root->set_attribute_ns( name = lc_xml_attr_name + value = lv_table_name ). + + lo_element_root->set_attribute_ns( name = lc_xml_attr_display_name + value = lv_table_name ). + + lv_ref = io_table->get_reference( ). + lo_element_root->set_attribute_ns( name = lc_xml_attr_ref + value = lv_ref ). + IF io_table->has_totals( ) = abap_true. + lo_element_root->set_attribute_ns( name = 'totalsRowCount' + value = '1' ). + ELSE. + lo_element_root->set_attribute_ns( name = lc_xml_attr_totals + value = '0' ). + ENDIF. + +********************************************************************** +* STEP 4: Create subnodes + + " autoFilter + IF io_table->settings-nofilters EQ abap_false. + lo_element = lo_document->create_simple_element( name = 'autoFilter' + parent = lo_document ). + + lv_ref = io_table->get_reference( ip_include_totals_row = abap_false ). + lo_element->set_attribute_ns( name = 'ref' + value = lv_ref ). + + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + "columns + lo_element = lo_document->create_simple_element( name = 'tableColumns' + parent = lo_document ). + +* lo_columns = io_table->get_columns( ). + LOOP AT io_table->fieldcat INTO ls_fieldcat WHERE dynpfld = abap_true. + ADD 1 TO lv_num_columns. + ENDLOOP. + + lv_value = lv_num_columns. + CONDENSE lv_value. + lo_element->set_attribute_ns( name = 'count' + value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). + + LOOP AT io_table->fieldcat INTO ls_fieldcat WHERE dynpfld = abap_true. + lo_element2 = lo_document->create_simple_element_ns( name = 'tableColumn' + parent = lo_element ). + + lv_value = ls_fieldcat-position. + SHIFT lv_value LEFT DELETING LEADING '0'. + lo_element2->set_attribute_ns( name = 'id' + value = lv_value ). + lv_value = ls_fieldcat-scrtext_l. + lo_element2->set_attribute_ns( name = 'name' + value = lv_value ). + + IF ls_fieldcat-totals_function IS NOT INITIAL. + lo_element2->set_attribute_ns( name = 'totalsRowFunction' + value = ls_fieldcat-totals_function ). + ENDIF. + + lo_element->append_child( new_child = lo_element2 ). + ENDLOOP. + + + lo_element = lo_document->create_simple_element( name = 'tableStyleInfo' + parent = lo_element_root ). + + lo_element->set_attribute_ns( name = 'name' + value = io_table->settings-table_style ). + + lo_element->set_attribute_ns( name = 'showFirstColumn' + value = '0' ). + + lo_element->set_attribute_ns( name = 'showLastColumn' + value = '0' ). + + IF io_table->settings-show_row_stripes = abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + + lo_element->set_attribute_ns( name = 'showRowStripes' + value = lv_value ). + + IF io_table->settings-show_column_stripes = abap_true. + lv_value = '1'. + ELSE. + lv_value = '0'. + ENDIF. + + lo_element->set_attribute_ns( name = 'showColumnStripes' + value = lv_value ). + + lo_element_root->append_child( new_child = lo_element ). +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + + method create_xl_theme. + data: lo_theme type ref to zcl_excel_theme. + + excel->get_theme( + importing + eo_theme = lo_theme + ). + if lo_theme is initial. + create object lo_theme. + endif. + ep_content = lo_theme->write_theme( ). + +endmethod. + + + + METHOD create_xl_workbook. +*--------------------------------------------------------------------* +* issue #230 - Pimp my Code +* - Stefan Schmoecker, (done) 2012-11-07 +* - ... +* changes: aligning code +* adding comments to explain what we are trying to achieve +*--------------------------------------------------------------------* +* issue#235 - repeat rows/columns +* - Stefan Schmoecker, 2012-12-01 +* changes: correction of pointer to localSheetId +*--------------------------------------------------------------------* + +** Constant node name + DATA: lc_xml_node_workbook TYPE string VALUE 'workbook', + lc_xml_node_fileversion TYPE string VALUE 'fileVersion', + lc_xml_node_workbookpr TYPE string VALUE 'workbookPr', + lc_xml_node_bookviews TYPE string VALUE 'bookViews', + lc_xml_node_workbookview TYPE string VALUE 'workbookView', + lc_xml_node_sheets TYPE string VALUE 'sheets', + lc_xml_node_sheet TYPE string VALUE 'sheet', + lc_xml_node_calcpr TYPE string VALUE 'calcPr', + lc_xml_node_workbookprotection TYPE string VALUE 'workbookProtection', + lc_xml_node_definednames TYPE string VALUE 'definedNames', + lc_xml_node_definedname TYPE string VALUE 'definedName', + " Node attributes + lc_xml_attr_appname TYPE string VALUE 'appName', + lc_xml_attr_lastedited TYPE string VALUE 'lastEdited', + lc_xml_attr_lowestedited TYPE string VALUE 'lowestEdited', + lc_xml_attr_rupbuild TYPE string VALUE 'rupBuild', + lc_xml_attr_themeversion TYPE string VALUE 'defaultThemeVersion', + lc_xml_attr_xwindow TYPE string VALUE 'xWindow', + lc_xml_attr_ywindow TYPE string VALUE 'yWindow', + lc_xml_attr_windowwidth TYPE string VALUE 'windowWidth', + lc_xml_attr_windowheight TYPE string VALUE 'windowHeight', + lc_xml_attr_activetab TYPE string VALUE 'activeTab', + lc_xml_attr_name TYPE string VALUE 'name', + lc_xml_attr_sheetid TYPE string VALUE 'sheetId', + lc_xml_attr_state TYPE string VALUE 'state', + lc_xml_attr_id TYPE string VALUE 'id', + lc_xml_attr_calcid TYPE string VALUE 'calcId', + lc_xml_attr_lockrevision TYPE string VALUE 'lockRevision', + lc_xml_attr_lockstructure TYPE string VALUE 'lockStructure', + lc_xml_attr_lockwindows TYPE string VALUE 'lockWindows', + lc_xml_attr_revisionspassword TYPE string VALUE 'revisionsPassword', + lc_xml_attr_workbookpassword TYPE string VALUE 'workbookPassword', + lc_xml_attr_hidden TYPE string VALUE 'hidden', + lc_xml_attr_localsheetid TYPE string VALUE 'localSheetId', + " Node namespace + lc_r_ns TYPE string VALUE 'r', + lc_xml_node_ns TYPE string VALUE 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + lc_xml_node_r_ns TYPE string VALUE 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_element_root TYPE REF TO if_ixml_element, + lo_element TYPE REF TO if_ixml_element, + lo_element_range TYPE REF TO if_ixml_element, + lo_sub_element TYPE REF TO if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_iterator_range TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lo_autofilters TYPE REF TO zcl_excel_autofilters, + lo_autofilter TYPE REF TO zcl_excel_autofilter. + + DATA: lv_xml_node_ridx_id TYPE string, + lv_value TYPE string, + lv_syindex TYPE string, + l_guid TYPE uuid, + lv_active_sheet TYPE zexcel_active_worksheet. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + +********************************************************************** +* STEP 3: Create main node + lo_element_root = lo_document->create_simple_element( name = lc_xml_node_workbook + parent = lo_document ). + lo_element_root->set_attribute_ns( name = 'xmlns' + value = lc_xml_node_ns ). + lo_element_root->set_attribute_ns( name = 'xmlns:r' + value = lc_xml_node_r_ns ). + +********************************************************************** +* STEP 4: Create subnode + " fileVersion node + lo_element = lo_document->create_simple_element( name = lc_xml_node_fileversion + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_appname + value = 'xl' ). + lo_element->set_attribute_ns( name = lc_xml_attr_lastedited + value = '4' ). + lo_element->set_attribute_ns( name = lc_xml_attr_lowestedited + value = '4' ). + lo_element->set_attribute_ns( name = lc_xml_attr_rupbuild + value = '4506' ). + lo_element_root->append_child( new_child = lo_element ). + + " fileVersion node + lo_element = lo_document->create_simple_element( name = lc_xml_node_workbookpr + parent = lo_document ). +* lo_element->set_attribute_ns( name = lc_xml_attr_themeversion +* value = '124226' ). + lo_element_root->append_child( new_child = lo_element ). + + " workbookProtection node + IF me->excel->zif_excel_book_protection~protected EQ abap_true. + lo_element = lo_document->create_simple_element( name = lc_xml_node_workbookprotection + parent = lo_document ). + MOVE me->excel->zif_excel_book_protection~workbookpassword TO lv_value. + IF lv_value IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_workbookpassword + value = lv_value ). + ENDIF. + MOVE me->excel->zif_excel_book_protection~revisionspassword TO lv_value. + IF lv_value IS NOT INITIAL. + lo_element->set_attribute_ns( name = lc_xml_attr_revisionspassword + value = lv_value ). + ENDIF. + MOVE me->excel->zif_excel_book_protection~lockrevision TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_lockrevision + value = lv_value ). + MOVE me->excel->zif_excel_book_protection~lockstructure TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_lockstructure + value = lv_value ). + MOVE me->excel->zif_excel_book_protection~lockwindows TO lv_value. + CONDENSE lv_value NO-GAPS. + lo_element->set_attribute_ns( name = lc_xml_attr_lockwindows + value = lv_value ). + lo_element_root->append_child( new_child = lo_element ). + ENDIF. + + " bookviews node + lo_element = lo_document->create_simple_element( name = lc_xml_node_bookviews + parent = lo_document ). + " bookview node + lo_sub_element = lo_document->create_simple_element( name = lc_xml_node_workbookview + parent = lo_document ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_xwindow + value = '120' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_ywindow + value = '120' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_windowwidth + value = '19035' ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_windowheight + value = '8445' ). + " Set Active Sheet + lv_active_sheet = excel->get_active_sheet_index( ). +* issue #365 - test if sheet exists - otherwise set active worksheet to 1 + lo_worksheet = excel->get_worksheet_by_index( lv_active_sheet ). + IF lo_worksheet IS NOT BOUND. + lv_active_sheet = 1. + excel->SET_ACTIVE_SHEET_INDEX( lv_active_sheet ). + ENDIF. + IF lv_active_sheet > 1. + lv_active_sheet = lv_active_sheet - 1. + lv_value = lv_active_sheet. + CONDENSE lv_value. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_activetab + value = lv_value ). + ENDIF. + lo_element->append_child( new_child = lo_sub_element )." bookview node + lo_element_root->append_child( new_child = lo_element )." bookviews node + + " sheets node + lo_element = lo_document->create_simple_element( name = lc_xml_node_sheets + parent = lo_document ). + lo_iterator = excel->get_worksheets_iterator( ). + + " ranges node + lo_element_range = lo_document->create_simple_element( name = lc_xml_node_definednames " issue 163 + + parent = lo_document ). " issue 163 + + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + " sheet node + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_sheet + parent = lo_document ). + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_syindex = sy-index. " question by Stefan Schmöcker 2012-12-02: sy-index seems to do the job - but is it proven to work or purely coincedence + lv_value = lo_worksheet->get_title( ). + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + lo_sub_element->set_attribute_ns( name = lc_xml_attr_sheetid + value = lv_syindex ). + IF lo_worksheet->zif_excel_sheet_properties~hidden EQ zif_excel_sheet_properties=>c_hidden. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_state + value = 'hidden' ). + ELSEIF lo_worksheet->zif_excel_sheet_properties~hidden EQ zif_excel_sheet_properties=>c_veryhidden. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_state + value = 'veryHidden' ). + ENDIF. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_id + prefix = lc_r_ns + value = lv_xml_node_ridx_id ). + lo_element->append_child( new_child = lo_sub_element ). " sheet node + + " issue 163 >>> + lo_iterator_range = lo_worksheet->get_ranges_iterator( ). + +*--------------------------------------------------------------------* +* Defined names sheetlocal: Ranges, Repeat rows and columns +*--------------------------------------------------------------------* + WHILE lo_iterator_range->if_object_collection_iterator~has_next( ) EQ abap_true. + " range node + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_definedname + parent = lo_document ). + lo_range ?= lo_iterator_range->if_object_collection_iterator~get_next( ). + lv_value = lo_range->name. + + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + +* lo_sub_element->set_attribute_ns( name = lc_xml_attr_localsheetid "del #235 Repeat rows/cols - EXCEL starts couting from zero +* value = lv_xml_node_ridx_id ). "del #235 Repeat rows/cols - and needs absolute referencing to localSheetId + lv_value = lv_syindex - 1. "ins #235 Repeat rows/cols + CONDENSE lv_value NO-GAPS. "ins #235 Repeat rows/cols + lo_sub_element->set_attribute_ns( name = lc_xml_attr_localsheetid + value = lv_value ). + + lv_value = lo_range->get_value( ). + lo_sub_element->set_value( value = lv_value ). + lo_element_range->append_child( new_child = lo_sub_element ). " range node + + ENDWHILE. + " issue 163 <<< + + ENDWHILE. + lo_element_root->append_child( new_child = lo_element )." sheets node + + +*--------------------------------------------------------------------* +* Defined names workbookgolbal: Ranges +*--------------------------------------------------------------------* +* " ranges node +* lo_element = lo_document->create_simple_element( name = lc_xml_node_definednames " issue 163 - +* parent = lo_document ). " issue 163 - + lo_iterator = excel->get_ranges_iterator( ). + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + " range node + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_definedname + parent = lo_document ). + lo_range ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_value = lo_range->name. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + lv_value = lo_range->get_value( ). + lo_sub_element->set_value( value = lv_value ). + lo_element_range->append_child( new_child = lo_sub_element ). " range node + + ENDWHILE. + +*--------------------------------------------------------------------* +* Defined names - Autofilters ( also sheetlocal ) +*--------------------------------------------------------------------* + lo_autofilters = excel->get_autofilters_reference( ). + IF lo_autofilters->is_empty( ) = abap_false. + lo_iterator = excel->get_worksheets_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + lv_syindex = sy-index - 1 . + l_guid = lo_worksheet->get_guid( ). + lo_autofilter = lo_autofilters->get( i_sheet_guid = l_guid ) . + IF lo_autofilter IS BOUND. + lo_sub_element = lo_document->create_simple_element_ns( name = lc_xml_node_definedname + parent = lo_document ). + lv_value = lo_autofilters->c_autofilter. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_name + value = lv_value ). + lv_value = lv_syindex. + CONDENSE lv_value NO-GAPS. + lo_sub_element->set_attribute_ns( name = lc_xml_attr_localsheetid + value = lv_value ). + lv_value = '1'. " Always hidden + lo_sub_element->set_attribute_ns( name = lc_xml_attr_hidden + value = lv_value ). + lv_value = lo_autofilter->get_filter_reference( ). + lo_sub_element->set_value( value = lv_value ). + lo_element_range->append_child( new_child = lo_sub_element ). " range node + ENDIF. + + ENDWHILE. + ENDIF. + lo_element_root->append_child( new_child = lo_element_range ). " ranges node + + + " calcPr node + lo_element = lo_document->create_simple_element( name = lc_xml_node_calcpr + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_calcid + value = '125725' ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + + + method FLAG2BOOL. + + + IF ip_flag EQ abap_true. + ep_boolean = 'true'. + ELSE. + ep_boolean = 'false'. + ENDIF. + endmethod. + + + + + METHOD get_shared_string_index. + + + DATA ls_shared_string TYPE zexcel_s_shared_string. + +* READ TABLE shared_strings INTO ls_shared_string WITH KEY string_value = ip_cell_value BINARY SEARCH. + READ TABLE shared_strings INTO ls_shared_string WITH TABLE KEY string_value = ip_cell_value. + ep_index = ls_shared_string-string_no. + +ENDMETHOD. + + + + + METHOD render_ixml_element_no_header. + +* + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, +* lo_element_root type ref to if_ixml_element, +* lo_element type ref to if_ixml_element, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + + DATA: lv_content TYPE string. + DATA: lv_contentx TYPE xstring. + +********************************************************************** +* STEP 1: Create [Content_Types].xml into the root of the ZIP + lo_ixml = cl_ixml=>create( ). + +********************************************************************** +* STEP 2: Set document attributes + lo_encoding = lo_ixml->create_encoding( byte_order = if_ixml_encoding=>co_platform_endian + character_set = 'utf-8' ). + lo_document = lo_ixml->create_document( ). + lo_document->set_encoding( lo_encoding ). + lo_document->set_standalone( abap_true ). + lo_document->set_declaration( abap_false ). " NO header!! + + lo_document->append_child( new_child = iv_ixml_element ). + + +********************************************************************** +* STEP 5: Create xstring stream + lo_streamfactory = lo_ixml->create_stream_factory( ). +* lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_ostream = lo_streamfactory->create_ostream_cstring( string = lv_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +* write:/ lv_content. + + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = rv_xstring ). +* lo_ostream = lo_streamfactory->create_ostream_cstring( string = lv_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + + +* rv_xstring = lv_contentx. + +ENDMETHOD. + + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + method ZIF_EXCEL_WRITER~WRITE_FILE. + me->excel = io_excel. + ep_file = me->create( ). + endmethod. + + + + method CREATE. + +* .csv format with ; delimiter + + ep_excel = me->CREATE_CSV( ). + + endmethod. + + + + method CREATE_CSV. + + TYPES: BEGIN OF lty_format, + cmpname TYPE SEOCMPNAME, + attvalue TYPE SEOVALUE, + END OF lty_format. + DATA: lt_format TYPE STANDARD TABLE OF lty_format, + ls_format LIKE LINE OF lt_format, + lv_date TYPE DATS, + lv_tmp TYPE string, + lv_time TYPE CHAR08. + + DATA: lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + DATA: lt_cell_data TYPE zexcel_t_cell_data_unsorted, + lv_row TYPE sytabix, + lv_col TYPE sytabix, + lv_string TYPE string, + lc_value TYPE string, + lv_attrname TYPE SEOCMPNAME. + + DATA: ls_numfmt TYPE zexcel_s_style_numfmt, + lo_style TYPE REF TO zcl_excel_style. + + FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data. + +* --- Retrieve supported cell format + REFRESH lt_format. + SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_format + FROM seocompodf + WHERE clsname = 'ZCL_EXCEL_STYLE_NUMBER_FORMAT' + AND typtype = 1 + AND type = 'ZEXCEL_NUMBER_FORMAT'. + +* --- Retrieve SAP date format + CLEAR ls_format. + SELECT ddtext INTO ls_format-attvalue FROM dd07t WHERE domname = 'XUDATFM' + AND ddlanguage = sy-langu. + ls_format-cmpname = 'DATE'. + CONDENSE ls_format-attvalue. + CONCATENATE '''' ls_format-attvalue '''' INTO ls_format-attvalue. + APPEND ls_format TO lt_format. + ENDSELECT. + + + LOOP AT lt_format INTO ls_format. + TRANSLATE ls_format-attvalue TO UPPER CASE. + MODIFY lt_format FROM ls_format. + ENDLOOP. + + +* STEP 1: Collect strings from the first worksheet + lo_iterator = excel->get_worksheets_iterator( ). + data: current_worksheet_title type ZEXCEL_SHEET_TITLE. + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + + IF worksheet_name IS NOT INITIAL. + current_worksheet_title = lo_worksheet->get_title( ). + CHECK current_worksheet_title = worksheet_name. + ELSE. + IF worksheet_index IS INITIAL. + worksheet_index = 1. + ENDIF. + CHECK worksheet_index = sy-index. + ENDIF. + APPEND LINES OF lo_worksheet->sheet_content TO lt_cell_data. + EXIT. " Take first worksheet only + ENDWHILE. + + DELETE lt_cell_data WHERE cell_formula IS NOT INITIAL. " delete formula content + + SORT lt_cell_data BY cell_row + cell_column. + lv_row = 1. + lv_col = 1. + CLEAR lv_string. + LOOP AT lt_cell_data ASSIGNING <fs_sheet_content>. + +* --- Retrieve Cell Style format and data type + CLEAR ls_numfmt. + IF <fs_sheet_content>-data_type IS INITIAL AND <fs_sheet_content>-cell_style IS NOT INITIAL. + lo_iterator = excel->get_styles_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_style ?= lo_iterator->if_object_collection_iterator~get_next( ). + CHECK lo_style->get_guid( ) = <fs_sheet_content>-cell_style. + ls_numfmt = lo_style->number_format->get_structure( ). + EXIT. + ENDWHILE. + ENDIF. + IF <fs_sheet_content>-data_type IS INITIAL AND ls_numfmt IS NOT INITIAL. + " determine data-type + CLEAR lv_attrname. + CONCATENATE '''' ls_numfmt-NUMFMT '''' INTO ls_numfmt-NUMFMT. + TRANSLATE ls_numfmt-numfmt TO UPPER CASE. + READ TABLE lt_format INTO ls_format WITH KEY attvalue = ls_numfmt-NUMFMT. + IF sy-subrc = 0. + lv_attrname = ls_format-cmpname. + ENDIF. + + IF lv_attrname IS NOT INITIAL. + FIND FIRST OCCURRENCE OF 'DATETIME' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'd'. + ELSE. + FIND FIRST OCCURRENCE OF 'TIME' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 't'. + ELSE. + FIND FIRST OCCURRENCE OF 'DATE' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'd'. + ELSE. + FIND FIRST OCCURRENCE OF 'CURRENCY' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'n'. + ELSE. + FIND FIRST OCCURRENCE OF 'NUMBER' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'n'. + ELSE. + FIND FIRST OCCURRENCE OF 'PERCENTAGE' IN lv_attrname. + IF sy-subrc = 0. + <fs_sheet_content>-data_type = 'n'. + ENDIF. " Purcentage + ENDIF. " Number + ENDIF. " Currency + ENDIF. " Date + ENDIF. " TIME + ENDIF. " DATETIME + ENDIF. " lv_attrname IS NOT INITIAL. + ENDIF. " <fs_sheet_content>-data_type IS INITIAL AND ls_numfmt IS NOT INITIAL. + +* --- Add empty rows + WHILE lv_row < <fs_sheet_content>-cell_row. +* CONCATENATE lv_string cl_abap_char_utilities=>newline INTO lv_string. +* CONCATENATE lv_string cl_abap_char_utilities=>cr_lf INTO lv_string. + CONCATENATE lv_string zcl_excel_writer_csv=>eol INTO lv_string. + lv_row = lv_row + 1. + lv_col = 1. + ENDWHILE. + +* --- Add empty columns + WHILE lv_col < <fs_sheet_content>-cell_column. +* CONCATENATE lv_string ';' INTO lv_string. + CONCATENATE lv_string zcl_excel_writer_csv=>delimiter INTO lv_string. + lv_col = lv_col + 1. + ENDWHILE. + +* ----- Use format to determine the data type and display format. + CASE <fs_sheet_content>-data_type. +* WHEN 'n' OR 'N'. +* lc_value = zcl_excel_common=>excel_number_to_string( ip_value = <fs_sheet_content>-cell_value ). + + WHEN 'd' OR 'D'. + lc_value = zcl_excel_common=>excel_string_to_date( ip_value = <fs_sheet_content>-cell_value ). + TRY. + lv_date = lc_value. + CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL' + EXPORTING + DATE_INTERNAL = lv_date + IMPORTING + DATE_EXTERNAL = lv_tmp + EXCEPTIONS + DATE_INTERNAL_IS_INVALID = 1 + OTHERS = 2 + . + IF SY-SUBRC = 0. + lc_value = lv_tmp. + ENDIF. + + CATCH CX_SY_CONVERSION_NO_NUMBER. + + ENDTRY. + + WHEN 't' OR 'T'. + lc_value = zcl_excel_common=>excel_string_to_time( ip_value = <fs_sheet_content>-cell_value ). + write lc_value to lv_time USING EDIT MASK '__:__:__'. + lc_value = lv_time. + WHEN OTHERS. + lc_value = <fs_sheet_content>-cell_value. + + ENDCASE. + +* REPLACE ALL OCCURRENCES OF '"' in lc_value with '""'. + CONCATENATE zcl_excel_writer_csv=>enclosure zcl_excel_writer_csv=>enclosure INTO lv_tmp. + CONDENSE lv_tmp. + REPLACE ALL OCCURRENCES OF zcl_excel_writer_csv=>enclosure in lc_value with lv_tmp. + +* FIND FIRST OCCURRENCE OF ';' IN lc_value. + FIND FIRST OCCURRENCE OF zcl_excel_writer_csv=>delimiter IN lc_value. + IF sy-subrc = 0. + CONCATENATE lv_string zcl_excel_writer_csv=>enclosure lc_value zcl_excel_writer_csv=>enclosure INTO lv_string. + ELSE. + CONCATENATE lv_string lc_value INTO lv_string. + ENDIF. + + ENDLOOP. " AT lt_cell_data + + CLEAR ep_content. + + CALL FUNCTION 'SCMS_STRING_TO_XSTRING' + EXPORTING + TEXT = lv_string +* MIMETYPE = ' ' +* ENCODING = + IMPORTING + BUFFER = ep_content + EXCEPTIONS + FAILED = 1 + OTHERS = 2 + . + + endmethod. + + + + method SET_ACTIVE_SHEET_INDEX. + CLEAR WORKSHEET_NAME. + WORKSHEET_INDEX = i_active_worksheet. + endmethod. + + + + method SET_ACTIVE_SHEET_INDEX_BY_NAME. + CLEAR WORKSHEET_INDEX. + WORKSHEET_NAME = i_worksheet_name. + endmethod. + + + + method SET_DELIMITER. + delimiter = ip_value. + endmethod. + + + + method SET_ENCLOSURE. + zcl_excel_writer_csv=>enclosure = ip_value. + endmethod. + + + + method SET_ENDOFLINE. + zcl_excel_writer_csv=>eol = ip_value. + endmethod. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + METHOD add_further_data_to_zip. + + super->add_further_data_to_zip( io_zip = io_zip ). + +* Add vbaProject.bin to zip + io_zip->add( name = me->c_xl_vbaproject + content = me->excel->zif_excel_book_vba_project~vbaproject ). + +ENDMETHOD. + + + method CREATE. + + +* Office 2007 file format is a cab of several xml files with extension .xlsx + + DATA: lo_zip TYPE REF TO cl_abap_zip, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_active_worksheet TYPE REF TO zcl_excel_worksheet, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_nested_iterator TYPE REF TO cl_object_collection_iterator, + lo_table TYPE REF TO zcl_excel_table, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_drawings TYPE REF TO zcl_excel_drawings. + + DATA: lv_content TYPE xstring, + lv_active TYPE flag, + lv_xl_sheet TYPE string, + lv_xl_sheet_rels TYPE string, + lv_xl_drawing TYPE string, + lv_xl_drawing_rels TYPE string, + lv_syindex TYPE string, + lv_value TYPE string, + lv_drawing_index TYPE i. + +********************************************************************** +* Start of insertion # issue 139 - Dateretention of cellstyles + me->excel->add_static_styles( ). +* End of insertion # issue 139 - Dateretention of cellstyles + +********************************************************************** +* STEP 1: Create archive object file (ZIP) + CREATE OBJECT lo_zip. + +********************************************************************** +* STEP 2: Add [Content_Types].xml to zip + lv_content = me->create_content_types( ). + lo_zip->add( name = me->c_content_types + content = lv_content ). + +********************************************************************** +* STEP 3: Add _rels/.rels to zip + lv_content = me->create_relationships( ). + lo_zip->add( name = me->c_relationships + content = lv_content ). + +********************************************************************** +* STEP 4: Add docProps/app.xml to zip + lv_content = me->create_docprops_app( ). + lo_zip->add( name = me->c_docprops_app + content = lv_content ). + +********************************************************************** +* STEP 5: Add docProps/core.xml to zip + lv_content = me->create_docprops_core( ). + lo_zip->add( name = me->c_docprops_core + content = lv_content ). + +********************************************************************** +* STEP 6: Add xl/_rels/workbook.xml.rels to zip + lv_content = me->create_xl_relationships( ). + lo_zip->add( name = me->c_xl_relationships + content = lv_content ). + +********************************************************************** +* STEP 6: Add xl/_rels/workbook.xml.rels to zip + lv_content = me->create_xl_theme( ). + lo_zip->add( name = me->c_xl_theme + content = lv_content ). + +********************************************************************** +* STEP 7: Add xl/workbook.xml to zip + lv_content = me->create_xl_workbook( ). + lo_zip->add( name = me->c_xl_workbook + content = lv_content ). + +********************************************************************** +* STEP 8: Add xl/workbook.xml to zip +* lv_content = me->create_xl_styles_static( ). + lv_content = me->create_xl_styles( ). + lo_zip->add( name = me->c_xl_styles + content = lv_content ). + +********************************************************************** +* STEP 9: Add sharedStrings.xml to zip + lv_content = me->create_xl_sharedstrings( ). + lo_zip->add( name = me->c_xl_sharedstrings + content = lv_content ). + +********************************************************************** +* STEP 10: Add sheet#.xml and drawing#.xml to zip + lo_iterator = me->excel->get_worksheets_iterator( ). + lo_active_worksheet = me->excel->get_active_worksheet( ). + lv_drawing_index = 1. + + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + IF lo_active_worksheet->get_guid( ) EQ lo_worksheet->get_guid( ). + lv_active = abap_true. + ELSE. + lv_active = abap_false. + ENDIF. + + lv_content = me->create_xl_sheet( io_worksheet = lo_worksheet + iv_active = lv_active ). + lv_xl_sheet = me->c_xl_sheet. + MOVE sy-index TO lv_syindex. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet WITH lv_syindex. + lo_zip->add( name = lv_xl_sheet + content = lv_content ). + + lv_xl_sheet_rels = me->c_xl_sheet_rels. + lv_content = me->create_xl_sheet_rels( io_worksheet = lo_worksheet + iv_drawing_index = lv_drawing_index ). + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_sheet_rels WITH lv_syindex. + lo_zip->add( name = lv_xl_sheet_rels + content = lv_content ). + + lo_nested_iterator = lo_worksheet->get_tables_iterator( ). + + WHILE lo_nested_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_table ?= lo_nested_iterator->if_object_collection_iterator~get_next( ). + lv_content = me->create_xl_table( lo_table ). + + lv_value = lo_table->get_name( ). + CONCATENATE 'xl/tables/' lv_value '.xml' INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +* Add drawings ********************************** + lo_drawings = lo_worksheet->get_drawings( ). + IF lo_drawings->is_empty( ) = abap_false. + MOVE lv_drawing_index TO lv_syindex. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + + lv_content = me->create_xl_drawings( lo_worksheet ). + lv_xl_drawing = me->c_xl_drawings. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing WITH lv_syindex. + lo_zip->add( name = lv_xl_drawing + content = lv_content ). + + lv_content = me->create_xl_drawings_rels( lo_worksheet ). + lv_xl_drawing_rels = me->c_xl_drawings_rels. + REPLACE ALL OCCURRENCES OF '#' IN lv_xl_drawing_rels WITH lv_syindex. + lo_zip->add( name = lv_xl_drawing_rels + content = lv_content ). + ADD 1 TO lv_drawing_index. + ENDIF. + ENDWHILE. + +********************************************************************** +* STEP 11: Add media + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_image ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_content = lo_drawing->get_media( ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/media/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +********************************************************************** +* STEP 12: Add charts + lo_iterator = me->excel->get_drawings_iterator( zcl_excel_drawing=>type_chart ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_drawing ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_content = lo_drawing->get_media( ). + lv_value = lo_drawing->get_media_name( ). + CONCATENATE 'xl/charts/' lv_value INTO lv_value. + lo_zip->add( name = lv_value + content = lv_content ). + ENDWHILE. + +********************************************************************** +* STEP 9: Add vbaProject.bin to zip + lo_zip->add( name = me->c_xl_vbaproject + content = me->excel->zif_excel_book_vba_project~vbaproject ). + +********************************************************************** +* STEP 12: Create the final zip + ep_excel = lo_zip->save( ). + + endmethod. + + + METHOD create_content_types. +** Constant node name + DATA: lc_xml_node_workb_ct TYPE string VALUE 'application/vnd.ms-excel.sheet.macroEnabled.main+xml', + lc_xml_node_default TYPE string VALUE 'Default', + " Node attributes + lc_xml_attr_partname TYPE string VALUE 'PartName', + lc_xml_attr_extension TYPE string VALUE 'Extension', + lc_xml_attr_contenttype TYPE string VALUE 'ContentType', + lc_xml_attr_codename TYPE string VALUE 'codeName', + lc_xml_node_workb_pn TYPE string VALUE '/xl/workbook.xml', + lc_xml_node_bin_ext TYPE string VALUE 'bin', + lc_xml_node_bin_ct TYPE string VALUE 'application/vnd.ms-office.vbaProject'. + + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_collection TYPE REF TO if_ixml_node_collection, + lo_iterator TYPE REF TO if_ixml_node_iterator, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_subrc TYPE sysubrc, + lv_contenttype TYPE string, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard contentType + ep_content = super->create_content_types( ). + +********************************************************************** +* STEP 2: modify XML adding the extension bin definition + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + " extension node + lo_element = lo_document->create_simple_element( name = lc_xml_node_default + parent = lo_document ). + lo_element->set_attribute_ns( name = lc_xml_attr_extension + value = lc_xml_node_bin_ext ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_bin_ct ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 3: modify XML changing the contentType of node Override /xl/workbook.xml + + lo_collection = lo_document->get_elements_by_tag_name( 'Override' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lv_contenttype = lo_element->get_attribute_ns( lc_xml_attr_partname ). + IF lv_contenttype EQ lc_xml_node_workb_pn. + lo_element->remove_attribute_ns( lc_xml_attr_contenttype ). + lo_element->set_attribute_ns( name = lc_xml_attr_contenttype + value = lc_xml_node_workb_ct ). + EXIT. + ENDIF. + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + METHOD create_xl_relationships. + +** Constant node name + DATA: lc_xml_node_relationships TYPE string VALUE 'Relationships', + lc_xml_node_relationship TYPE string VALUE 'Relationship', + " Node attributes + lc_xml_attr_id TYPE string VALUE 'Id', + lc_xml_attr_type TYPE string VALUE 'Type', + lc_xml_attr_target TYPE string VALUE 'Target', + " Node id + lc_xml_node_ridx_id TYPE string VALUE 'rId#', + " Node type + lc_xml_node_rid_vba_tp TYPE string VALUE 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', + " Node target + lc_xml_node_rid_vba_tg TYPE string VALUE 'vbaProject.bin'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_xml_node_ridx_tg TYPE string, + lv_xml_node_ridx_id TYPE string, + lv_size TYPE i, + lv_subrc TYPE sysubrc, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard relationship + ep_content = super->create_xl_relationships( ). + +********************************************************************** +* STEP 2: modify XML adding the vbaProject relation + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + + lv_size = excel->get_worksheets_size( ). + + " Relationship node + lo_element = lo_document->create_simple_element( name = lc_xml_node_relationship + parent = lo_document ). + ADD 4 TO lv_size. + lv_syindex = lv_size. + SHIFT lv_syindex RIGHT DELETING TRAILING space. + SHIFT lv_syindex LEFT DELETING LEADING space. + lv_xml_node_ridx_id = lc_xml_node_ridx_id. + REPLACE ALL OCCURRENCES OF '#' IN lv_xml_node_ridx_id WITH lv_syindex. + lo_element->set_attribute_ns( name = lc_xml_attr_id + value = lv_xml_node_ridx_id ). + lo_element->set_attribute_ns( name = lc_xml_attr_type + value = lc_xml_node_rid_vba_tp ). + lo_element->set_attribute_ns( name = lc_xml_attr_target + value = lc_xml_node_rid_vba_tg ). + lo_element_root->append_child( new_child = lo_element ). + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). + +ENDMETHOD. + + + METHOD create_xl_sheet. + +** Constant node name + DATA: lc_xml_attr_codename TYPE string VALUE 'codeName'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_collection TYPE REF TO if_ixml_node_collection, + lo_iterator TYPE REF TO if_ixml_node_iterator, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_subrc TYPE sysubrc, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard relationship + ep_content = super->create_xl_sheet( io_worksheet = io_worksheet + iv_active = iv_active ). + +********************************************************************** +* STEP 2: modify XML adding the vbaProject relation + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + lo_collection = lo_document->get_elements_by_tag_name( 'sheetPr' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lo_element->set_attribute_ns( name = lc_xml_attr_codename + value = io_worksheet->zif_excel_sheet_vba_project~codename_pr ). + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). +ENDMETHOD. + + + METHOD create_xl_workbook. + +** Constant node name + DATA: lc_xml_attr_codename TYPE string VALUE 'codeName'. + + DATA: lo_ixml TYPE REF TO if_ixml, + lo_document TYPE REF TO if_ixml_document, + lo_document_xml TYPE REF TO cl_xml_document, + lo_element_root TYPE REF TO if_ixml_node, + lo_element TYPE REF TO if_ixml_element, + lo_collection TYPE REF TO if_ixml_node_collection, + lo_iterator TYPE REF TO if_ixml_node_iterator, + lo_node TYPE REF TO if_ixml_node, + lo_encoding TYPE REF TO if_ixml_encoding, + lo_streamfactory TYPE REF TO if_ixml_stream_factory, + lo_ostream TYPE REF TO if_ixml_ostream, + lo_renderer TYPE REF TO if_ixml_renderer. + + DATA: lv_subrc TYPE sysubrc, + lv_syindex(2) TYPE c. + +********************************************************************** +* STEP 3: Create standard relationship + ep_content = super->create_xl_workbook( ). + +********************************************************************** +* STEP 2: modify XML adding the vbaProject relation + + CREATE OBJECT lo_document_xml. + lv_subrc = lo_document_xml->parse_xstring( ep_content ). + + lo_document ?= lo_document_xml->m_document. + lo_element_root = lo_document->if_ixml_node~get_first_child( ). + + lo_collection = lo_document->get_elements_by_tag_name( 'fileVersion' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lo_element->set_attribute_ns( name = lc_xml_attr_codename + value = me->excel->zif_excel_book_vba_project~codename ). + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + + lo_collection = lo_document->get_elements_by_tag_name( 'workbookPr' ). + lo_iterator = lo_collection->create_iterator( ). + lo_element ?= lo_iterator->get_next( ). + WHILE lo_element IS BOUND. + lo_element->set_attribute_ns( name = lc_xml_attr_codename + value = me->excel->zif_excel_book_vba_project~codename_pr ). + lo_element ?= lo_iterator->get_next( ). + ENDWHILE. + +********************************************************************** +* STEP 3: Create xstring stream + CLEAR ep_content. + lo_ixml = cl_ixml=>create( ). + lo_streamfactory = lo_ixml->create_stream_factory( ). + lo_ostream = lo_streamfactory->create_ostream_xstring( string = ep_content ). + lo_renderer = lo_ixml->create_renderer( ostream = lo_ostream document = lo_document ). + lo_renderer->render( ). +ENDMETHOD. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + method IF_MESSAGE~GET_LONGTEXT. + + IF me->error IS NOT INITIAL + OR me->syst_at_raise IS NOT INITIAL. +*--------------------------------------------------------------------* +* If message was supplied explicitly use this as longtext as well +*--------------------------------------------------------------------* + result = me->get_text( ). + ELSE. +*--------------------------------------------------------------------* +* otherwise use standard method to derive text +*--------------------------------------------------------------------* + super->if_message~get_longtext( EXPORTING + preserve_newlines = preserve_newlines + RECEIVING + result = result ). + ENDIF. + endmethod. + + + method IF_MESSAGE~GET_TEXT. + + IF me->error IS NOT INITIAL. +*--------------------------------------------------------------------* +* If message was supplied explicitly use this +*--------------------------------------------------------------------* + result = me->error . + ELSEIF me->syst_at_raise IS NOT INITIAL. +*--------------------------------------------------------------------* +* If message was supplied by syst create messagetext now +*--------------------------------------------------------------------* + MESSAGE ID syst_at_raise-msgid TYPE syst_at_raise-msgty NUMBER syst_at_raise-msgno + WITH syst_at_raise-msgv1 syst_at_raise-msgv2 syst_at_raise-msgv3 syst_at_raise-msgv4 + INTO result. + ELSE. +*--------------------------------------------------------------------* +* otherwise use standard method to derive text +*--------------------------------------------------------------------* + CALL METHOD super->if_message~get_text + RECEIVING + result = result. + ENDIF. + endmethod. + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + method GET_GUID. + + ep_guid = me->guid. + + endmethod. + + + + method GET_VALUE. + + ep_value = me->value. + + endmethod. + + + + method SET_RANGE_VALUE. + me->value = ip_value. + endmethod. + + + + + + + + method SET_VALUE. + DATA: lv_start_row_c TYPE char7, + lv_stop_row_c TYPE char7, + lv_value TYPE string. + lv_stop_row_c = ip_stop_row. + SHIFT lv_stop_row_c RIGHT DELETING TRAILING space. + SHIFT lv_stop_row_c LEFT DELETING LEADING space. + lv_start_row_c = ip_start_row. + SHIFT lv_start_row_c RIGHT DELETING TRAILING space. + SHIFT lv_start_row_c LEFT DELETING LEADING space. + lv_value = ip_sheet_name. + me->value = zcl_excel_common=>escape_string( ip_value = lv_value ). + + CONCATENATE me->value '!$' ip_start_column '$' lv_start_row_c ':$' ip_stop_column '$' lv_stop_row_c INTO me->value. + endmethod. + + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + +* Signal "not found" +class lcx_not_found implementation. + method constructor. + super->constructor( textid = textid previous = previous ). + me->error = error. + endmethod. "constructor + method if_message~get_text. + result = error. + endmethod. "if_message~get_text +endclass. "lcx_not_found IMPLEMENTATION + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + +* Signal for "Not found" +class lcx_not_found definition inheriting from cx_static_check. + public section. + data error type string. + methods constructor + importing error type string + textid type sotr_conc optional + previous type ref to cx_root optional. + methods if_message~get_text redefinition. +endclass. + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + *"* use this source file for your ABAP unit test classes +class lcl_test definition deferred. +class zcl_excel_reader_huge_file definition local friends lcl_test. + +* +class lcl_test definition for testing " #AU Risk_Level Harmless + inheriting from cl_aunit_assert. " #AU Duration Short + + private section. + data: + out type ref to zcl_excel_reader_huge_file, " object under test + excel type ref to zcl_excel, + worksheet type ref to zcl_excel_worksheet. + methods: + setup, + test_number for testing, + test_shared_string for testing, + test_shared_string_missing for testing, + test_inline_string for testing, + test_empty_cells for testing, + test_boolean for testing, + test_style for testing, + test_style_missing for testing, + test_formula for testing, + test_read_shared_strings for testing, + test_shared_string_some_empty for testing, + test_skip_to_inexistent for testing, + get_reader importing iv_xml type string returning value(eo_reader) type ref to if_sxml_reader, + assert_value_equals importing iv_row type i default 1 iv_col type i default 1 iv_value type string, + assert_formula_equals importing iv_row type i default 1 iv_col type i default 1 iv_formula type string, + assert_style_equals importing iv_row type i default 1 iv_col type i default 1 iv_style type ZEXCEL_CELL_STYLE, + assert_datatype_equals importing iv_row type i default 1 iv_col type i default 1 iv_datatype type string. + +endclass. "lcl_test DEFINITION + +* +class lcl_test implementation. + +* + method test_number. + data lo_reader type ref to if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="n"><v>17</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `17` ). + assert_datatype_equals( `n` ). + endmethod. "test_shared_string + +* + method test_shared_string. + data lo_reader type ref to if_sxml_reader. + append `Test1` to out->shared_strings. + append `Test2` to out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>1</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Test2` ). + assert_datatype_equals( `s` ). + endmethod. "test_shared_string +* + method test_shared_string_missing. + + data: lo_reader type ref to if_sxml_reader, + lo_ex type ref to lcx_not_found, + lv_text type string. + append `Test` to out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>1</v></c>` + ). + + try. + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + fail(`Index to non-existent shared string should give an error`). + catch lcx_not_found into lo_ex. + lv_text = lo_ex->get_text( ). " >>> May inspect the message in the debugger + endtry. + + endmethod. +* + method test_inline_string. + data lo_reader type ref to if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="inlineStr"><is><t>Alpha</t></is></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `Alpha` ). + assert_datatype_equals( `inlineStr` ). + endmethod. "test_inline_string + +* + method test_boolean. + data lo_reader type ref to if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="b"><v>1</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_value_equals( `1` ). + assert_datatype_equals( `b` ). + endmethod. "test_boolean + +* + method test_formula. + data lo_reader type ref to if_sxml_reader. + lo_reader = get_reader( + `<c r="A1" t="n"><f>A2*A2</f></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + assert_formula_equals( `A2*A2` ). + assert_datatype_equals( `n` ). + endmethod. "test_formula + +* + method test_empty_cells. + +* There is no need to store an empty cell in the ABAP worksheet structure + + data: lo_reader type ref to if_sxml_reader, + lo_ex type ref to lcx_not_found, + lv_text type string. + append `` to out->shared_strings. + append `t` to out->shared_strings. + lo_reader = get_reader( + `<c r="A1" t="s"><v>0</v></c>` & + `<c r="A2" t="inlineStr"><is><t></t></is></c>` & + `<c r="A3" t="s"><v>1</v></c>` + ). + + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + + assert_value_equals( iv_row = 1 iv_col = 1 iv_value = `` ). + assert_value_equals( iv_row = 2 iv_col = 1 iv_value = `` ). + assert_value_equals( iv_row = 3 iv_col = 1 iv_value = `t` ). + + endmethod. + +* + method test_style. + data: + lo_reader type ref to if_sxml_reader, + lo_style type ref to zcl_excel_style, + lv_guid type ZEXCEL_CELL_STYLE. + create object lo_style. + append lo_style to out->styles. + lv_guid = lo_style->get_guid( ). + + lo_reader = get_reader( + `<c r="A1" s="0"><v>18</v></c>` + ). + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + + assert_style_equals( lv_guid ). + + endmethod. "test_style + +* + method test_style_missing. + + data: + lo_reader type ref to if_sxml_reader, + lo_ex type ref to lcx_not_found, + lv_text type string. + + lo_reader = get_reader( + `<c r="A1" s="0"><v>18</v></c>` + ). + + try. + out->read_worksheet_data( io_reader = lo_reader io_worksheet = worksheet ). + fail(`Reference to non-existent style should throw an lcx_not_found exception`). + catch lcx_not_found into lo_ex. + lv_text = lo_ex->get_text( ). " >>> May inspect the message in the debugger + endtry. + + endmethod. "test_style + +* + method test_read_shared_strings. + data: lo_c2x type ref to cl_abap_conv_out_ce, + lv_xstring type xstring, + lo_reader type ref to if_sxml_reader, + lt_act type stringtab, + lt_exp type stringtab. + + lo_c2x = cl_abap_conv_out_ce=>create( ). + lo_c2x->convert( exporting data = `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + importing buffer = lv_xstring ). + lo_reader = cl_sxml_string_reader=>create( lv_xstring ). + append : + `` to lt_exp, + `Alpha` to lt_exp, + `Bravo` to lt_exp. + + lt_act = out->read_shared_strings( lo_reader ). + + assert_equals( act = lt_act + exp = lt_exp ). + + endmethod. + +* + method test_shared_string_some_empty. + data: lo_reader type ref to if_sxml_reader, + lt_act type stringtab, + lt_exp type stringtab. + lo_reader = cl_sxml_string_reader=>create( cl_abap_codepage=>convert_to( + `<sst><si><t/></si>` & + `<si><t>Alpha</t></si>` & + `<si><t/></si>` & + `<si><t>Bravo</t></si></sst>` + ) ). + append : + `` to lt_exp, + `Alpha` to lt_exp, + `` to lt_exp, + `Bravo` to lt_exp. + + lt_act = out->read_shared_strings( lo_reader ). + + assert_equals( act = lt_act + exp = lt_exp ). + + endmethod. + + +* + method test_skip_to_inexistent. + data: lo_c2x type ref to cl_abap_conv_out_ce, + lv_xstring type xstring, + lo_reader type ref to if_sxml_reader, + lo_ex type ref to lcx_not_found, + lv_text type string. + + lo_c2x = cl_abap_conv_out_ce=>create( ). + lo_c2x->convert( exporting data = `<sst><si><t/></si><si><t>Alpha</t></si><si><t>Bravo</t></si></sst>` + importing buffer = lv_xstring ). + lo_reader = cl_sxml_string_reader=>create( lv_xstring ). + try. + out->skip_to( iv_element_name = `nonExistingElement` io_reader = lo_reader ). + fail(`Skipping to non-existing element must raise lcx_not_found exception`). + catch lcx_not_found into lo_ex. + lv_text = lo_ex->get_text( ). " May inspect exception text in debugger + endtry. + endmethod. + +* + method get_reader. + data: lv_full type string, + lo_c2x type ref to cl_abap_conv_out_ce, + lv_xstring type xstring. + concatenate `<root><sheetData><row>` iv_xml `</row></sheetData></root>` into lv_full. + lo_c2x = cl_abap_conv_out_ce=>create( ). + lo_c2x->convert( exporting data = lv_full + importing buffer = lv_xstring ). + eo_reader = cl_sxml_string_reader=>create( lv_xstring ). + endmethod. "get_reader +* + method assert_value_equals. + + constants: lc_empty_string type string value is initial. + + field-symbols: <ls_cell_data> type zexcel_s_cell_data, + <lv_value> type string. + + read table worksheet->sheet_content assigning <ls_cell_data> + with table key cell_row = iv_row cell_column = iv_col. + if sy-subrc eq 0. + assign <ls_cell_data>-cell_value to <lv_value>. + else. + assign lc_empty_string to <lv_value>. + endif. + + assert_equals( act = <lv_value> + exp = iv_value ). + + endmethod. "assert_value_equals +** + method assert_formula_equals. + + field-symbols: <ls_cell_data> type zexcel_s_cell_data. + + read table worksheet->sheet_content assigning <ls_cell_data> + with table key cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_formula + exp = iv_formula ). + + endmethod. "assert_formula_equals +* + method assert_style_equals. + + field-symbols: <ls_cell_data> type zexcel_s_cell_data. + + read table worksheet->sheet_content assigning <ls_cell_data> + with table key cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-cell_style + exp = iv_style ). + + endmethod. +* + method assert_datatype_equals. + + field-symbols: <ls_cell_data> type zexcel_s_cell_data. + + read table worksheet->sheet_content assigning <ls_cell_data> + with table key cell_row = iv_row cell_column = iv_col. + assert_subrc( sy-subrc ). + + assert_equals( act = <ls_cell_data>-data_type + exp = iv_datatype ). + + endmethod. "assert_datatype_equals + method setup. + create object out. + create object excel. + create object worksheet + exporting + ip_excel = excel. + endmethod. "setup +endclass. "lcl_test IMPLEMENTATION + + + + + + + + + + + + + + + + method FILL_CELL_FROM_ATTRIBUTES. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_attribute( ). + if io_reader->node_type ne c_attribute. + exit. + endif. + case io_reader->name. + when `t`. + es_cell-datatype = io_reader->value. + when `s`. + if io_reader->value is not initial. + es_cell-style = get_style( io_reader->value ). + endif. + when `r`. + es_cell-coord = get_cell_coord( io_reader->value ). + endcase. + endwhile. + +endmethod. + + + + + method GET_CELL_COORD. + + zcl_excel_common=>convert_columnrow2column_a_row( + exporting + i_columnrow = iv_coord + importing + e_column = es_coord-column + e_row = es_coord-row + ). + +endmethod. + + + + + + method GET_SHARED_STRING. + data: lv_tabix type i, + lv_error type string. + lv_tabix = iv_index + 1. + read table shared_strings into ev_value index lv_tabix. + if sy-subrc ne 0. + concatenate 'Entry ' iv_index ' not found in Shared String Table' into lv_error. + raise exception type lcx_not_found + exporting + error = lv_error. + endif. +endmethod. + + + + + + method GET_STYLE. + + data: lv_tabix type i, + lo_style type ref to zcl_excel_style, + lv_error type string. + + if gs_buffer_style-index ne iv_index. + lv_tabix = iv_index + 1. + read table styles into lo_style index lv_tabix. + if sy-subrc ne 0. + concatenate 'Entry ' iv_index ' not found in Style Table' into lv_error. + raise exception type lcx_not_found + exporting + error = lv_error. + else. + gs_buffer_style-index = iv_index. + gs_buffer_style-guid = lo_style->get_guid( ). + endif. + endif. + + ev_style_guid = gs_buffer_style-guid. + +endmethod. + + + + + + method GET_SXML_READER. + + data: lv_xml type xstring. + + lv_xml = get_from_zip_archive( iv_path ). + eo_reader = cl_sxml_string_reader=>create( lv_xml ). + +endmethod. + + + method LOAD_SHARED_STRINGS. + + data: lo_reader type ref to if_sxml_reader. + + lo_reader = get_sxml_reader( ip_path ). + + shared_strings = read_shared_strings( lo_reader ). + +endmethod. + + + method LOAD_WORKSHEET. + + data: lo_reader type ref to if_sxml_reader. + + lo_reader = get_sxml_reader( ip_path ). + + read_worksheet_data( io_reader = lo_reader + io_worksheet = io_worksheet ). + +endmethod. + + + + + method PUT_CELL_TO_WORKSHEET. + check is_cell-value is not initial + or is_cell-formula is not initial + or is_cell-style is not initial. + call method io_worksheet->set_cell + exporting + ip_column = is_cell-column + ip_row = is_cell-row + ip_value = is_cell-value + ip_formula = is_cell-formula + ip_data_type = is_cell-datatype + ip_style = is_cell-style. +endmethod. + + + + + method read_shared_strings. + + data lv_value type string. + + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + if io_reader->name eq `t`. + case io_reader->node_type . + when c_element_open . + clear lv_value . + when c_node_value . + lv_value = lv_value && io_reader->value . + when c_element_close . + append lv_value to et_shared_strings. + endcase . + endif. + endwhile. + +endmethod. + + + + + + method READ_WORKSHEET_DATA. + + data: ls_cell type t_cell. + +* Skip to <sheetData> element + skip_to( iv_element_name = `sheetData` io_reader = io_reader ). + +* Main loop: Evaluate the <c> elements and its children + while io_reader->node_type ne c_end_of_stream. + io_reader->next_node( ). + case io_reader->node_type. + when c_element_open. + if io_reader->name eq `c`. + ls_cell = fill_cell_from_attributes( io_reader ). + endif. + when c_node_value. + case io_reader->name. + when `f`. + ls_cell-formula = io_reader->value. + when `v`. + if ls_cell-datatype eq `s`. + ls_cell-value = get_shared_string( io_reader->value ). + else. + ls_cell-value = io_reader->value. + endif. + when `t` or `is`. + ls_cell-value = io_reader->value. + endcase. + when c_element_close. + case io_reader->name. + when `c`. + put_cell_to_worksheet( is_cell = ls_cell io_worksheet = io_worksheet ). + when `sheetData`. + exit. + endcase. + endcase. + endwhile. + +endmethod. + + + + + + method SKIP_TO. + + data: lv_error type string. + +* Skip forward to given element + while io_reader->name ne iv_element_name or + io_reader->node_type ne c_element_open. + io_reader->next_node( ). + if io_reader->node_type = c_end_of_stream. + concatenate 'XML error: Didn''t find element <' iv_element_name '>' into lv_error. + raise exception type lcx_not_found + exporting + error = lv_error. + endif. + endwhile. + + +endmethod. + + + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + METHOD add_pagebreak. + DATA: ls_pagebreak LIKE LINE OF me->mt_pagebreaks. + + ls_pagebreak-cell_row = ip_row. + ls_pagebreak-cell_column = zcl_excel_common=>convert_column2int( ip_column ). + + INSERT ls_pagebreak INTO TABLE me->mt_pagebreaks. + + +ENDMETHOD. + + + + METHOD get_all_pagebreaks. + rt_pagebreaks = me->mt_pagebreaks. +ENDMETHOD. + + + + *"* use this source file for the definition and implementation of +*"* local helper classes, interface definitions and type +*"* declarations + *"* use this source file for any type of declarations (class +*"* definitions, interfaces or type declarations) you need for +*"* components in the private section + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + + + + + + + + + + + + + + + + + + + + + + METHOD guid_create. + + TRY. + rv_guid_16 = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ). + CATCH cx_uuid_error. + ENDTRY. + +*--------------------------------------------------------------------* +* If you are on a release that does not yet have the class cl_system_uuid +* please use the following coding instead which is using the function +* call that was used before but which has been flagged as obsolete +* in newer SAP releases +*--------------------------------------------------------------------* +* +* CALL FUNCTION 'GUID_CREATE' +* IMPORTING +* ev_guid_16 = rv_guid_16. + +ENDMETHOD. + + + + + + + *"* 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 + *"* use this source file for any macro definitions you need +*"* in the implementation part of the class + CLASS zcl_tc_excel DEFINITION DEFERRED. +CLASS zcl_excel DEFINITION LOCAL FRIENDS zcl_tc_excel. + +*----------------------------------------------------------------------* +* CLASS zcl_Tc_Excel DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_tc_excel DEFINITION FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS +. +*?<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> +*?<asx:values> +*?<TESTCLASS_OPTIONS> +*?<TEST_CLASS>zcl_Tc_Excel +*?</TEST_CLASS> +*?<TEST_MEMBER>f_Cut +*?</TEST_MEMBER> +*?<OBJECT_UNDER_TEST>ZCL_EXCEL +*?</OBJECT_UNDER_TEST> +*?<OBJECT_IS_LOCAL/> +*?<GENERATE_FIXTURE>X +*?</GENERATE_FIXTURE> +*?<GENERATE_CLASS_FIXTURE>X +*?</GENERATE_CLASS_FIXTURE> +*?<GENERATE_INVOCATION>X +*?</GENERATE_INVOCATION> +*?<GENERATE_ASSERT_EQUAL>X +*?</GENERATE_ASSERT_EQUAL> +*?</TESTCLASS_OPTIONS> +*?</asx:values> +*?</asx:abap> + PRIVATE SECTION. +* ================ + DATA: + f_cut TYPE REF TO zcl_excel. "class under test + + CLASS-METHODS: class_setup. + CLASS-METHODS: class_teardown. + METHODS: setup. + METHODS: teardown. + METHODS: create_empty_excel FOR TESTING. + +ENDCLASS. "zcl_Tc_Excel + + +*----------------------------------------------------------------------* +* CLASS zcl_Tc_Excel IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_tc_excel IMPLEMENTATION. +* ================================== + + METHOD class_setup. +* =================== + + + ENDMETHOD. "class_Setup + + + METHOD class_teardown. +* ====================== + + + ENDMETHOD. "class_Teardown + + + METHOD setup. +* ============= + + CREATE OBJECT f_cut. + ENDMETHOD. "setup + + + METHOD teardown. +* ================ + + + ENDMETHOD. "teardown + +*// START TEST METHODS + + METHOD create_empty_excel. +* ================================== + + DATA: lv_count TYPE i. + lv_count = f_cut->get_worksheets_size( ). + + cl_abap_unit_assert=>assert_equals( act = lv_count + exp = 1 + msg = 'Testing number of sheet' + level = if_aunit_constants=>tolerable ). + ENDMETHOD. "create_empty_excel + +*// END TEST METHODS + + +ENDCLASS. "zcl_Tc_Excel + + + + + + + + + + + + + + + + + + + + + + METHOD zif_excel_book_properties~initialize. + DATA: lv_timestamp TYPE timestampl. + + me->zif_excel_book_properties~application = 'Microsoft Excel'. + me->zif_excel_book_properties~appversion = '12.0000'. + + GET TIME STAMP FIELD lv_timestamp. + me->zif_excel_book_properties~created = lv_timestamp. + me->zif_excel_book_properties~creator = sy-uname. + me->zif_excel_book_properties~description = zcl_excel=>version. + me->zif_excel_book_properties~modified = lv_timestamp. + me->zif_excel_book_properties~lastmodifiedby = sy-uname. +ENDMETHOD. + + + method ZIF_EXCEL_BOOK_PROTECTION~INITIALIZE. + me->zif_excel_book_protection~protected = zif_excel_book_protection=>c_unprotected. + me->zif_excel_book_protection~lockrevision = zif_excel_book_protection=>c_unlocked. + me->zif_excel_book_protection~lockstructure = zif_excel_book_protection=>c_unlocked. + me->zif_excel_book_protection~lockwindows = zif_excel_book_protection=>c_unlocked. + CLEAR me->zif_excel_book_protection~workbookpassword. + CLEAR me->zif_excel_book_protection~revisionspassword. + endmethod. + + + method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_CODENAME. + me->zif_excel_book_vba_project~codename = ip_codename. + endmethod. + + + method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_CODENAME_PR. + me->zif_excel_book_vba_project~codename_pr = ip_codename_pr. + endmethod. + + + method ZIF_EXCEL_BOOK_VBA_PROJECT~SET_VBAPROJECT. + me->zif_excel_book_vba_project~vbaproject = ip_vbaproject. + endmethod. + + + + + + METHOD add_new_autofilter. +* Check for autofilter reference: new or overwrite; only one per sheet + ro_autofilter = autofilters->add( io_sheet ) . +ENDMETHOD. + + + + + + method ADD_NEW_DRAWING. + DATA: lv_guid TYPE guid_16. +* Create default blank worksheet + CREATE OBJECT eo_drawing + EXPORTING + ip_type = ip_type + ip_title = ip_title. + + CASE ip_type. + WHEN 'image'. + drawings->add( eo_drawing ). + WHEN 'chart'. + charts->add( eo_drawing ). + ENDCASE. + endmethod. + + + + method ADD_NEW_RANGE. +* Create default blank range + CREATE OBJECT eo_range. + ranges->add( eo_range ). + endmethod. + + + + + method ADD_NEW_STYLE. +* Start of deletion # issue 139 - Dateretention of cellstyles +* CREATE OBJECT eo_style. +* styles->add( eo_style ). +* End of deletion # issue 139 - Dateretention of cellstyles +* Start of insertion # issue 139 - Dateretention of cellstyles +* Create default style + CREATE OBJECT eo_style + EXPORTING + ip_guid = ip_guid. + styles->add( eo_style ). + + DATA: style2 TYPE zexcel_s_stylemapping. +* Copy to new representations + style2 = stylemapping_dynamic_style( eo_style ). + INSERT style2 INTO TABLE t_stylemapping1. + INSERT style2 INTO TABLE t_stylemapping2. +* End of insertion # issue 139 - Dateretention of cellstyles + + endmethod. + + + + + + method ADD_NEW_WORKSHEET. + DATA: lv_guid TYPE guid_16. + +* Create default blank worksheet + CREATE OBJECT eo_worksheet + EXPORTING + ip_excel = me + ip_title = ip_title. + + worksheets->add( eo_worksheet ). + worksheets->active_worksheet = worksheets->size( ). + endmethod. + + + METHOD add_static_styles. + " # issue 139 + FIELD-SYMBOLS: <style1> LIKE LINE OF t_stylemapping1, + <style2> LIKE LINE OF t_stylemapping2. + DATA: style TYPE REF TO zcl_excel_style. + + LOOP AT me->t_stylemapping1 ASSIGNING <style1> WHERE added_to_iterator IS INITIAL. + READ TABLE me->t_stylemapping2 ASSIGNING <style2> WITH TABLE KEY guid = <style1>-guid. + CHECK sy-subrc = 0. " Should always be true since these tables are being filled parallel + + style = me->add_new_style( <style1>-guid ). + + zcl_excel_common=>recursive_struct_to_class( EXPORTING i_source = <style1>-complete_style + i_sourcex = <style1>-complete_stylex + CHANGING e_target = style ). + + ENDLOOP. +ENDMETHOD. + + + method CONSTRUCTOR. + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style TYPE REF TO zcl_excel_style. + +* Inizialize instance objects + CREATE OBJECT security. + CREATE OBJECT worksheets. + CREATE OBJECT ranges. + CREATE OBJECT styles. + CREATE OBJECT drawings + EXPORTING + ip_type = zcl_excel_drawing=>type_image. + CREATE OBJECT charts + EXPORTING + ip_type = zcl_excel_drawing=>type_chart. + CREATE OBJECT legacy_palette. + CREATE OBJECT autofilters. + + me->zif_excel_book_protection~initialize( ). + me->zif_excel_book_properties~initialize( ). + + me->add_new_worksheet( ). + me->add_new_style( ). " Standard style + lo_style = me->add_new_style( ). " Standard style with fill gray125 + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_pattern_gray125. + + endmethod. + + + + + METHOD delete_worksheet. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + l_size TYPE i, + lv_errormessage TYPE string. + + l_size = get_worksheets_size( ). + IF l_size = 1. " Only 1 worksheet left --> check whether this is the worksheet to be deleted + lo_worksheet = me->get_worksheet_by_index( 1 ). + IF lo_worksheet = io_worksheet. + lv_errormessage = 'Deleting last remaining worksheet is not allowed'(002). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + ENDIF. + + me->worksheets->remove( io_worksheet ). + +ENDMETHOD. + + + + METHOD delete_worksheet_by_index. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_errormessage TYPE string. + + lo_worksheet = me->get_worksheet_by_index( iv_index ). + IF lo_worksheet IS NOT BOUND. + lv_errormessage = 'Worksheet not existing'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + me->delete_worksheet( lo_worksheet ). + +ENDMETHOD. + + + + METHOD delete_worksheet_by_name. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_errormessage TYPE string. + + lo_worksheet = me->get_worksheet_by_name( iv_title ). + IF lo_worksheet IS NOT BOUND. + lv_errormessage = 'Worksheet not existing'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + me->delete_worksheet( lo_worksheet ). + +ENDMETHOD. + + + + method GET_ACTIVE_SHEET_INDEX. + r_active_worksheet = me->worksheets->active_worksheet. + endmethod. + + + + method GET_ACTIVE_WORKSHEET. + + eo_worksheet = me->worksheets->get( me->worksheets->active_worksheet ). + + endmethod. + + + + method GET_AUTOFILTERS_REFERENCE. + + ro_autofilters = autofilters. + + endmethod. + + + + method GET_DEFAULT_STYLE. + ep_style = me->default_style. + endmethod. + + + + + method GET_DRAWINGS_ITERATOR. + + CASE ip_type. + WHEN zcl_excel_drawing=>type_image. + eo_iterator = me->drawings->get_iterator( ). + WHEN zcl_excel_drawing=>type_chart. + eo_iterator = me->charts->get_iterator( ). + WHEN OTHERS. + ENDCASE. + + endmethod. + + + + method GET_NEXT_TABLE_ID. + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_iterator TYPE REF TO cl_object_collection_iterator, + lv_tables_count TYPE i. + + lo_iterator = me->get_worksheets_iterator( ). + WHILE lo_iterator->if_object_collection_iterator~has_next( ) EQ abap_true. + lo_worksheet ?= lo_iterator->if_object_collection_iterator~get_next( ). + + lv_tables_count = lo_worksheet->get_tables_size( ). + ADD lv_tables_count TO ep_id. + + ENDWHILE. + + ADD 1 TO ep_id. + + endmethod. + + + + method GET_RANGES_ITERATOR. + + eo_iterator = me->ranges->get_iterator( ). + + endmethod. + + + + + + METHOD get_static_cellstyle_guid. + " # issue 139 + DATA: style LIKE LINE OF me->t_stylemapping1. + + READ TABLE me->t_stylemapping1 INTO style + WITH TABLE KEY dynamic_style_guid = style-guid " no dynamic style --> look for initial guid here + complete_style = ip_cstyle_complete + complete_stylex = ip_cstylex_complete. + IF sy-subrc <> 0. + style-complete_style = ip_cstyle_complete. + style-complete_stylex = ip_cstylex_complete. +* CALL FUNCTION 'GUID_CREATE' " del issue #379 - function is outdated in newer releases +* IMPORTING +* ev_guid_16 = style-guid. + style-guid = zcl_excel_obsolete_func_wrap=>guid_create( ). " ins issue #379 - replacement for outdated function call + INSERT style INTO TABLE me->t_stylemapping1. + INSERT style INTO TABLE me->t_stylemapping2. + + ENDIF. + + ep_guid = style-guid. +ENDMETHOD. + + + + method GET_STYLES_ITERATOR. + + eo_iterator = me->styles->get_iterator( ). + + endmethod. + + + + + + method GET_STYLE_INDEX_IN_STYLES. + DATA: index TYPE syindex. + DATA: lo_iterator TYPE REF TO cl_object_collection_iterator, + lo_style TYPE REF TO zcl_excel_style. + + CHECK ip_guid IS NOT INITIAL. + + + lo_iterator = me->get_styles_iterator( ). + WHILE lo_iterator->has_next( ) = 'X'. + ADD 1 TO index. + lo_style ?= lo_iterator->get_next( ). + IF lo_style->get_guid( ) = ip_guid. + ep_index = index. + EXIT. + ENDIF. + ENDWHILE. + + IF ep_index IS INITIAL. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'Index not found'. + else. + SUBTRACT 1 from ep_index. " In excel list starts with "0" + ENDIF. + endmethod. + + + + + + method GET_STYLE_TO_GUID. + " # issue 139 + + READ TABLE me->t_stylemapping2 INTO ep_stylemapping WITH TABLE KEY guid = ip_guid. + IF sy-subrc <> 0. + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = 'GUID not found'. + ENDIF. + + IF ep_stylemapping-dynamic_style_guid IS NOT INITIAL. + zcl_excel_common=>recursive_class_to_struct( EXPORTING i_source = ep_stylemapping-cl_style + CHANGING e_target = ep_stylemapping-complete_style + e_targetx = ep_stylemapping-complete_stylex ). + ENDIF. + + + endmethod. + + + + method GET_THEME. + eo_theme = theme. +endmethod. + + + + method GET_WORKSHEETS_ITERATOR. + + eo_iterator = me->worksheets->get_iterator( ). + + endmethod. + + + + method GET_WORKSHEETS_NAME. + + ep_name = me->worksheets->name. + + endmethod. + + + + METHOD get_worksheets_size. + + ep_size = me->worksheets->size( ). + +ENDMETHOD. + + + + + METHOD get_worksheet_by_index. + + + DATA: lv_index TYPE zexcel_active_worksheet. + + lv_index = iv_index. + eo_worksheet = me->worksheets->get( lv_index ). + +ENDMETHOD. + + + + + METHOD get_worksheet_by_name. + + DATA: lv_index TYPE zexcel_active_worksheet, + l_size TYPE i. + + l_size = get_worksheets_size( ). + + DO l_size TIMES. + lv_index = sy-index. + eo_worksheet = me->worksheets->get( lv_index ). + IF eo_worksheet->get_title( ) = ip_sheet_name. + RETURN. + ENDIF. + ENDDO. + + CLEAR eo_worksheet. + +ENDMETHOD. + + + + + METHOD set_active_sheet_index. + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_errormessage TYPE string. + +*--------------------------------------------------------------------* +* Check whether worksheet exists +*--------------------------------------------------------------------* + lo_worksheet = me->get_worksheet_by_index( i_active_worksheet ). + IF lo_worksheet IS NOT BOUND. + lv_errormessage = 'Worksheet not existing'(001). + RAISE EXCEPTION TYPE zcx_excel + EXPORTING + error = lv_errormessage. + ENDIF. + + me->worksheets->active_worksheet = i_active_worksheet. + +ENDMETHOD. + + + + METHOD set_active_sheet_index_by_name. + + DATA: ws_it TYPE REF TO cl_object_collection_iterator, + ws TYPE REF TO zcl_excel_worksheet, + lv_title TYPE zexcel_sheet_title, + count TYPE i VALUE 1. + + ws_it = me->worksheets->get_iterator( ). + + WHILE ws_it->if_object_collection_iterator~has_next( ) = abap_true. + ws ?= ws_it->if_object_collection_iterator~get_next( ). + lv_title = ws->get_title( ). + IF lv_title = i_worksheet_name. + me->worksheets->active_worksheet = count. + EXIT. + ENDIF. + count = count + 1. + ENDWHILE. + +ENDMETHOD. + + + + + method SET_DEFAULT_STYLE. + me->default_style = ip_style. + endmethod. + + + + method SET_THEME. + theme = io_theme. +endmethod. + + + + + method STYLEMAPPING_DYNAMIC_STYLE. +" # issue 139 + eo_style2-dynamic_style_guid = ip_style->get_guid( ). + eo_style2-guid = eo_style2-dynamic_style_guid. + eo_style2-added_to_iterator = abap_true. + eo_style2-cl_style = ip_style. + +* don't care about attributes here, since this data may change +* dynamically + + endmethod. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PROCESS BEFORE OUTPUT. + MODULE STATUS_9000. + +PROCESS AFTER INPUT. + MODULE USER_COMMAND_9000 AT EXIT-COMMAND. + MODULE USER_COMMAND_9000. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + REPORT. + +CONSTANTS: gc_save_file_name TYPE string VALUE 'ABAP2XLSX Inheritance.xlsx'. + +*--------------------------------------------------------------------* +* Demo inheritance ZCL_EXCEL1 +* Variation of ZCL_EXCEL that creates numerous sheets +*--------------------------------------------------------------------* +CLASS lcl_my_zcl_excel1 DEFINITION INHERITING FROM zcl_excel. + PUBLIC SECTION. + METHODS: constructor IMPORTING iv_sheetcount TYPE i DEFAULT 5. +ENDCLASS. + +CLASS lcl_my_zcl_excel1 IMPLEMENTATION. + METHOD constructor. + DATA: lv_sheets_to_create TYPE i. + super->constructor( ). + lv_sheets_to_create = iv_sheetcount - 1. " one gets created by standard class + DO lv_sheets_to_create TIMES. + TRY. + me->add_new_worksheet( ). + CATCH zcx_excel. + ENDTRY. + ENDDO. + me->set_active_sheet_index( 1 ). + + ENDMETHOD. +ENDCLASS. + +*--------------------------------------------------------------------* +* Demo inheritance ZCL_EXCEL_WORKSHEET +* Variation of ZCL_EXCEL_WORKSHEET ( and ZCL_EXCEL that calls the new type of worksheet ) +* that sets a fixed title +*--------------------------------------------------------------------* +CLASS lcl_my_zcl_excel2 DEFINITION INHERITING FROM zcl_excel. + PUBLIC SECTION. + METHODS: constructor. +ENDCLASS. + +CLASS lcl_my_zcl_excel_worksheet DEFINITION INHERITING FROM zcl_excel_worksheet. + PUBLIC SECTION. + METHODS: constructor IMPORTING ip_excel TYPE REF TO zcl_excel + ip_title TYPE zexcel_sheet_title OPTIONAL " Will be ignored - keep parameter for demonstration purpose + RAISING zcx_excel. +ENDCLASS. + +CLASS lcl_my_zcl_excel2 IMPLEMENTATION. + METHOD constructor. + + DATA: lo_worksheet TYPE REF TO zcl_excel_worksheet. + + super->constructor( ). + +* To use own worksheet we have to remove the standard worksheet + lo_worksheet = get_active_worksheet( ). + me->worksheets->remove( lo_worksheet ). +* and replace it with own version + CREATE OBJECT lo_worksheet TYPE lcl_my_zcl_excel_worksheet + EXPORTING + ip_excel = me + ip_title = 'This title will be ignored'. + me->worksheets->add( lo_worksheet ). + + ENDMETHOD. +ENDCLASS. + +CLASS lcl_my_zcl_excel_worksheet IMPLEMENTATION. + METHOD constructor. + super->constructor( ip_excel = ip_excel + ip_title = 'Inherited Worksheet' ). + + ENDMETHOD. +ENDCLASS. + +DATA: go_excel1 TYPE REF TO lcl_my_zcl_excel1. +DATA: go_excel2 TYPE REF TO lcl_my_zcl_excel2. + + +SELECTION-SCREEN BEGIN OF BLOCK bli WITH FRAME TITLE text-bli. +PARAMETERS: rbi_1 RADIOBUTTON GROUP rbi DEFAULT 'X' , " Simple inheritance + rbi_2 RADIOBUTTON GROUP rbi. +SELECTION-SCREEN END OF BLOCK bli. + +INCLUDE zdemo_excel_outputopt_incl. + +END-OF-SELECTION. + + CASE 'X'. + + WHEN rbi_1. " Simple inheritance of zcl_excel, object created directly + CREATE OBJECT go_excel1 + EXPORTING + iv_sheetcount = 5. + lcl_output=>output( go_excel1 ). + + WHEN rbi_2. " Inheritance of zcl_excel_worksheet, inheritance of zcl_excel needed to allow this + CREATE OBJECT go_excel2. + lcl_output=>output( go_excel2 ). + + + ENDCASE. + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZABAP2XLSX_DEMO_SHOW +*&---------------------------------------------------------------------* +REPORT zabap2xlsx_demo_like_se83. + + +*----------------------------------------------------------------------* +* CLASS lcl_perform DEFINITION +*----------------------------------------------------------------------* +CLASS lcl_perform DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS: setup_objects, + collect_reports, + + handle_nav FOR EVENT double_click OF cl_gui_alv_grid + IMPORTING e_row. + + PRIVATE SECTION. + TYPES: BEGIN OF ty_reports, + progname TYPE reposrc-progname, + sort TYPE reposrc-progname, + filename TYPE string, + END OF ty_reports. + + CLASS-DATA: + lo_grid TYPE REF TO cl_gui_alv_grid, + lo_text TYPE REF TO cl_gui_textedit, + cl_document TYPE REF TO i_oi_document_proxy, + + t_reports TYPE STANDARD TABLE OF ty_reports WITH NON-UNIQUE DEFAULT KEY. + CLASS-DATA:error TYPE REF TO i_oi_error, + t_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY, + cl_control TYPE REF TO i_oi_container_control. "Office Dokument + +ENDCLASS. "lcl_perform DEFINITION + + +START-OF-SELECTION. + lcl_perform=>collect_reports( ). + lcl_perform=>setup_objects( ). + +END-OF-SELECTION. + + WRITE '.'. " Force output + + +*----------------------------------------------------------------------* +* CLASS lcl_perform IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_perform IMPLEMENTATION. + METHOD setup_objects. + DATA: lo_split TYPE REF TO cl_gui_splitter_container, + lo_container TYPE REF TO cl_gui_container. + + DATA: it_fieldcat TYPE lvc_t_fcat, + is_layout TYPE lvc_s_layo, + is_variant TYPE disvariant. + FIELD-SYMBOLS: <fc> LIKE LINE OF it_fieldcat. + + + CREATE OBJECT lo_split + EXPORTING + parent = cl_gui_container=>screen0 + rows = 1 + columns = 3 + no_autodef_progid_dynnr = 'X'. + lo_split->set_column_width( EXPORTING id = 1 + width = 20 ). + lo_split->set_column_width( EXPORTING id = 2 + width = 40 ). + +* Left: List of reports + lo_container = lo_split->get_container( row = 1 + column = 1 ). + + CREATE OBJECT lo_grid + EXPORTING + i_parent = lo_container. + SET HANDLER lcl_perform=>handle_nav FOR lo_grid. + + is_variant-report = sy-repid. + is_variant-handle = '0001'. + + is_layout-cwidth_opt = 'X'. + + APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. + <fc>-fieldname = 'PROGNAME'. + <fc>-tabname = 'REPOSRC'. + + APPEND INITIAL LINE TO it_fieldcat ASSIGNING <fc>. + <fc>-fieldname = 'SORT'. + <fc>-ref_field = 'PROGNAME'. + <fc>-ref_table = 'REPOSRC'. + + + lo_grid->set_table_for_first_display( EXPORTING + is_variant = is_variant + i_save = 'A' + is_layout = is_layout + CHANGING + it_outtab = t_reports + it_fieldcatalog = it_fieldcat + EXCEPTIONS + invalid_parameter_combination = 1 + program_error = 2 + too_many_lines = 3 + OTHERS = 4 ). + +* Middle: Text with coding + lo_container = lo_split->get_container( row = 1 + column = 2 ). + CREATE OBJECT lo_text + EXPORTING + parent = lo_container. + lo_text->set_readonly_mode( cl_gui_textedit=>true ). + lo_text->set_font_fixed( ). + + + +* right: DemoOutput + lo_container = lo_split->get_container( row = 1 + column = 3 ). + + c_oi_container_control_creator=>get_container_control( IMPORTING control = cl_control + error = error ). + APPEND error TO t_errors. + + cl_control->init_control( EXPORTING inplace_enabled = 'X' + no_flush = 'X' + r3_application_name = 'Demo Document Container' + parent = lo_container + IMPORTING error = error + EXCEPTIONS OTHERS = 2 ). + APPEND error TO t_errors. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + APPEND error TO t_errors. +* Errorhandling should be inserted here + + + ENDMETHOD. "setup_objects + + "collect_reports + METHOD collect_reports. + FIELD-SYMBOLS:<report> LIKE LINE OF t_reports. + DATA: t_source TYPE STANDARD TABLE OF text255 WITH NON-UNIQUE DEFAULT KEY. + +* Get all demoreports + SELECT progname + INTO CORRESPONDING FIELDS OF TABLE t_reports + FROM reposrc + WHERE progname LIKE 'ZDEMO_EXCEL%' + AND progname <> sy-repid + AND subc = '1'. + + LOOP AT t_reports ASSIGNING <report>. + +* Check if already switched to new outputoptions + READ REPORT <report>-progname INTO t_source. + IF sy-subrc = 0. + FIND 'INCLUDE zdemo_excel_outputopt_incl.' IN TABLE t_source IGNORING CASE. + ENDIF. + IF sy-subrc <> 0. + DELETE t_reports. + CONTINUE. + ENDIF. + + +* Build half-numeric sort + <report>-sort = <report>-progname. + REPLACE REGEX '(ZDEMO_EXCEL)(\d\d)\s*$' IN <report>-sort WITH '$1\0$2'. " REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE REGEX '(ZDEMO_EXCEL)([^][^])*$' IN <report>-sort WITH '$1$2'.REPLACE + + REPLACE REGEX '(ZDEMO_EXCEL)(\d)\s*$' IN <report>-sort WITH '$1\0\0$2'. + ENDLOOP. + SORT t_reports BY sort progname. + + ENDMETHOD. "collect_reports + + METHOD handle_nav. + CONSTANTS: filename TYPE text80 VALUE 'ZABAP2XLSX_DEMO_SHOW.xlsx'. + DATA: wa_report LIKE LINE OF t_reports, + t_source TYPE STANDARD TABLE OF text255, + t_rawdata TYPE solix_tab, + wa_rawdata LIKE LINE OF t_rawdata, + bytecount TYPE i, + length TYPE i, + add_selopt TYPE flag. + + + READ TABLE t_reports INTO wa_report INDEX e_row-index. + CHECK sy-subrc = 0. + +* Set new text into middle frame + READ REPORT wa_report-progname INTO t_source. + lo_text->set_text_as_r3table( EXPORTING table = t_source ). + + +* Unload old xls-file + cl_document->close_document( ). + +* Get the demo +* If additional parameters found on selection screen, start via selection screen , otherwise start w/o + CLEAR add_selopt. + FIND 'PARAMETERS' IN TABLE t_source. + IF sy-subrc = 0. + add_selopt = 'X'. + ELSE. + FIND 'SELECT-OPTIONS' IN TABLE t_source. + IF sy-subrc = 0. + add_selopt = 'X'. + ENDIF. + ENDIF. + IF add_selopt IS INITIAL. + SUBMIT (wa_report-progname) AND RETURN "#EC CI_SUBMIT + WITH p_backfn = filename + WITH rb_back = 'X' + WITH rb_down = ' ' + WITH rb_send = ' ' + WITH rb_show = ' '. + ELSE. + SUBMIT (wa_report-progname) VIA SELECTION-SCREEN AND RETURN "#EC CI_SUBMIT + WITH p_backfn = filename + WITH rb_back = 'X' + WITH rb_down = ' ' + WITH rb_send = ' ' + WITH rb_show = ' '. + ENDIF. + + OPEN DATASET filename FOR INPUT IN BINARY MODE. + IF sy-subrc = 0. + DO. + CLEAR wa_rawdata. + READ DATASET filename INTO wa_rawdata LENGTH length. + IF sy-subrc <> 0. + APPEND wa_rawdata TO t_rawdata. + ADD length TO bytecount. + EXIT. + ENDIF. + APPEND wa_rawdata TO t_rawdata. + ADD length TO bytecount. + ENDDO. + CLOSE DATASET filename. + ENDIF. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + + cl_document->open_document_from_table( EXPORTING document_size = bytecount + document_table = t_rawdata + open_inplace = 'X' ). + + ENDMETHOD. "handle_nav + +ENDCLASS. "lcl_perform IMPLEMENTATION + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZANGRY_BIRDS +*& Just for fun +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zangry_birds. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_border_light TYPE REF TO zcl_excel_style_border, + lo_style_color0 TYPE REF TO zcl_excel_style, + lo_style_color1 TYPE REF TO zcl_excel_style, + lo_style_color2 TYPE REF TO zcl_excel_style, + lo_style_color3 TYPE REF TO zcl_excel_style, + lo_style_color4 TYPE REF TO zcl_excel_style, + lo_style_color5 TYPE REF TO zcl_excel_style, + lo_style_color6 TYPE REF TO zcl_excel_style, + lo_style_color7 TYPE REF TO zcl_excel_style, + lo_style_credit TYPE REF TO zcl_excel_style, + lo_style_link TYPE REF TO zcl_excel_style, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink. + +DATA: lv_style_color0_guid TYPE zexcel_cell_style, + lv_style_color1_guid TYPE zexcel_cell_style, + lv_style_color2_guid TYPE zexcel_cell_style, + lv_style_color3_guid TYPE zexcel_cell_style, + lv_style_color4_guid TYPE zexcel_cell_style, + lv_style_color5_guid TYPE zexcel_cell_style, + lv_style_color6_guid TYPE zexcel_cell_style, + lv_style_color7_guid TYPE zexcel_cell_style, + lv_style_credit_guid TYPE zexcel_cell_style, + lv_style_link_guid TYPE zexcel_cell_style, + lv_style TYPE zexcel_cell_style. + +DATA: lv_col_str TYPE zexcel_cell_column_alpha, + lv_row TYPE i, + lv_col TYPE i, + lt_mapper TYPE TABLE OF zexcel_cell_style, + ls_mapper TYPE zexcel_cell_style. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'angry_birds.xlsx'. + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + " Creates active sheet + CREATE OBJECT lo_excel. + + CREATE OBJECT lo_border_light. + lo_border_light->border_color-rgb = zcl_excel_style_color=>c_white. + lo_border_light->border_style = zcl_excel_style_border=>c_border_thin. + + " Create color white + lo_style_color0 = lo_excel->add_new_style( ). + lo_style_color0->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color0->fill->fgcolor-rgb = 'FFFFFFFF'. + lo_style_color0->borders->allborders = lo_border_light. + lv_style_color0_guid = lo_style_color0->get_guid( ). + + " Create color black + lo_style_color1 = lo_excel->add_new_style( ). + lo_style_color1->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color1->fill->fgcolor-rgb = 'FF252525'. + lo_style_color1->borders->allborders = lo_border_light. + lv_style_color1_guid = lo_style_color1->get_guid( ). + + " Create color dark green + lo_style_color2 = lo_excel->add_new_style( ). + lo_style_color2->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color2->fill->fgcolor-rgb = 'FF75913A'. + lo_style_color2->borders->allborders = lo_border_light. + lv_style_color2_guid = lo_style_color2->get_guid( ). + + " Create color light green + lo_style_color3 = lo_excel->add_new_style( ). + lo_style_color3->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color3->fill->fgcolor-rgb = 'FF9DFB73'. + lo_style_color3->borders->allborders = lo_border_light. + lv_style_color3_guid = lo_style_color3->get_guid( ). + + " Create color green + lo_style_color4 = lo_excel->add_new_style( ). + lo_style_color4->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color4->fill->fgcolor-rgb = 'FF92CF56'. + lo_style_color4->borders->allborders = lo_border_light. + lv_style_color4_guid = lo_style_color4->get_guid( ). + + " Create color 2dark green + lo_style_color5 = lo_excel->add_new_style( ). + lo_style_color5->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color5->fill->fgcolor-rgb = 'FF506228'. + lo_style_color5->borders->allborders = lo_border_light. + lv_style_color5_guid = lo_style_color5->get_guid( ). + + " Create color yellow + lo_style_color6 = lo_excel->add_new_style( ). + lo_style_color6->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color6->fill->fgcolor-rgb = 'FFC3E224'. + lo_style_color6->borders->allborders = lo_border_light. + lv_style_color6_guid = lo_style_color6->get_guid( ). + + " Create color yellow + lo_style_color7 = lo_excel->add_new_style( ). + lo_style_color7->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_color7->fill->fgcolor-rgb = 'FFB3C14F'. + lo_style_color7->borders->allborders = lo_border_light. + lv_style_color7_guid = lo_style_color7->get_guid( ). + + " Credits + lo_style_credit = lo_excel->add_new_style( ). + lo_style_credit->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_credit->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lo_style_credit->font->size = 20. + lv_style_credit_guid = lo_style_credit->get_guid( ). + + " Link + lo_style_link = lo_excel->add_new_style( ). + lo_style_link->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_link->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. +* lo_style_link->font->size = 20. + lv_style_link_guid = lo_style_link->get_guid( ). + + " Create image map " line 2 + DO 30 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 3 + DO 28 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 4 + DO 27 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 5 + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 15 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 6 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 13 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 7 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 8 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 9 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 10 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 11 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 7 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 12 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 13 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 14 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 12 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 15 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 16 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 7 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 17 + DO 8 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 13 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 18 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 23 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 19 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 27 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 20 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 23 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 21 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 19 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 22 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 17 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 23 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 17 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 24 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 25 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 26 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color6_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 27 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color6_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 28 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color6_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 29 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 30 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 31 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color4_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 32 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color5_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 33 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 34 + DO 3 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 35 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 36 + DO 4 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 37 + DO 5 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color7_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 38 + DO 6 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 10 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 11 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 39 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 22 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 1 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 40 + DO 7 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 17 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 41 + DO 8 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 3 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 15 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 42 + DO 9 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 9 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 2 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 43 + DO 11 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 5 TIMES. APPEND lv_style_color3_guid TO lt_mapper. ENDDO. + DO 7 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 44 + DO 13 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 6 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + DO 4 TIMES. APPEND lv_style_color2_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 45 + DO 16 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 13 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + " line 46 + DO 18 TIMES. APPEND lv_style_color0_guid TO lt_mapper. ENDDO. + DO 8 TIMES. APPEND lv_style_color1_guid TO lt_mapper. ENDDO. + APPEND INITIAL LINE TO lt_mapper. " escape + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Angry Birds' ). + + lv_row = 1. + lv_col = 1. + + LOOP AT lt_mapper INTO ls_mapper. + lv_col_str = zcl_excel_common=>convert_column2alpha( lv_col ). + IF ls_mapper IS INITIAL. + lo_row_dimension = lo_worksheet->get_row_dimension( ip_row = lv_row ). + lo_row_dimension->set_row_height( ip_row_height = 8 ). + lv_col = 1. + lv_row = lv_row + 1. + CONTINUE. + ENDIF. + lo_worksheet->set_cell( ip_column = lv_col_str + ip_row = lv_row + ip_value = space + ip_style = ls_mapper ). + lv_col = lv_col + 1. + + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = lv_col_str ). + lo_column_dimension->set_width( ip_width = 2 ). + ENDLOOP. + + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_false ). + + lo_worksheet->set_cell( ip_column = 'AP' + ip_row = 15 + ip_value = 'Created with abap2xlsx' + ip_style = lv_style_credit_guid ). + + lo_hyperlink = zcl_excel_hyperlink=>create_external_link( iv_url = 'http://www.abap2xlsx.org' ). + lo_worksheet->set_cell( ip_column = 'AP' + ip_row = 24 + ip_value = 'http://www.abap2xlsx.org' + ip_style = lv_style_link_guid + ip_hyperlink = lo_hyperlink ). + + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'AP' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_worksheet->set_merge( ip_row = 15 ip_column_start = 'AP' ip_row_to = 22 ip_column_end = 'AR' ). + lo_worksheet->set_merge( ip_row = 24 ip_column_start = 'AP' ip_row_to = 26 ip_column_end = 'AR' ). + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + + + + + + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_CALENDAR +*& abap2xlsx Demo: Create Calendar with Pictures +*&---------------------------------------------------------------------* +*& This report creates a monthly calendar in the specified date range. +*& Each month is put on a seperate worksheet. The pictures for each +*& month can be specified in a tab delimited file called "Calendar.txt" +*& which is saved in the Export Directory. By default this is the SAP +*& Workdir. The file contains 3 fields: +*& +*& Month (with leading 0) +*& Image Filename +*& Image Description +*& URL for the Description +*& +*& The Images should be landscape JPEG's with a 3:2 ratio and min. +*& 450 pixel height. They must also be saved in the Export Directory. +*& In my tests I've discovered a limit of 20 MB in the +*& cl_gui_frontend_services=>gui_download method. So keep your images +*& smaller or change to a server export using OPEN DATASET. +*&---------------------------------------------------------------------* + +REPORT zdemo_calendar. + +TYPE-POOLS: abap. +CONSTANTS: gc_save_file_name TYPE string VALUE 'Calendar.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. +INCLUDE zdemo_calendar_classes. + +DATA: lv_workdir TYPE string. + +PARAMETERS: p_from TYPE dfrom DEFAULT '20130101', + p_to TYPE dto DEFAULT '20131231'. + +SELECTION-SCREEN BEGIN OF BLOCK orientation WITH FRAME TITLE orient. +PARAMETERS: p_portr TYPE flag RADIOBUTTON GROUP orie, + p_lands TYPE flag RADIOBUTTON GROUP orie DEFAULT 'X'. +SELECTION-SCREEN END OF BLOCK orientation. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + orient = 'Orientation'(000). + +START-OF-SELECTION. + + DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi, + hyperlink TYPE REF TO zcl_excel_hyperlink, + lo_drawing TYPE REF TO zcl_excel_drawing. + + DATA: lo_style_month TYPE REF TO zcl_excel_style, + lv_style_month_guid TYPE zexcel_cell_style. + DATA: lo_style_border TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + lv_style_border_guid TYPE zexcel_cell_style. + DATA: lo_style_center TYPE REF TO zcl_excel_style, + lv_style_center_guid TYPE zexcel_cell_style. + + DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + + DATA: lv_full_path TYPE string, + image_descr_path TYPE string, + lv_file_separator TYPE c. + DATA: lv_content TYPE xstring, + width TYPE i, + lv_height TYPE i, + lv_from_row TYPE zexcel_cell_row. + + DATA: month TYPE i, + month_nr TYPE fcmnr, + count TYPE i VALUE 1, + title TYPE zexcel_sheet_title, + value TYPE string, + image_path TYPE string, + date_from TYPE datum, + date_to TYPE datum, + row TYPE zexcel_cell_row, + to_row TYPE zexcel_cell_row, + to_col TYPE zexcel_cell_column_alpha, + to_col_end TYPE zexcel_cell_column_alpha, + to_col_int TYPE i. + + DATA: month_names TYPE TABLE OF t247. + FIELD-SYMBOLS: <month_name> LIKE LINE OF month_names. + + TYPES: BEGIN OF tt_datatab, + month_nr TYPE fcmnr, + filename TYPE string, + descr TYPE string, + url TYPE string, + END OF tt_datatab. + + DATA: image_descriptions TYPE TABLE OF tt_datatab. + FIELD-SYMBOLS: <img_descr> LIKE LINE OF image_descriptions. + + CONSTANTS: lv_default_file_name TYPE string VALUE 'Calendar', "#EC NOTEXT + c_from_row_portrait TYPE zexcel_cell_row VALUE 28, + c_from_row_landscape TYPE zexcel_cell_row VALUE 38, + from_col TYPE zexcel_cell_column_alpha VALUE 'C', + c_height_portrait TYPE i VALUE 450, " Image Height in Portrait Mode + c_height_landscape TYPE i VALUE 670, " Image Height in Landscape Mode + c_factor TYPE f VALUE '1.5'. " Image Ratio, default 3:2 + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name '.xlsx' INTO lv_full_path. "#EC NOTEXT + + " Read Image Names for Month and Description + CONCATENATE p_path lv_file_separator lv_default_file_name '.txt' INTO image_descr_path. "#EC NOTEXT + cl_gui_frontend_services=>gui_upload( + EXPORTING + filename = image_descr_path " Name of file + filetype = 'ASC' " File Type (ASCII, Binary) + has_field_separator = 'X' + read_by_line = 'X' " File Written Line-By-Line to the Internal Table + CHANGING + data_tab = image_descriptions " Transfer table for file contents + 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. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create Styles + " Create an underline double style + lo_style_month = lo_excel->add_new_style( ). + " lo_style_month->font->underline = abap_true. + " lo_style_month->font->underline_mode = zcl_excel_style_font=>c_underline_single. + lo_style_month->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_month->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_month->font->family = zcl_excel_style_font=>c_family_roman. + lo_style_month->font->bold = abap_true. + lo_style_month->font->size = 36. + lv_style_month_guid = lo_style_month->get_guid( ). + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + "Create style with border + lo_style_border = lo_excel->add_new_style( ). + lo_style_border->borders->allborders = lo_border_dark. + lo_style_border->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_right. + lo_style_border->alignment->vertical = zcl_excel_style_alignment=>c_vertical_top. + lv_style_border_guid = lo_style_border->get_guid( ). + "Create style alignment center + lo_style_center = lo_excel->add_new_style( ). + lo_style_center->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_center->alignment->vertical = zcl_excel_style_alignment=>c_vertical_top. + lv_style_center_guid = lo_style_center->get_guid( ). + + " Get Month Names + CALL FUNCTION 'MONTH_NAMES_GET' + TABLES + month_names = month_names. + + zcl_date_calculation=>months_between_two_dates( + EXPORTING + i_date_from = p_from + i_date_to = p_to + i_incl_to = abap_true + IMPORTING + e_month = month + ). + + date_from = p_from. + + WHILE count <= month. + IF count = 1. + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + ELSE. + lo_worksheet = lo_excel->add_new_worksheet( ). + ENDIF. + + lo_worksheet->zif_excel_sheet_properties~selected = zif_excel_sheet_properties=>c_selected. + + title = count. + value = count. + CONDENSE title. + CONDENSE value. + lo_worksheet->set_title( title ). + lo_worksheet->set_print_gridlines( abap_false ). + lo_worksheet->sheet_setup->paper_size = zcl_excel_sheet_setup=>c_papersize_a4. + lo_worksheet->sheet_setup->horizontal_centered = abap_true. + lo_worksheet->sheet_setup->vertical_centered = abap_true. + lo_col_dim = lo_worksheet->get_column_dimension( 'A' ). + lo_col_dim->set_width( '1.0' ). + lo_col_dim = lo_worksheet->get_column_dimension( 'B' ). + lo_col_dim->set_width( '2.0' ). + IF p_lands = abap_true. + lo_worksheet->sheet_setup->orientation = zcl_excel_sheet_setup=>c_orientation_landscape. + lv_height = c_height_landscape. + lv_from_row = c_from_row_landscape. + lo_worksheet->sheet_setup->margin_top = '0.10'. + lo_worksheet->sheet_setup->margin_left = '0.10'. + lo_worksheet->sheet_setup->margin_right = '0.10'. + lo_worksheet->sheet_setup->margin_bottom = '0.10'. + ELSE. + lo_col_dim = lo_worksheet->get_column_dimension( 'K' ). + lo_col_dim->set_width( '3.0' ). + lo_worksheet->sheet_setup->margin_top = '0.80'. + lo_worksheet->sheet_setup->margin_left = '0.55'. + lo_worksheet->sheet_setup->margin_right = '0.05'. + lo_worksheet->sheet_setup->margin_bottom = '0.30'. + lv_height = c_height_portrait. + lv_from_row = c_from_row_portrait. + ENDIF. + + " Add Month Name + month_nr = date_from+4(2). + IF p_portr = abap_true. + READ TABLE month_names WITH KEY mnr = month_nr ASSIGNING <month_name>. + CONCATENATE <month_name>-ltx ` ` date_from(4) INTO value. + row = lv_from_row - 2. + to_col = from_col. + ELSE. + row = lv_from_row - 1. + to_col_int = zcl_excel_common=>convert_column2int( from_col ) + 32. + to_col = zcl_excel_common=>convert_column2alpha( to_col_int ). + to_col_int = to_col_int + 1. + to_col_end = zcl_excel_common=>convert_column2alpha( to_col_int ). + CONCATENATE month_nr '/' date_from+2(2) INTO value. + to_row = row + 2. + lo_worksheet->set_merge( + EXPORTING + ip_column_start = to_col " Cell Column Start + ip_column_end = to_col_end " Cell Column End + ip_row = row " Cell Row + ip_row_to = to_row " Cell Row + ). + ENDIF. + lo_worksheet->set_cell( + EXPORTING + ip_column = to_col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = lv_style_month_guid + ). + +* to_col_int = zcl_excel_common=>convert_column2int( from_col ) + 7. +* to_col = zcl_excel_common=>convert_column2alpha( to_col_int ). +* +* lo_worksheet->set_merge( +* EXPORTING +* ip_column_start = from_col " Cell Column Start +* ip_column_end = to_col " Cell Column End +* ip_row = row " Cell Row +* ip_row_to = row " Cell Row +* ). + + " Add drawing from a XSTRING read from a file + UNASSIGN <img_descr>. + READ TABLE image_descriptions WITH KEY month_nr = month_nr ASSIGNING <img_descr>. + IF <img_descr> IS ASSIGNED. + value = <img_descr>-descr. + IF p_portr = abap_true. + row = lv_from_row - 3. + ELSE. + row = lv_from_row - 2. + ENDIF. + IF NOT <img_descr>-url IS INITIAL. + hyperlink = zcl_excel_hyperlink=>create_external_link( <img_descr>-url ). + lo_worksheet->set_cell( + EXPORTING + ip_column = from_col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_hyperlink = hyperlink + ). + ELSE. + lo_worksheet->set_cell( + EXPORTING + ip_column = from_col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ). + ENDIF. + lo_row_dim = lo_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '22.0' ). + + " In Landscape mode the row between the description and the + " dates should be not so high + IF p_lands = abap_true. + row = lv_from_row - 3. + lo_worksheet->set_cell( + EXPORTING + ip_column = from_col " Cell Column + ip_row = row " Cell Row + ip_value = ' ' " Cell Value + ). + lo_row_dim = lo_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '7.0' ). + row = lv_from_row - 1. + lo_row_dim = lo_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '5.0' ). + ENDIF. + + CONCATENATE p_path lv_file_separator <img_descr>-filename INTO image_path. + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 1 + ip_from_col = 'B' ). + + lv_content = zcl_helper=>load_image( image_path ). + width = lv_height * c_factor. + lo_drawing->set_media( ip_media = lv_content + ip_media_type = zcl_excel_drawing=>c_media_type_jpg + ip_width = width + ip_height = lv_height ). + lo_worksheet->add_drawing( lo_drawing ). + ENDIF. + + " Add Calendar +* CALL FUNCTION 'SLS_MISC_GET_LAST_DAY_OF_MONTH' +* EXPORTING +* day_in = date_from +* IMPORTING +* last_day_of_month = date_to. + date_to = date_from. + date_to+6(2) = '01'. " First of month + add 31 to date_to. " Somewhere in following month + date_to = date_to - date_to+6(2). " Last of month + IF p_portr = abap_true. + zcl_helper=>add_calendar( + EXPORTING + i_date_from = date_from + i_date_to = date_to + i_from_row = lv_from_row + i_from_col = from_col + i_day_style = lv_style_border_guid + i_cw_style = lv_style_center_guid + CHANGING + c_worksheet = lo_worksheet + ). + ELSE. + zcl_helper=>add_calendar_landscape( + EXPORTING + i_date_from = date_from + i_date_to = date_to + i_from_row = lv_from_row + i_from_col = from_col + i_day_style = lv_style_border_guid + i_cw_style = lv_style_center_guid + CHANGING + c_worksheet = lo_worksheet + ). + ENDIF. + count = count + 1. + date_from = date_to + 1. + ENDWHILE. + + lo_excel->set_active_sheet_index_by_name( '1' ). +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Include ZDEMO_CALENDAR_CLASSES +*&---------------------------------------------------------------------* + +*&---------------------------------------------------------------------* +*& Class ZCL_DATE_CALCULATION +*&---------------------------------------------------------------------* +* Text +*----------------------------------------------------------------------* +CLASS zcl_date_calculation DEFINITION. + PUBLIC SECTION. + CLASS-METHODS: months_between_two_dates + IMPORTING + i_date_from TYPE datum + i_date_to TYPE datum + i_incl_to TYPE flag + EXPORTING + e_month TYPE i. +ENDCLASS. "ZCL_DATE_CALCULATION + + +*----------------------------------------------------------------------* +* CLASS ZCL_DATE_CALCULATION IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_date_calculation IMPLEMENTATION. + METHOD months_between_two_dates. + DATA: date_to TYPE datum. + DATA: BEGIN OF datum_von, + jjjj(4) TYPE n, + mm(2) TYPE n, + tt(2) TYPE n, + END OF datum_von. + + DATA: BEGIN OF datum_bis, + jjjj(4) TYPE n, + mm(2) TYPE n, + tt(2) TYPE n, + END OF datum_bis. + + e_month = 0. + + CHECK NOT ( i_date_from IS INITIAL ) + AND NOT ( i_date_to IS INITIAL ). + + date_to = i_date_to. + IF i_incl_to = abap_true. + date_to = date_to + 1. + ENDIF. + + datum_von = i_date_from. + datum_bis = date_to. + + e_month = ( datum_bis-jjjj - datum_von-jjjj ) * 12 + + ( datum_bis-mm - datum_von-mm ). + ENDMETHOD. "MONTHS_BETWEEN_TWO_DATES +ENDCLASS. "ZCL_DATE_CALCULATION IMPLEMENTATION + +*----------------------------------------------------------------------* +* CLASS zcl_date_calculation_test DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_date_calculation_test DEFINITION FOR TESTING + " DURATION SHORT + " RISK LEVEL HARMLESS + "#AU Duration Medium + "#AU Risk_Level Harmless + . + PUBLIC SECTION. + METHODS: + months_between_two_dates FOR TESTING. +ENDCLASS. "zcl_date_calculation_test DEFINITION +*----------------------------------------------------------------------* +* CLASS zcl_date_calculation_test IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_date_calculation_test IMPLEMENTATION. + METHOD months_between_two_dates. + + DATA: date_from TYPE datum VALUE '20120101', + date_to TYPE datum VALUE '20121231'. + DATA: month TYPE i. + + zcl_date_calculation=>months_between_two_dates( + EXPORTING + i_date_from = date_from + i_date_to = date_to + i_incl_to = abap_true + IMPORTING + e_month = month + ). + + cl_aunit_assert=>assert_equals( + exp = 12 " Data Object with Expected Type + act = month " Data Object with Current Value + msg = 'Calculated date is wrong' " Message in Case of Error + ). + + ENDMETHOD. "months_between_two_dates +ENDCLASS. "zcl_date_calculation_test IMPLEMENTATION +*----------------------------------------------------------------------* +* CLASS zcl_helper DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_helper DEFINITION. + PUBLIC SECTION. + CLASS-METHODS: + load_image + IMPORTING + filename TYPE string + RETURNING value(r_image) TYPE xstring, + add_calendar + IMPORTING + i_date_from TYPE datum + i_date_to TYPE datum + i_from_row TYPE zexcel_cell_row + i_from_col TYPE zexcel_cell_column_alpha + i_day_style TYPE zexcel_cell_style + i_cw_style TYPE zexcel_cell_style + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet, + add_calendar_landscape + IMPORTING + i_date_from TYPE datum + i_date_to TYPE datum + i_from_row TYPE zexcel_cell_row + i_from_col TYPE zexcel_cell_column_alpha + i_day_style TYPE zexcel_cell_style + i_cw_style TYPE zexcel_cell_style + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet, + add_a2x_footer + IMPORTING + i_from_row TYPE zexcel_cell_row + i_from_col TYPE zexcel_cell_column_alpha + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet, + add_calender_week + IMPORTING + i_date TYPE datum + i_row TYPE zexcel_cell_row + i_col TYPE zexcel_cell_column_alpha + i_style TYPE zexcel_cell_style + CHANGING + c_worksheet TYPE REF TO zcl_excel_worksheet. +ENDCLASS. "zcl_helper DEFINITION + +*----------------------------------------------------------------------* +* CLASS zcl_helper IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS zcl_helper IMPLEMENTATION. + METHOD load_image. + "Load samle image + DATA: lt_bin TYPE solix_tab, + lv_len TYPE i. + + CALL METHOD cl_gui_frontend_services=>gui_upload + EXPORTING + filename = filename + filetype = 'BIN' + IMPORTING + filelength = lv_len + CHANGING + data_tab = lt_bin + 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. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_len + IMPORTING + buffer = r_image + TABLES + binary_tab = lt_bin + EXCEPTIONS + failed = 1 + OTHERS = 2. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + ENDMETHOD. "load_image + METHOD add_calendar. + DATA: day_names TYPE TABLE OF t246. + DATA: row TYPE zexcel_cell_row, + row_max TYPE i, + col_int TYPE zexcel_cell_column, + col_max TYPE i, + from_col_int TYPE zexcel_cell_column, + col TYPE zexcel_cell_column_alpha, + lr_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lr_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi. + DATA: lv_date TYPE datum, + value TYPE string, + weekday TYPE wotnr, + weekrow TYPE wotnr VALUE 1, + day TYPE i, + width TYPE f, + height TYPE f. + DATA: hyperlink TYPE REF TO zcl_excel_hyperlink. + + FIELD-SYMBOLS: <day_name> LIKE LINE OF day_names. + + lv_date = i_date_from. + from_col_int = zcl_excel_common=>convert_column2int( i_from_col ). + " Add description for Calendar Week + c_worksheet->set_cell( + EXPORTING + ip_column = i_from_col " Cell Column + ip_row = i_from_row " Cell Row + ip_value = 'CW'(001) " Cell Value + ip_style = i_cw_style + ). + + " Add Days + CALL FUNCTION 'DAY_NAMES_GET' + TABLES + day_names = day_names. + + LOOP AT day_names ASSIGNING <day_name>. + row = i_from_row. + col_int = from_col_int + <day_name>-wotnr. + col = zcl_excel_common=>convert_column2alpha( col_int ). + value = <day_name>-langt. + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_cw_style + ). + ENDLOOP. + + WHILE lv_date <= i_date_to. + day = lv_date+6(2). + CALL FUNCTION 'FIMA_X_DAY_IN_MONTH_COMPUTE' + EXPORTING + i_datum = lv_date + IMPORTING + e_wochentag_nr = weekday. + + row = i_from_row + weekrow. + col_int = from_col_int + weekday. + col = zcl_excel_common=>convert_column2alpha( col_int ). + + value = day. + CONDENSE value. + + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_day_style " Single-Character Indicator + ). + + IF weekday = 7. + " Add Calender Week + zcl_helper=>add_calender_week( + EXPORTING + i_date = lv_date + i_row = row + i_col = i_from_col + i_style = i_cw_style + CHANGING + c_worksheet = c_worksheet + ). + weekrow = weekrow + 1. + ENDIF. + lv_date = lv_date + 1. + ENDWHILE. + " Add Calender Week + zcl_helper=>add_calender_week( + EXPORTING + i_date = lv_date + i_row = row + i_col = i_from_col + i_style = i_cw_style + CHANGING + c_worksheet = c_worksheet + ). + " Add Created with abap2xlsx + row = row + 2. + zcl_helper=>add_a2x_footer( + EXPORTING + i_from_row = row + i_from_col = i_from_col + CHANGING + c_worksheet = c_worksheet + ). + col_int = from_col_int. + col_max = from_col_int + 7. + WHILE col_int <= col_max. + col = zcl_excel_common=>convert_column2alpha( col_int ). + IF sy-index = 1. + width = '5.0'. + ELSE. + width = '11.4'. + ENDIF. + lr_col_dim = c_worksheet->get_column_dimension( col ). + lr_col_dim->set_width( width ). + col_int = col_int + 1. + ENDWHILE. + row = i_from_row + 1. + row_max = i_from_row + 6. + WHILE row <= row_max. + height = 50. + lr_row_dim = c_worksheet->get_row_dimension( row ). + lr_row_dim->set_row_height( height ). + row = row + 1. + ENDWHILE. + ENDMETHOD. "add_calendar + METHOD add_a2x_footer. + DATA: value TYPE string, + hyperlink TYPE REF TO zcl_excel_hyperlink. + + value = 'Created with abap2xlsx. Find more information at http://abap2xlsx.org.'(002). + hyperlink = zcl_excel_hyperlink=>create_external_link( 'http://abap2xlsx.org' ). "#EC NOTEXT + c_worksheet->set_cell( + EXPORTING + ip_column = i_from_col " Cell Column + ip_row = i_from_row " Cell Row + ip_value = value " Cell Value + ip_hyperlink = hyperlink + ). + + ENDMETHOD. "add_a2x_footer + METHOD add_calendar_landscape. + DATA: day_names TYPE TABLE OF t246. + + DATA: lv_date TYPE datum, + day TYPE i, + value TYPE string, + weekday TYPE wotnr. + DATA: row TYPE zexcel_cell_row, + from_col_int TYPE zexcel_cell_column, + col_int TYPE zexcel_cell_column, + col TYPE zexcel_cell_column_alpha. + DATA: lo_col_dim TYPE REF TO zcl_excel_worksheet_columndime, + lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi. + + FIELD-SYMBOLS: <day_name> LIKE LINE OF day_names. + + lv_date = i_date_from. + " Add Days + CALL FUNCTION 'DAY_NAMES_GET' + TABLES + day_names = day_names. + + WHILE lv_date <= i_date_to. + day = lv_date+6(2). + CALL FUNCTION 'FIMA_X_DAY_IN_MONTH_COMPUTE' + EXPORTING + i_datum = lv_date + IMPORTING + e_wochentag_nr = weekday. + " Day name row + row = i_from_row. + col_int = from_col_int + day + 2. + col = zcl_excel_common=>convert_column2alpha( col_int ). + READ TABLE day_names ASSIGNING <day_name> + WITH KEY wotnr = weekday. + value = <day_name>-kurzt. + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_cw_style + ). + + " Day row + row = i_from_row + 1. + value = day. + CONDENSE value. + + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = value " Cell Value + ip_style = i_day_style " Single-Character Indicator + ). + " width + lo_col_dim = c_worksheet->get_column_dimension( col ). + lo_col_dim->set_width( '3.6' ). + + + lv_date = lv_date + 1. + ENDWHILE. + " Add ABAP2XLSX Footer + row = i_from_row + 2. + c_worksheet->set_cell( + EXPORTING + ip_column = col " Cell Column + ip_row = row " Cell Row + ip_value = ' ' " Cell Value + ). + lo_row_dim = c_worksheet->get_row_dimension( row ). + lo_row_dim->set_row_height( '5.0' ). + row = i_from_row + 3. + zcl_helper=>add_a2x_footer( + EXPORTING + i_from_row = row + i_from_col = i_from_col + CHANGING + c_worksheet = c_worksheet + ). + + " Set with for all 31 coulumns + WHILE day < 32. + day = day + 1. + col_int = from_col_int + day + 2. + col = zcl_excel_common=>convert_column2alpha( col_int ). + " width + lo_col_dim = c_worksheet->get_column_dimension( col ). + lo_col_dim->set_width( '3.6' ). + ENDWHILE. + ENDMETHOD. "ADD_CALENDAR_LANDSCAPE + + METHOD add_calender_week. + DATA: week TYPE kweek, + week_int TYPE i, + value TYPE string. + " Add Calender Week + CALL FUNCTION 'DATE_GET_WEEK' + EXPORTING + date = i_date " Date for which the week should be calculated + IMPORTING + week = week. " Week for date (format:YYYYWW) + value = week+4(2). + week_int = value. + value = week_int. + CONDENSE value. + c_worksheet->set_cell( + EXPORTING + ip_column = i_col " Cell Column + ip_row = i_row " Cell Row + ip_value = value " Cell Value + ip_style = i_style + ). + ENDMETHOD. "add_calender_week +ENDCLASS. "zcl_helper IMPLEMENTATION + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel. + +DATA: lv_workdir TYPE string, + lv_upfile TYPE string. + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = sy-lisel ). + CONCATENATE p_path sy-lisel '01_HelloWorld.xlsx' INTO lv_upfile. + + SUBMIT zdemo_excel1 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Hello world + SUBMIT zdemo_excel2 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Styles + SUBMIT zdemo_excel3 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: iTab binding + SUBMIT zdemo_excel4 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Multi sheets, page setup and sheet properties + SUBMIT zdemo_excel5 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Conditional formatting + SUBMIT zdemo_excel6 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Formulas + SUBMIT zdemo_excel7 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Conditional formatting + SUBMIT zdemo_excel8 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Ranges + SUBMIT zdemo_excel9 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Data validation + SUBMIT zdemo_excel10 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Bind table with field catalog + " zdemo_excel11 is not added because it has a selection screen and + " you also need to have business partners maintained in transaction BP + SUBMIT zdemo_excel12 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Column size + SUBMIT zdemo_excel13 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Merge cell + SUBMIT zdemo_excel14 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Alignment + " zdemo_excel15 added at the end + SUBMIT zdemo_excel16 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Drawing + SUBMIT zdemo_excel17 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Lock sheet + SUBMIT zdemo_excel18 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Lock workbook + SUBMIT zdemo_excel19 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Set active sheet + " zdemo_excel20 is not added because it uses ALV and cannot be processed (OLE2) + SUBMIT zdemo_excel21 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Color Picker + SUBMIT zdemo_excel22 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Bind table with field catalog & sheet style + SUBMIT zdemo_excel23 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Multiple sheets with and w/o grid lines, print options + SUBMIT zdemo_excel24 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Multiple sheets with different default date formats + SUBMIT zdemo_excel25 AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Create and xlsx on Application Server (could be executed in batch mode) + " zdemo_excel26 is not added because it uses ALV and cannot be processed (Native) + SUBMIT zdemo_excel27 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Conditional Formatting + SUBMIT zdemo_excel28 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: CSV writer + " SUBMIT zdemo_excel29 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Macro enabled workbook + SUBMIT zdemo_excel30 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: ABAP Cell data types + leading blanks string + SUBMIT zdemo_excel31 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Autosize Column with different Font sizes + " zdemo_excel32 is not added because it uses ALV and cannot be processed (Native) + SUBMIT zdemo_excel33 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Table autofilter + SUBMIT zdemo_excel34 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Static Styles Chess + SUBMIT zdemo_excel35 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Static Styles + SUBMIT zdemo_excel36 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Style applied to sheet, column and single cell + SUBMIT zdemo_excel37 WITH p_upfile = lv_upfile + WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Simplest call of the reader and writer - passthrough data + SUBMIT zdemo_excel38 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Show off integration of drawings ( here using the SAP-Icons ) + SUBMIT zdemo_excel39 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Charts + SUBMIT zdemo_excel40 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Demo Printsettings + SUBMIT zdemo_excel41 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT abap2xlsx Demo: Inheritance + " + " Reader/Writer Demo must always run at the end + " to make sure all documents where created + " + SUBMIT zdemo_excel15 WITH rb_down = abap_true WITH rb_show = abap_false WITH p_path = p_path AND RETURN. "#EC CI_SUBMIT Read Excel and write it back + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel1. + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +CONSTANTS: gc_save_file_name TYPE string VALUE '01_HelloWorld.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). +* lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = sy-datum ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = sy-uzeit ). + lo_hyperlink = zcl_excel_hyperlink=>create_external_link( iv_url = 'http://www.abap2xlsx.org' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 4 ip_value = 'Click here to visit abap2xlsx homepage' ip_hyperlink = lo_hyperlink ). + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + column_dimension->set_width( ip_width = 11 ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL10 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel10. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional2 TYPE REF TO zcl_excel_style_conditional, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +DATA: lt_field_catalog TYPE zexcel_t_fieldcatalog, + ls_table_settings TYPE zexcel_s_table_settings, + ls_iconset TYPE zexcel_conditional_iconset. + +CONSTANTS: gc_save_file_name TYPE string VALUE '10_iTabFieldCatalog.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + FIELD-SYMBOLS: <fs_field_catalog> TYPE zexcel_s_fieldcatalog. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Internal table' ). + + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_5arrows. + ls_iconset-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo1_value = '0'. + ls_iconset-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo2_value = '20'. + ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo3_value = '40'. + ls_iconset-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo4_value = '60'. + ls_iconset-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo5_value = '80'. + ls_iconset-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + "Conditional style + lo_style_conditional2 = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional2->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional2->mode_iconset = ls_iconset. + lo_style_conditional2->priority = 1. + + DATA lt_test TYPE TABLE OF sflight. + SELECT * FROM sflight INTO TABLE lt_test. "#EC CI_NOWHERE + + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_test ). + + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog>. + CASE <fs_field_catalog>-fieldname. + WHEN 'CARRID'. + <fs_field_catalog>-position = 3. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-totals_function = zcl_excel_table=>totals_function_count. + WHEN 'CONNID'. + <fs_field_catalog>-position = 4. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-abap_type = cl_abap_typedescr=>typekind_int. + "This avoid the excel warning that the number is formatted as a text: abap2xlsx is not able to recognize numc as a number so it formats the number as a text with + "the related warning. You can force the type and the framework will correctly format the number as a number + WHEN 'FLDATE'. + <fs_field_catalog>-position = 2. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'PRICE'. + <fs_field_catalog>-position = 1. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-totals_function = zcl_excel_table=>totals_function_sum. + <fs_field_catalog>-cond_style = lo_style_conditional2. + WHEN OTHERS. + <fs_field_catalog>-dynpfld = abap_false. + ENDCASE. + ENDLOOP. + + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium5. + + lo_worksheet->bind_table( ip_table = lt_test + is_table_settings = ls_table_settings + it_field_catalog = lt_field_catalog ). + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'D' ). "make date field a bit wider + column_dimension->set_width( ip_width = 13 ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL11 +*& Export Organisation and Contact Persons using ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel11. + +TYPE-POOLS: abap. + +DATA: central_search TYPE bapibus1006_central_search, + addressdata_search TYPE bapibus1006_addr_search, + others_search TYPE bapibus1006_other_data. +DATA: searchresult TYPE TABLE OF bapibus1006_bp_addr, + return TYPE TABLE OF bapiret2. +DATA: lines TYPE i. +FIELD-SYMBOLS: <searchresult_line> LIKE LINE OF searchresult. +DATA: centraldata TYPE bapibus1006_central, + centraldataperson TYPE bapibus1006_central_person, + centraldataorganization TYPE bapibus1006_central_organ. +DATA: addressdata TYPE bapibus1006_address. +DATA: relationships TYPE TABLE OF bapibus1006_relations. +FIELD-SYMBOLS: <relationship> LIKE LINE OF relationships. +DATA: relationship_centraldata TYPE bapibus1006002_central. +DATA: relationship_addresses TYPE TABLE OF bapibus1006002_addresses. +FIELD-SYMBOLS: <relationship_address> LIKE LINE OF relationship_addresses. + +DATA: lt_download TYPE TABLE OF zexcel_s_org_rel. +FIELD-SYMBOLS: <download> LIKE LINE OF lt_download. + +CONSTANTS: gc_save_file_name TYPE string VALUE '11_Export_Org_and_Contact.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +PARAMETERS: md TYPE flag RADIOBUTTON GROUP act. + +SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME TITLE text-00a. +PARAMETERS: partnerc TYPE bu_type DEFAULT 2, " Organizations + postlcod TYPE ad_pstcd1 DEFAULT '8334*', + country TYPE land1 DEFAULT 'DE', + maxsel TYPE bu_maxsel DEFAULT 100. +SELECTION-SCREEN END OF BLOCK a. + +PARAMETERS: rel TYPE flag RADIOBUTTON GROUP act DEFAULT 'X'. + +SELECTION-SCREEN BEGIN OF BLOCK b WITH FRAME TITLE text-00b. +PARAMETERS: reltyp TYPE bu_reltyp DEFAULT 'BUR011', + partner TYPE bu_partner DEFAULT '191'. +SELECTION-SCREEN END OF BLOCK b. + +START-OF-SELECTION. + IF md = abap_true. + " Read all Companies by Master Data + central_search-partnercategory = partnerc. + addressdata_search-postl_cod1 = postlcod. + addressdata_search-country = country. + others_search-maxsel = maxsel. + others_search-no_search_for_contactperson = 'X'. + + CALL FUNCTION 'BAPI_BUPA_SEARCH_2' + EXPORTING + centraldata = central_search + addressdata = addressdata_search + OTHERS = others_search + TABLES + searchresult = searchresult + return = return. + + SORT searchresult BY partner. + DELETE ADJACENT DUPLICATES FROM searchresult COMPARING partner. + ELSEIF rel = abap_true. + " Read by Relationship + SELECT but050~partner1 AS partner FROM but050 + INNER JOIN but000 ON but000~partner = but050~partner1 AND but000~type = '2' + INTO CORRESPONDING FIELDS OF TABLE searchresult + WHERE but050~partner2 = partner + AND but050~reltyp = reltyp. + ENDIF. + + DESCRIBE TABLE searchresult LINES lines. + WRITE: / 'Number of search results: ', lines. + + LOOP AT searchresult ASSIGNING <searchresult_line>. + " Read Details of Organization + CALL FUNCTION 'BAPI_BUPA_CENTRAL_GETDETAIL' + EXPORTING + businesspartner = <searchresult_line>-partner + IMPORTING + centraldataorganization = centraldataorganization. + " Read Standard Address of Organization + CALL FUNCTION 'BAPI_BUPA_ADDRESS_GETDETAIL' + EXPORTING + businesspartner = <searchresult_line>-partner + IMPORTING + addressdata = addressdata. + + " Add Organization to Download + APPEND INITIAL LINE TO lt_download ASSIGNING <download>. + " Fill Organization Partner Numbers + CALL FUNCTION 'BAPI_BUPA_GET_NUMBERS' + EXPORTING + businesspartner = <searchresult_line>-partner + IMPORTING + businesspartnerout = <download>-org_number + businesspartnerguidout = <download>-org_guid. + + MOVE-CORRESPONDING centraldataorganization TO <download>. + MOVE-CORRESPONDING addressdata TO <download>. + CLEAR: addressdata. + + " Read all Relationships + CLEAR: relationships. + CALL FUNCTION 'BAPI_BUPA_RELATIONSHIPS_GET' + EXPORTING + businesspartner = <searchresult_line>-partner + TABLES + relationships = relationships. + DELETE relationships WHERE relationshipcategory <> 'BUR001'. + LOOP AT relationships ASSIGNING <relationship>. + " Read details of Contact person + CALL FUNCTION 'BAPI_BUPA_CENTRAL_GETDETAIL' + EXPORTING + businesspartner = <relationship>-partner2 + IMPORTING + centraldata = centraldata + centraldataperson = centraldataperson. + " Read details of the Relationship + CALL FUNCTION 'BAPI_BUPR_CONTP_GETDETAIL' + EXPORTING + businesspartner = <relationship>-partner1 + contactperson = <relationship>-partner2 + IMPORTING + centraldata = relationship_centraldata. + " Read relationship address + CLEAR: relationship_addresses. + + CALL FUNCTION 'BAPI_BUPR_CONTP_ADDRESSES_GET' + EXPORTING + businesspartner = <relationship>-partner1 + contactperson = <relationship>-partner2 + TABLES + addresses = relationship_addresses. + + READ TABLE relationship_addresses + ASSIGNING <relationship_address> + WITH KEY standardaddress = 'X'. + + IF <relationship_address> IS ASSIGNED. + " Read Relationship Address + CLEAR addressdata. + CALL FUNCTION 'BAPI_BUPA_ADDRESS_GETDETAIL' + EXPORTING + businesspartner = <searchresult_line>-partner + addressguid = <relationship_address>-addressguid + IMPORTING + addressdata = addressdata. + + APPEND INITIAL LINE TO lt_download ASSIGNING <download>. + CALL FUNCTION 'BAPI_BUPA_GET_NUMBERS' + EXPORTING + businesspartner = <relationship>-partner1 + IMPORTING + businesspartnerout = <download>-org_number + businesspartnerguidout = <download>-org_guid. + + CALL FUNCTION 'BAPI_BUPA_GET_NUMBERS' + EXPORTING + businesspartner = <relationship>-partner2 + IMPORTING + businesspartnerout = <download>-contpers_number + businesspartnerguidout = <download>-contpers_guid. + + MOVE-CORRESPONDING centraldataorganization TO <download>. + MOVE-CORRESPONDING addressdata TO <download>. + MOVE-CORRESPONDING centraldataperson TO <download>. + MOVE-CORRESPONDING relationship_centraldata TO <download>. + + WRITE: / <relationship>-partner1, <relationship>-partner2. + WRITE: centraldataorganization-name1(20), centraldataorganization-name2(10). + WRITE: centraldataperson-firstname(15), centraldataperson-lastname(15). + WRITE: addressdata-street(25), addressdata-house_no, + addressdata-postl_cod1, addressdata-city(25). + ENDIF. + ENDLOOP. + + ENDLOOP. + + DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_body TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + + DATA: lv_style_body_even_guid TYPE zexcel_cell_style, + lv_style_body_green TYPE zexcel_cell_style. + + DATA: row TYPE zexcel_cell_row. + + DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + + DATA: lt_field_catalog TYPE zexcel_t_fieldcatalog, + ls_table_settings TYPE zexcel_s_table_settings. + + DATA: column TYPE zexcel_cell_column, + column_alpha TYPE zexcel_cell_column_alpha, + value TYPE zexcel_cell_value. + + FIELD-SYMBOLS: <fs_field_catalog> TYPE zexcel_s_fieldcatalog. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + "Create style with border even + lo_style_body = lo_excel->add_new_style( ). + lo_style_body->fill->fgcolor-rgb = zcl_excel_style_color=>c_yellow. + lo_style_body->borders->allborders = lo_border_dark. + lv_style_body_even_guid = lo_style_body->get_guid( ). + "Create style with border and green fill + lo_style_body = lo_excel->add_new_style( ). + lo_style_body->fill->fgcolor-rgb = zcl_excel_style_color=>c_green. + lo_style_body->borders->allborders = lo_border_dark. + lv_style_body_green = lo_style_body->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Internal table' ). + + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_download ). + + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog>. + CASE <fs_field_catalog>-fieldname. + WHEN 'ORG_NUMBER'. + <fs_field_catalog>-position = 1. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'CONTPERS_NUMBER'. + <fs_field_catalog>-position = 2. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'NAME1'. + <fs_field_catalog>-position = 3. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'NAME2'. + <fs_field_catalog>-position = 4. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'STREET'. + <fs_field_catalog>-position = 5. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'HOUSE_NO'. + <fs_field_catalog>-position = 6. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'POSTL_COD1'. + <fs_field_catalog>-position = 7. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'CITY'. + <fs_field_catalog>-position = 8. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'COUNTRYISO'. + <fs_field_catalog>-position = 9. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FIRSTNAME'. + <fs_field_catalog>-position = 10. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'LASTNAME'. + <fs_field_catalog>-position = 11. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FUNCTIONNAME'. + <fs_field_catalog>-position = 12. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'DEPARTMENTNAME'. + <fs_field_catalog>-position = 13. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'TEL1_NUMBR'. + <fs_field_catalog>-position = 14. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'TEL1_EXT'. + <fs_field_catalog>-position = 15. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FAX_NUMBER'. + <fs_field_catalog>-position = 16. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'FAX_EXTENS'. + <fs_field_catalog>-position = 17. + <fs_field_catalog>-dynpfld = abap_true. + WHEN 'E_MAIL'. + <fs_field_catalog>-position = 18. + <fs_field_catalog>-dynpfld = abap_true. + WHEN OTHERS. + <fs_field_catalog>-dynpfld = abap_false. + ENDCASE. + ENDLOOP. + + ls_table_settings-top_left_column = 'A'. + ls_table_settings-top_left_row = '2'. + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium5. + + lo_worksheet->bind_table( ip_table = lt_download + is_table_settings = ls_table_settings + it_field_catalog = lt_field_catalog ). + LOOP AT lt_download ASSIGNING <download>. + row = sy-tabix + 2. + IF NOT <download>-org_number IS INITIAL + AND <download>-contpers_number IS INITIAL. + " Mark fields of Organization which can be changed green + lo_worksheet->set_cell_style( + ip_column = 'C' + ip_row = row + ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'D' + ip_row = row + ip_style = lv_style_body_green + ). +* CATCH zcx_excel. " Exceptions for ABAP2XLSX + ELSEIF NOT <download>-org_number IS INITIAL + AND NOT <download>-contpers_number IS INITIAL. + " Mark fields of Relationship which can be changed green + lo_worksheet->set_cell_style( + ip_column = 'L' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'M' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'N' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'O' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'P' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'Q' ip_row = row ip_style = lv_style_body_green + ). + lo_worksheet->set_cell_style( + ip_column = 'R' ip_row = row ip_style = lv_style_body_green + ). + ENDIF. + ENDLOOP. + " Add Fieldnames in first row and hide the row + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog> + WHERE position <> '' AND dynpfld = abap_true. + column = <fs_field_catalog>-position. + column_alpha = zcl_excel_common=>convert_column2alpha( column ). + value = <fs_field_catalog>-fieldname. + lo_worksheet->set_cell( ip_column = column_alpha + ip_row = 1 + ip_value = value + ip_style = lv_style_body_even_guid ). + ENDLOOP. + " Hide first row + row_dimension = lo_worksheet->get_row_dimension( 1 ). + row_dimension->set_visible( abap_false ). + + DATA: highest_column TYPE zexcel_cell_column, + count TYPE int4, + col_alpha TYPE zexcel_cell_column_alpha. + + highest_column = lo_worksheet->get_highest_column( ). + count = 1. + WHILE count <= highest_column. + col_alpha = zcl_excel_common=>convert_column2alpha( ip_column = count ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = col_alpha ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + count = count + 1. + ENDWHILE. +* " Set Column width manuall +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). +* column_dimension->set_width( ip_width = 11 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). +* column_dimension->set_width( ip_width = 11 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). +* column_dimension->set_width( ip_width = 35 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'E' ). +* column_dimension->set_width( ip_width = 18 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'F' ). +* column_dimension->set_width( ip_width = 5 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'G' ). +* column_dimension->set_width( ip_width = 6 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'H' ). +* column_dimension->set_width( ip_width = 12 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'I' ). +* column_dimension->set_width( ip_width = 3 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'J' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'K' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'L' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'M' ). +* column_dimension->set_width( ip_width = 13 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'N' ). +* column_dimension->set_width( ip_width = 12 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'O' ). +* column_dimension->set_width( ip_width = 9 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'P' ). +* column_dimension->set_width( ip_width = 12 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'Q' ). +* column_dimension->set_width( ip_width = 9 ). +* column_dimension = lo_worksheet->get_column_dimension( ip_column = 'R' ). +* column_dimension->set_width( ip_width = 40 ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL12 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel12. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: gc_save_file_name TYPE string VALUE '12_HideSizeOutlineRowsAndColumns.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world in AutoSize column' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Hello world in a column width size 50' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 4 ip_value = 'Hello world (hidden column)' ). + lo_worksheet->set_cell( ip_column = 'F' ip_row = 2 ip_value = 'Outline column level 0' ). + lo_worksheet->set_cell( ip_column = 'G' ip_row = 2 ip_value = 'Outline column level 1' ). + lo_worksheet->set_cell( ip_column = 'H' ip_row = 2 ip_value = 'Outline column level 2' ). + lo_worksheet->set_cell( ip_column = 'I' ip_row = 2 ip_value = 'Small' ). + + + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Hello world (hidden row)' ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = 5 ip_value = 'Hello world in a row height size 20' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 9 ip_value = 'Simple outline rows 10-16 ( collapsed )' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 19 ip_value = '3 Outlines - Outlinelevel 1 is collapsed' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 19 ip_value = 'One of the two inner outlines is expanded, one collapsed' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 20 ip_value = 'Inner outline level - expanded' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 24 ip_value = 'Inner outline level - lines 25-28 are collapsed' ). + + lo_worksheet->zif_excel_sheet_properties~summarybelow = zif_excel_sheet_properties=>c_below_off. " By default is on + lo_worksheet->zif_excel_sheet_properties~summaryright = zif_excel_sheet_properties=>c_right_off. " By default is on + + " Column Settings + " Auto size + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'I' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + " Manual Width + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + column_dimension->set_width( ip_width = 50 ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'D' ). + column_dimension->set_visible( ip_visible = abap_false ). + " Implementation in the Writer is not working yet ===== TODO ===== + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'F' ). + column_dimension->set_outline_level( ip_outline_level = 0 ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'G' ). + column_dimension->set_outline_level( ip_outline_level = 1 ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'H' ). + column_dimension->set_outline_level( ip_outline_level = 2 ). + + row_dimension = lo_worksheet->get_row_dimension( ip_row = 1 ). + row_dimension->set_visible( ip_visible = abap_false ). + row_dimension = lo_worksheet->get_row_dimension( ip_row = 5 ). + row_dimension->set_row_height( ip_row_height = 20 ). +* obsolete, not intuitive. Use new method shown below +* " Implementation in the Writer is not working yet ===== TODO ===== +* row_dimension = lo_worksheet->get_row_dimension( ip_row = 6 ). +* row_dimension->set_outline_level( ip_outline_level = 0 ). +* row_dimension = lo_worksheet->get_row_dimension( ip_row = 7 ). +* row_dimension->set_outline_level( ip_outline_level = 1 ). +* row_dimension = lo_worksheet->get_row_dimension( ip_row = 8 ). +* row_dimension->set_outline_level( ip_outline_level = 2 ). + +* Define an outline rows 10-16, collapsed on startup + lo_worksheet->set_row_outline( iv_row_from = 10 + iv_row_to = 16 + iv_collapsed = abap_true ). " collapsed + +* Define an inner outline rows 21-22, expanded when outer outline becomes extended + lo_worksheet->set_row_outline( iv_row_from = 21 + iv_row_to = 22 + iv_collapsed = abap_false ). " expanded + +* Define an inner outline rows 25-28, collapsed on startup + lo_worksheet->set_row_outline( iv_row_from = 25 + iv_row_to = 28 + iv_collapsed = abap_true ). " collapsed + +* Define an outer outline rows 20-30, collapsed on startup + lo_worksheet->set_row_outline( iv_row_from = 20 + iv_row_to = 30 + iv_collapsed = abap_true ). " collapsed + +* Hint: the order you create the outlines can be arbitrary +* You can start with inner outlines or with outer outlines + +*--------------------------------------------------------------------* +* Hide columns right of column M +*--------------------------------------------------------------------* + lo_worksheet->zif_excel_sheet_properties~hide_columns_from = 'M'. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL13 +*& +*&---------------------------------------------------------------------* +*& Example by: Alvaro "Blag" Tejada Galindo. +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel13. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_style_bold_border_guid TYPE zexcel_cell_style, + lo_style_bold_border TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '13_MergedCells.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'sheet1' ). + + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + + lo_style_bold_border = lo_excel->add_new_style( ). + lo_style_bold_border->font->bold = abap_true. + lo_style_bold_border->font->italic = abap_false. + lo_style_bold_border->font->color-rgb = zcl_excel_style_color=>c_black. + lo_style_bold_border->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_bold_border->borders->allborders = lo_border_dark. + lv_style_bold_border_guid = lo_style_bold_border->get_guid( ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = 'Test' ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'B' ip_value = 'Banana' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'C' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'D' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'E' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'F' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'G' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'Apple' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'F' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'G' ip_value = '' ip_style = lv_style_bold_border_guid ). + + lo_worksheet->set_merge( ip_row = 4 ip_column_start = 'B' ip_column_end = 'G' ). + + " Test also if merge works when oher merged chells are empty + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 'Tomato' ). + lo_worksheet->set_merge( ip_row = 6 ip_column_start = 'B' ip_column_end = 'G' ). + + " Test the patch provided by Victor Alekhin to merge cells in one column + lo_worksheet->set_cell( ip_row = 8 ip_column = 'B' ip_value = 'Merge cells also over multiple rows by Victor Alekhin' ). + lo_worksheet->set_merge( ip_row = 8 ip_column_start = 'B' ip_column_end = 'G' ip_row_to = 10 ). + + " Test the patch provided by Alexander Budeyev with different column merges + lo_worksheet->set_cell( ip_row = 12 ip_column = 'B' ip_value = 'Merge cells with different merges by Alexander Budeyev' ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'B' ip_value = 'Test' ). + + lo_worksheet->set_cell( ip_row = 13 ip_column = 'D' ip_value = 'Banana' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'D' ip_value = '' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'E' ip_value = 'Apple' ip_style = lv_style_bold_border_guid ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'F' ip_value = '' ip_style = lv_style_bold_border_guid ). + + " Test merge (issue) + lo_worksheet->set_merge( ip_row = 13 ip_column_start = 'B' ip_column_end = 'C' ip_row_to = 15 ). + lo_worksheet->set_merge( ip_row = 13 ip_column_start = 'D' ip_column_end = 'D' ip_row_to = 14 ). + lo_worksheet->set_merge( ip_row = 13 ip_column_start = 'E' ip_column_end = 'F' ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL14 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel14. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_center TYPE REF TO zcl_excel_style, + lo_style_right TYPE REF TO zcl_excel_style, + lo_style_left TYPE REF TO zcl_excel_style, + lo_style_general TYPE REF TO zcl_excel_style, + lo_style_bottom TYPE REF TO zcl_excel_style, + lo_style_middle TYPE REF TO zcl_excel_style, + lo_style_top TYPE REF TO zcl_excel_style, + lo_style_justify TYPE REF TO zcl_excel_style, + lo_style_mixed TYPE REF TO zcl_excel_style, + lo_style_mixed_wrap TYPE REF TO zcl_excel_style, + lo_style_rotated TYPE REF TO zcl_excel_style, + lo_style_shrink TYPE REF TO zcl_excel_style, + lo_style_indent TYPE REF TO zcl_excel_style, + lv_style_center_guid TYPE zexcel_cell_style, + lv_style_right_guid TYPE zexcel_cell_style, + lv_style_left_guid TYPE zexcel_cell_style, + lv_style_general_guid TYPE zexcel_cell_style, + lv_style_bottom_guid TYPE zexcel_cell_style, + lv_style_middle_guid TYPE zexcel_cell_style, + lv_style_top_guid TYPE zexcel_cell_style, + lv_style_justify_guid TYPE zexcel_cell_style, + lv_style_mixed_guid TYPE zexcel_cell_style, + lv_style_mixed_wrap_guid TYPE zexcel_cell_style, + lv_style_rotated_guid TYPE zexcel_cell_style, + lv_style_shrink_guid TYPE zexcel_cell_style, + lv_style_indent_guid TYPE zexcel_cell_style. + +DATA: lo_row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi. + +CONSTANTS: gc_save_file_name TYPE string VALUE '14_Alignment.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'sheet1' ). + + "Center + lo_style_center = lo_excel->add_new_style( ). + lo_style_center->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lv_style_center_guid = lo_style_center->get_guid( ). + "Right + lo_style_right = lo_excel->add_new_style( ). + lo_style_right->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_right. + lv_style_right_guid = lo_style_right->get_guid( ). + "Left + lo_style_left = lo_excel->add_new_style( ). + lo_style_left->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_left. + lv_style_left_guid = lo_style_left->get_guid( ). + "General + lo_style_general = lo_excel->add_new_style( ). + lo_style_general->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_general. + lv_style_general_guid = lo_style_general->get_guid( ). + "Bottom + lo_style_bottom = lo_excel->add_new_style( ). + lo_style_bottom->alignment->vertical = zcl_excel_style_alignment=>c_vertical_bottom. + lv_style_bottom_guid = lo_style_bottom->get_guid( ). + "Middle + lo_style_middle = lo_excel->add_new_style( ). + lo_style_middle->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lv_style_middle_guid = lo_style_middle->get_guid( ). + "Top + lo_style_top = lo_excel->add_new_style( ). + lo_style_top->alignment->vertical = zcl_excel_style_alignment=>c_vertical_top. + lv_style_top_guid = lo_style_top->get_guid( ). + "Justify + lo_style_justify = lo_excel->add_new_style( ). + lo_style_justify->alignment->vertical = zcl_excel_style_alignment=>c_vertical_justify. + lv_style_justify_guid = lo_style_justify->get_guid( ). + + "Shrink + lo_style_shrink = lo_excel->add_new_style( ). + lo_style_shrink->alignment->shrinktofit = abap_true. + lv_style_shrink_guid = lo_style_shrink->get_guid( ). + + "Indent + lo_style_indent = lo_excel->add_new_style( ). + lo_style_indent->alignment->indent = 5. + lv_style_indent_guid = lo_style_indent->get_guid( ). + + "Middle / Centered / Wrap + lo_style_mixed_wrap = lo_excel->add_new_style( ). + lo_style_mixed_wrap->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_mixed_wrap->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lo_style_mixed_wrap->alignment->wraptext = abap_true. + lv_style_mixed_wrap_guid = lo_style_mixed_wrap->get_guid( ). + + "Middle / Centered / Wrap + lo_style_mixed = lo_excel->add_new_style( ). + lo_style_mixed->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_mixed->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lv_style_mixed_guid = lo_style_mixed->get_guid( ). + + "Center + lo_style_rotated = lo_excel->add_new_style( ). + lo_style_rotated->alignment->horizontal = zcl_excel_style_alignment=>c_horizontal_center. + lo_style_rotated->alignment->vertical = zcl_excel_style_alignment=>c_vertical_center. + lo_style_rotated->alignment->textrotation = 165. " -75° == 90° + 75° + lv_style_rotated_guid = lo_style_rotated->get_guid( ). + + + " Set row size for first 7 rows to 40 + DO 7 TIMES. + lo_row_dimension = lo_worksheet->get_row_dimension( sy-index ). + lo_row_dimension->set_row_height( 40 ). + ENDDO. + + "Horizontal alignment + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'Centered Text' ip_style = lv_style_center_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'B' ip_value = 'Right Text' ip_style = lv_style_right_guid ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 'Left Text' ip_style = lv_style_left_guid ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'B' ip_value = 'General Text' ip_style = lv_style_general_guid ). + + " Shrink & indent + lo_worksheet->set_cell( ip_row = 4 ip_column = 'F' ip_value = 'Text shrinked' ip_style = lv_style_shrink_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'F' ip_value = 'Text indented' ip_style = lv_style_indent_guid ). + + "Vertical alignment + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'Bottom Text' ip_style = lv_style_bottom_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 'Middle Text' ip_style = lv_style_middle_guid ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'D' ip_value = 'Top Text' ip_style = lv_style_top_guid ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'D' ip_value = 'Justify Text' ip_style = lv_style_justify_guid ). + + " Wrapped + lo_worksheet->set_cell( ip_row = 10 ip_column = 'B' + ip_value = 'This is a wrapped text centered in the middle' + ip_style = lv_style_mixed_wrap_guid ). + + " Rotated + lo_worksheet->set_cell( ip_row = 10 ip_column = 'D' + ip_value = 'This is a centered text rotated by -75°' + ip_style = lv_style_rotated_guid ). + + " forced line break + DATA: lv_value TYPE string. + CONCATENATE 'This is a wrapped text centered in the middle' cl_abap_char_utilities=>cr_lf + 'and a manuall line break.' INTO lv_value. + lo_worksheet->set_cell( ip_row = 11 ip_column = 'B' + ip_value = lv_value + ip_style = lv_style_mixed_guid ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL15 +*& +*&---------------------------------------------------------------------* +*& 2010-10-30, Gregor Wolf: +*& Added the functionality to ouput the read table content +*& 2011-12-19, Shahrin Shahrulzaman: +*& Added the functionality to have multiple input and output files +*&---------------------------------------------------------------------* + +REPORT zdemo_excel15. + +TYPE-POOLS: abap. + +TYPES: + BEGIN OF t_demo_excel15, + input TYPE string, + END OF t_demo_excel15. + +DATA: excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + reader TYPE REF TO zif_excel_reader. + +DATA: ex TYPE REF TO zcx_excel, + msg TYPE string. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_workdir TYPE string, + output_file_path TYPE string, + input_file_path TYPE string, + lv_file_separator TYPE c. + +DATA: worksheet TYPE REF TO zcl_excel_worksheet, + highest_column TYPE zexcel_cell_column, + highest_row TYPE int4, + column TYPE zexcel_cell_column VALUE 1, + col_str TYPE zexcel_cell_column_alpha, + row TYPE int4 VALUE 1, + value TYPE zexcel_cell_value. + +DATA: + lt_files TYPE TABLE OF t_demo_excel15. +FIELD-SYMBOLS: <wa_files> TYPE t_demo_excel15. + +PARAMETERS: p_path TYPE zexcel_export_dir, + p_noout TYPE xfeld DEFAULT abap_true. + + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '01_HelloWorld.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '02_Styles.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '03_iTab.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '04_Sheets.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '08_Range.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '13_MergedCells.xlsx'. + APPEND INITIAL LINE TO lt_files ASSIGNING <wa_files>. + <wa_files>-input = '31_AutosizeWithDifferentFontSizes.xlsx'. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + + LOOP AT lt_files ASSIGNING <wa_files>. + CONCATENATE p_path lv_file_separator <wa_files>-input INTO input_file_path. + CONCATENATE p_path lv_file_separator '15_' <wa_files>-input INTO output_file_path. + REPLACE '.xlsx' IN output_file_path WITH 'FromReader.xlsx'. + + TRY. + CREATE OBJECT reader TYPE zcl_excel_reader_2007. + excel = reader->load_file( input_file_path ). + + IF p_noout EQ abap_false. + worksheet = excel->get_active_worksheet( ). + highest_column = worksheet->get_highest_column( ). + highest_row = worksheet->get_highest_row( ). + + WRITE: 'Highest column: ', highest_column, 'Highest row: ', highest_row. + WRITE: /. + + WHILE row <= highest_row. + WHILE column <= highest_column. + col_str = zcl_excel_common=>convert_column2alpha( column ). + worksheet->get_cell( + EXPORTING + ip_column = col_str + ip_row = row + IMPORTING + ep_value = value + ). + WRITE: value. + column = column + 1. + ENDWHILE. + WRITE: /. + column = 1. + row = row + 1. + ENDWHILE. + ENDIF. + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = output_file_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + CATCH zcx_excel INTO ex. " Exceptions for ABAP2XLSX + msg = ex->get_text( ). + WRITE: / msg. + ENDTRY. + ENDLOOP. + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL16 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel16. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_drawing TYPE REF TO zcl_excel_drawing. + + +DATA: ls_io TYPE skwf_io. + +CONSTANTS: gc_save_file_name TYPE string VALUE '16_Drawings.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_objid TYPE sdok_docid DEFAULT '456694429165174BE10000000A1550C0', " Question mark in standard Web Dynpro WDT_QUIZ + p_class TYPE sdok_class DEFAULT 'M_IMAGE_P', + pobjtype TYPE skwf_ioty DEFAULT 'P'. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + "Load samle image + DATA: lt_bin TYPE solix_tab, + lv_len TYPE i, + lv_content TYPE xstring, + ls_key TYPE wwwdatatab. + + CALL METHOD cl_gui_frontend_services=>gui_upload + EXPORTING + filename = 'c:\Program Files\SAP\FrontEnd\SAPgui\wwi\graphics\W_bio.bmp' + filetype = 'BIN' + IMPORTING + filelength = lv_len + CHANGING + data_tab = lt_bin + 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. +* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno +* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + CALL FUNCTION 'SCMS_BINARY_TO_XSTRING' + EXPORTING + input_length = lv_len + IMPORTING + buffer = lv_content + TABLES + binary_tab = lt_bin + EXCEPTIONS + failed = 1 + OTHERS = 2. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Image from web repository (SMW0)' ). + + " create global drawing, set position and media from web repository + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 3 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'SAPLOGO.GIF'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 166 + ip_height = 75 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " another drawing from a XSTRING read from a file + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Image from a file (c:\Program Files\SAP\FrontEnd\SAPgui\wwi\graphics\W_bio.bmp)' ). + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 9 + ip_from_col = 'B' ). + lo_drawing->set_media( ip_media = lv_content + ip_media_type = zcl_excel_drawing=>c_media_type_bmp + ip_width = 83 + ip_height = 160 ). + + lo_worksheet->add_drawing( lo_drawing ). + + ls_io-objid = p_objid. + ls_io-class = p_class. + ls_io-objtype = pobjtype. + IF ls_io IS NOT INITIAL. + " another drawing from a XSTRING read from a file + lo_worksheet->set_cell( ip_column = 'B' ip_row = 18 ip_value = 'Mime repository (by default Question mark in standard Web Dynpro WDT_QUIZ)' ). + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 19 + ip_from_col = 'B' ). + lo_drawing->set_media_mime( ip_io = ls_io + ip_width = 126 + ip_height = 145 ). + + lo_worksheet->add_drawing( lo_drawing ). + ENDIF. + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL26 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel29. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_excel_reader TYPE REF TO zif_excel_reader. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_filename TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +PARAMETERS: p_path TYPE zexcel_export_dir OBLIGATORY. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + + DATA: lt_filetable TYPE filetable, + lv_rc TYPE i. + + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + + CALL METHOD cl_gui_frontend_services=>file_open_dialog + EXPORTING + window_title = 'Select Macro-Enabled Workbook template' + default_extension = '*.xlsm' + file_filter = 'Excel Macro-Enabled Workbook (*.xlsm)|*.xlsm' + initial_directory = lv_workdir + CHANGING + file_table = lt_filetable + rc = lv_rc + EXCEPTIONS + file_open_dialog_failed = 1 + cntl_error = 2 + error_no_gui = 3 + not_supported_by_gui = 4 + OTHERS = 5. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + READ TABLE lt_filetable INTO lv_filename INDEX 1. + p_path = lv_filename. + +START-OF-SELECTION. + + lv_full_path = p_path. + + CREATE OBJECT lo_excel_reader TYPE zcl_excel_reader_xlsm. + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_xlsm. + lo_excel = lo_excel_reader->load_file( lv_full_path ). + lv_file = lo_excel_writer->write_file( lo_excel ). + REPLACE '.xlsm' IN lv_full_path WITH 'FromReader.xlsm'. + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL28 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel28. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_file_name TYPE string, + lv_file_path TYPE string, + lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE '28_HelloWorld.csv'. + +PARAMETERS: p_path TYPE string. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = p_path + CHANGING selected_folder = p_path ). + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = sy-datum ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = sy-uzeit ). + + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_width( 11 ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the second sheet' ). + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_csv. + zcl_excel_writer_csv=>set_delimiter( ip_value = cl_abap_char_utilities=>horizontal_tab ). + zcl_excel_writer_csv=>set_enclosure( ip_value = '''' ). + zcl_excel_writer_csv=>set_endofline( ip_value = cl_abap_char_utilities=>cr_lf ). + + zcl_excel_writer_csv=>set_active_sheet_index( i_active_worksheet = 2 ). +* zcl_excel_writer_csv=>set_active_sheet_index_by_name( I_WORKSHEET_NAME = 'Sheet2' ). + + lv_file = lo_excel_writer->write_file( lo_excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + REPLACE FIRST OCCURRENCE OF '.csv' IN lv_full_path WITH '_Sheet2.csv'. + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + +* zcl_excel_writer_csv=>set_active_sheet_index( i_active_worksheet = 2 ). + zcl_excel_writer_csv=>set_active_sheet_index_by_name( I_WORKSHEET_NAME = 'Sheet1' ). + lv_file = lo_excel_writer->write_file( lo_excel ). + REPLACE FIRST OCCURRENCE OF '_Sheet2.csv' IN lv_full_path WITH '_Sheet1.csv'. + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL27 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel27. + +CONSTANTS: c_fish TYPE string VALUE 'Fish'. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lo_style_1 TYPE REF TO zcl_excel_style, + lo_style_2 TYPE REF TO zcl_excel_style, + lv_style_1_guid TYPE zexcel_cell_style, + lv_style_2_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis. + + +DATA: lv_title TYPE zexcel_sheet_title. + +CONSTANTS: gc_save_file_name TYPE string VALUE '27_ConditionalFormatting.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + lo_style_1 = lo_excel->add_new_style( ). + lo_style_1->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_1->fill->bgcolor-rgb = zcl_excel_style_color=>c_green. + lv_style_1_guid = lo_style_1->get_guid( ). + + lo_style_2 = lo_excel->add_new_style( ). + lo_style_2->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_2->fill->bgcolor-rgb = zcl_excel_style_color=>c_red. + lv_style_2_guid = lo_style_2->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lv_title = 'Data Validation'. + lo_worksheet->set_title( lv_title ). + " Set values for dropdown + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = c_fish ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 'Anchovy' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 'Carp' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 'Catfish' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 'Cod' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 'Eel' ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'A' ip_value = 'Haddock' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_fish. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 9 ). + + " 1st validation + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_fish. + lo_data_validation->cell_row = 2. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 2 ip_column = 'C' ip_value = 'Select a value' ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '"Anchovy"'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_1_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 1. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 2 + ip_stop_column = 'C' + ip_stop_row = 2 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '"Carp"'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_2_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 2 + ip_stop_column = 'C' + ip_stop_row = 2 ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *--------------------------------------------------------------------* +* REPORT ZDEMO_EXCEL26 +* Demo for method zcl_excel_worksheet-bind_object: +* export data from ALV (CL_GUI_ALV_GRID) object or cl_salv_table object +* to Excel. +*--------------------------------------------------------------------* +report zdemo_excel26. + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +class lcl_handle_events definition. + public section. + methods: + on_user_command for event added_function of cl_salv_events + importing e_salv_function. +endclass. "lcl_handle_events DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +class lcl_handle_events implementation. + method on_user_command. + perform user_command." using e_salv_function text-i08. + endmethod. "on_user_command +endclass. "lcl_handle_events IMPLEMENTATION + +*--------------------------------------------------------------------* +* DATA DECLARATION +*--------------------------------------------------------------------* + +data: lo_excel type ref to zcl_excel, + lo_worksheet type ref to zcl_excel_worksheet, + lo_salv type ref to cl_salv_table, + gr_events type ref to lcl_handle_events, + lr_events type ref to cl_salv_events_table, + gt_sbook type table of sbook. + +data: l_path type string, " local dir + lv_workdir type string, + lv_file_separator type c. + +constants: + lv_default_file_name type string value '26_Bind_ALV.xlsx'. +*--------------------------------------------------------------------* +*START-OF-SELECTION +*--------------------------------------------------------------------* + +start-of-selection. + +* get data +* ------------------------------------------ + + select * + into table gt_sbook[] + from sbook "#EC CI_NOWHERE + up to 10 rows. + +* Display ALV +* ------------------------------------------ + + try. + cl_salv_table=>factory( + exporting + list_display = abap_false + importing + r_salv_table = lo_salv + changing + t_table = gt_sbook[] ). + catch cx_salv_msg . + endtry. + + try. + lo_salv->set_screen_status( + exporting + report = sy-repid + pfstatus = 'ALV_STATUS' + set_functions = lo_salv->c_functions_all ). + catch cx_salv_msg . + endtry. + + lr_events = lo_salv->get_event( ). + create object gr_events. + set handler gr_events->on_user_command for lr_events. + + lo_salv->display( ). + + +*&---------------------------------------------------------------------* +*& Form USER_COMMAND +*&---------------------------------------------------------------------* +* ALV user command +*--------------------------------------------------------------------* +form user_command . + if sy-ucomm = 'EXCEL'. + +* get save file path + cl_gui_frontend_services=>get_sapgui_workdir( changing sapworkdir = l_path ). + cl_gui_cfw=>flush( ). + cl_gui_frontend_services=>directory_browse( + exporting initial_folder = l_path + changing selected_folder = l_path ). + + if l_path is initial. + cl_gui_frontend_services=>get_sapgui_workdir( + changing sapworkdir = lv_workdir ). + l_path = lv_workdir. + endif. + + cl_gui_frontend_services=>get_file_separator( + changing file_separator = lv_file_separator ). + + concatenate l_path lv_file_separator lv_default_file_name + into l_path. + +* export file to save file path + perform export_to_excel. + + endif. +endform. " USER_COMMAND + +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +form export_to_excel. + data: lo_converter type ref to zcl_excel_converter. +* create zcl_excel_worksheet object + + create object lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + +* write to excel using method Bin_object + try. + lo_worksheet->bind_alv( + io_alv = lo_salv + it_table = gt_sbook + i_top = 2 + i_left = 1 + ). + catch zcx_excel . + endtry. + + perform write_file. + +endform. "EXPORT_TO_EXCEL +*&---------------------------------------------------------------------* +*& Form WRITE_FILE +*&---------------------------------------------------------------------* +* text +*----------------------------------------------------------------------* +* --> p1 text +* <-- p2 text +*----------------------------------------------------------------------* +form write_file . + data: lt_file type solix_tab, + l_bytecount type i, + l_file type xstring. + + data: lo_excel_writer type ref to zif_excel_writer. + + data: ls_seoclass type seoclass. + + create object lo_excel_writer type zcl_excel_writer_2007. + l_file = lo_excel_writer->write_file( lo_excel ). + + select single * into ls_seoclass + from seoclass + where clsname = 'CL_BCS_CONVERT'. + + if sy-subrc = 0. + call method (ls_seoclass-clsname)=>xstring_to_solix + exporting + iv_xstring = l_file + receiving + et_solix = lt_file. + + l_bytecount = xstrlen( l_file ). + else. + " Convert to binary + call function 'SCMS_XSTRING_TO_BINARY' + exporting + buffer = l_file + importing + output_length = l_bytecount + tables + binary_tab = lt_file. + endif. + + cl_gui_frontend_services=>gui_download( exporting bin_filesize = l_bytecount + filename = l_path + filetype = 'BIN' + changing data_tab = lt_file ). + +endform. " WRITE_FILE + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL25 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel25. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_exception TYPE REF TO cx_root. + +DATA: lv_file TYPE xstring. + +CONSTANTS: lv_file_name TYPE string VALUE '25_HelloWorld.xlsx'. +DATA: lv_default_file_name TYPE string. +DATA: lv_error TYPE string. + +CALL FUNCTION 'FILE_GET_NAME_USING_PATH' + EXPORTING + logical_path = 'LOCAL_TEMPORARY_FILES' " Logical path' + file_name = lv_file_name " File name + IMPORTING + file_name_with_path = lv_default_file_name. " File name with path +" Creates active sheet +CREATE OBJECT lo_excel. + +" Get active sheet +lo_worksheet = lo_excel->get_active_worksheet( ). +lo_worksheet->set_title( ip_title = 'Sheet1' ). +lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + +CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. +lv_file = lo_excel_writer->write_file( lo_excel ). + +TRY. + OPEN DATASET lv_default_file_name FOR OUTPUT IN BINARY MODE. + TRANSFER lv_file TO lv_default_file_name. + CLOSE DATASET lv_default_file_name. + CATCH cx_root INTO lo_exception. + lv_error = lo_exception->get_text( ). + MESSAGE lv_error TYPE 'I'. +ENDTRY. + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL23 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel24. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +DATA: lv_value TYPE string. + +CONSTANTS: gc_save_file_name TYPE string VALUE '24_Sheets_with_different_default_date_formats.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Default Date Format' ). + " Insert current date + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Current Date:' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 4 ip_value = sy-datum ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet2!A1' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 6 ip_value = 'This is a link to the second sheet' ip_hyperlink = lo_hyperlink ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + + " Second sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_default_excel_date_format( zcl_excel_style_number_format=>c_format_date_yyyymmdd ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Date Format set to YYYYMMDD' ). + " Insert current date + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Current Date:' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 4 ip_value = sy-datum ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet3!B2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 6 ip_value = 'This is link to the third sheet' ip_hyperlink = lo_hyperlink ). + + " Third sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + " TODO: It seems that the zcl_excel_style_number_format=>c_format_date_yyyymmddslash + " does not produce a valid output + lo_worksheet->set_default_excel_date_format( zcl_excel_style_number_format=>c_format_date_yyyymmddslash ). + lo_worksheet->set_title( ip_title = 'Sheet3' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Date Format set to YYYY/MM/DD' ). + " Insert current date + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Current Date:' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 4 ip_value = sy-datum ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet4!B2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 6 ip_value = 'This is link to the 4th sheet' ip_hyperlink = lo_hyperlink ). + + " 4th sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + " Illustrate the Problem caused by: + " Excel 2000 incorrectly assumes that the year 1900 is a leap year. + " http://support.microsoft.com/kb/214326/en-us + lo_worksheet->set_title( ip_title = 'Sheet4' ). + " Loop from Start Date to the Max Date current data in daily steps + CONSTANTS: lv_max type d VALUE '19000302'. + + DATA: lv_date TYPE d VALUE '19000226', + lv_row TYPE i. + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'Formated date' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Integer value for this date' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 3 ip_value = 'Date as string' ). + + lv_row = 4. + WHILE lv_date < lv_max. + lo_worksheet->set_cell( ip_column = 'B' ip_row = lv_row ip_value = lv_date ). + lv_value = zcl_excel_common=>date_to_excel_string( lv_date ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = lv_row ip_value = lv_value ). + lv_value = lv_date. + lo_worksheet->set_cell( ip_column = 'D' ip_row = lv_row ip_value = lv_value ). + lv_date = lv_date + 1. + lv_row = lv_row + 1. + ENDWHILE. + + lv_row = lv_row + 1. + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet1!B2' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = lv_row ip_value = 'This is link to the first sheet' ip_hyperlink = lo_hyperlink ). + + lo_excel->set_active_sheet_index_by_name( 'Sheet1' ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL23 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel23. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '23_Sheets_with_and_without_grid_lines.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the first sheet with grid lines and print centered horizontal & vertical' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_true ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet2!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is a link to the second sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 150. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_NORMAL = 150. + + lo_worksheet->sheet_setup->vertical_centered = abap_true. + lo_worksheet->sheet_setup->horizontal_centered = abap_true. + + " Second sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the second sheet with grid lines in display and print' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_true ). + lo_worksheet->set_print_gridlines( i_print_gridlines = abap_true ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet3!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to the third sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 160. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_PAGELAYOUTVIEW = 200. + + " Third sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet3' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the third sheet without grid lines in display and print' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_false ). + lo_worksheet->set_print_gridlines( i_print_gridlines = abap_false ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet4!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to the fourth sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 170. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_SHEETLAYOUTVIEW = 150. + + " Fourth sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet4' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the fourth sheet with grid lines and print centered ONLY horizontal' ). + lo_worksheet->set_show_gridlines( i_show_gridlines = abap_true ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet1!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to the first sheet' ip_hyperlink = lo_hyperlink ). + + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_properties~zoomscale = 150. + lo_worksheet->ZIF_EXCEL_SHEET_PROPERTIES~ZOOMSCALE_NORMAL = 150. + +" lo_worksheet->sheet_setup->vertical_centered = abap_true. + lo_worksheet->sheet_setup->horizontal_centered = abap_true. + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL17 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel17. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_protection TYPE REF TO zcl_excel_style, + lv_style_protection_guid TYPE zexcel_cell_style, + lo_style TYPE REF TO zcl_excel_style, + lv_style TYPE zexcel_cell_style. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '17_SheetProtection.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_pwd TYPE zexcel_aes_password LOWER CASE DEFAULT 'secret'. + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. +* lo_worksheet->zif_excel_sheet_protection~password = 'DAA7'. "it is the encoded word "secret" + lo_worksheet->zif_excel_sheet_protection~password = zcl_excel_common=>encrypt_password( p_pwd ). + lo_worksheet->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_active. + " First style to unlock a cell + lo_style_protection = lo_excel->add_new_style( ). + lo_style_protection->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. + lv_style_protection_guid = lo_style_protection->get_guid( ). + " Another style which should not affect the unlock style + lo_style = lo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = 'FFCC3333'. + lv_style = lo_style->get_guid( ). + lo_worksheet->set_cell( ip_row = 3 ip_column = 'C' ip_value = 'This cell is locked locked and has the second formating' ip_style = lv_style ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 'This cell is locked as all the others empty cell' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'This cell is locked as all the others empty cell' ). + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL18 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel18. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_style_protection_guid TYPE zexcel_cell_style. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '18_BookProtection.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_excel->zif_excel_book_protection~protected = zif_excel_book_protection=>c_protected. + lo_excel->zif_excel_book_protection~lockrevision = zif_excel_book_protection=>c_locked. + lo_excel->zif_excel_book_protection~lockstructure = zif_excel_book_protection=>c_locked. + lo_excel->zif_excel_book_protection~lockwindows = zif_excel_book_protection=>c_locked. + + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'This cell is unlocked' ip_style = lv_style_protection_guid ). + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL19 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel19. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '19_SetActiveSheet.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_noout TYPE xfeld DEFAULT abap_true. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " First Worksheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'First' ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'This is Sheet 1' ). + + " Second Worksheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Second' ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'This is Sheet 2' ). + + " Third Worksheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Third' ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'This is Sheet 3' ). + + IF p_noout EQ abap_false. + " lo_excel->set_active_sheet_index_by_name( data_sheet_name ). + DATA: active_sheet_index TYPE zexcel_active_worksheet. + active_sheet_index = lo_excel->get_active_sheet_index( ). + WRITE: 'Sheet Index before: ', active_sheet_index. + ENDIF. + lo_excel->set_active_sheet_index( '2' ). + IF p_noout EQ abap_false. + active_sheet_index = lo_excel->get_active_sheet_index( ). + WRITE: 'Sheet Index after: ', active_sheet_index. + ENDIF. + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL2 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel2. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_bold TYPE REF TO zcl_excel_style, + lo_style_underline TYPE REF TO zcl_excel_style, + lo_style_filled TYPE REF TO zcl_excel_style, + lo_style_border TYPE REF TO zcl_excel_style, + lo_style_button TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + lo_border_light TYPE REF TO zcl_excel_style_border. + +DATA: lv_style_bold_guid TYPE zexcel_cell_style, + lv_style_underline_guid TYPE zexcel_cell_style, + lv_style_filled_guid TYPE zexcel_cell_style, + lv_style_filled_green_guid TYPE zexcel_cell_style, + lv_style_border_guid TYPE zexcel_cell_style, + lv_style_button_guid TYPE zexcel_cell_style, + lv_style_filled_turquoise_guid TYPE zexcel_cell_style, + lv_style_gr_cornerlb_guid TYPE zexcel_cell_style, + lv_style_gr_cornerlt_guid TYPE zexcel_cell_style, + lv_style_gr_cornerrb_guid TYPE zexcel_cell_style, + lv_style_gr_cornerrt_guid TYPE zexcel_cell_style, + lv_style_gr_horizontal90_guid TYPE zexcel_cell_style, + lv_style_gr_horizontal270_guid TYPE zexcel_cell_style, + lv_style_gr_horizontalb_guid TYPE zexcel_cell_style, + lv_style_gr_vertical_guid TYPE zexcel_cell_style, + lv_style_gr_vertical2_guid TYPE zexcel_cell_style, + lv_style_gr_fromcenter_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal45_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal45b_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal135_guid TYPE zexcel_cell_style, + lv_style_gr_diagonal135b_guid TYPE zexcel_cell_style . + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. +DATA: lo_row_dim TYPE REF TO zcl_excel_worksheet_rowdimensi. + +CONSTANTS: gc_save_file_name TYPE string VALUE '02_Styles.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + CREATE OBJECT lo_border_light. + lo_border_light->border_color-rgb = zcl_excel_style_color=>c_gray. + lo_border_light->border_style = zcl_excel_style_border=>c_border_thin. + " Create a bold / italic style + lo_style_bold = lo_excel->add_new_style( ). + lo_style_bold->font->bold = abap_true. + lo_style_bold->font->italic = abap_true. + lo_style_bold->font->name = zcl_excel_style_font=>c_name_arial. + lo_style_bold->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_bold->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_bold_guid = lo_style_bold->get_guid( ). + " Create an underline double style + lo_style_underline = lo_excel->add_new_style( ). + lo_style_underline->font->underline = abap_true. + lo_style_underline->font->underline_mode = zcl_excel_style_font=>c_underline_double. + lo_style_underline->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_underline->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_underline->font->family = zcl_excel_style_font=>c_family_roman. + lv_style_underline_guid = lo_style_underline->get_guid( ). + " Create filled style yellow + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-theme = zcl_excel_style_color=>c_theme_accent6. + lv_style_filled_guid = lo_style_filled->get_guid( ). + " Create border with button effects + lo_style_button = lo_excel->add_new_style( ). + lo_style_button->borders->right = lo_border_dark. + lo_style_button->borders->down = lo_border_dark. + lo_style_button->borders->left = lo_border_light. + lo_style_button->borders->top = lo_border_light. + lv_style_button_guid = lo_style_button->get_guid( ). + "Create style with border + lo_style_border = lo_excel->add_new_style( ). + lo_style_border->borders->allborders = lo_border_dark. + lo_style_border->borders->diagonal = lo_border_dark. + lo_style_border->borders->diagonal_mode = zcl_excel_style_borders=>c_diagonal_both. + lv_style_border_guid = lo_style_border->get_guid( ). + " Create filled style green + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_green. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_filled_green_guid = lo_style_filled->get_guid( ). + + " Create filled with gradients + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerlb. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerlb_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerlt. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerlt_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerrb. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerrb_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_cornerrt. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_cornerrt_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_horizontal90. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_horizontal90_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_horizontal270. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_horizontal270_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_horizontalb. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_horizontalb_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_vertical. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_vertical_guid = lo_style_filled->get_guid( ). + + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_vertical. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_vertical2_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_fromcenter. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_fromcenter_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal45. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal45_guid = lo_style_filled->get_guid( ). + + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal45b. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal45b_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal135. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal135_guid = lo_style_filled->get_guid( ). + + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal135b. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_blue. + lo_style_filled->fill->bgcolor-rgb = zcl_excel_style_color=>c_white. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_gr_diagonal135b_guid = lo_style_filled->get_guid( ). + + + + " Create filled style turquoise using legacy excel ver <= 2003 palette. (https://code.sdn.sap.com/spaces/abap2xlsx/tickets/92) + lo_style_filled = lo_excel->add_new_style( ). + lo_excel->legacy_palette->set_color( "replace built-in color from palette with out custom RGB turquoise + ip_index = 16 + ip_color = '0040E0D0' ). + + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-indexed = 16. + lv_style_filled_turquoise_guid = lo_style_filled->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Styles' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Bold text' ip_style = lv_style_bold_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 4 ip_value = 'Underlined text' ip_style = lv_style_underline_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 6 ip_value = 'Borders' ip_style = lv_style_border_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 7 ip_value = 'I''m not a button :)' ip_style = lv_style_button_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 9 ip_value = 'Modified color for Excel 2003' ip_style = lv_style_filled_turquoise_guid ). + " Fill the cell and apply one style + lo_worksheet->set_cell( ip_column = 'B' ip_row = 6 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + " Change the style + lo_worksheet->set_cell_style( ip_column = 'B' ip_row = 6 ip_style = lv_style_filled_green_guid ). + " Add Style to an empty cell to test Fix for Issue + "#44 Exception ZCX_EXCEL thrown when style is set for an empty cell + " https://code.sdn.sap.com/spaces/abap2xlsx/tickets/44-exception-zcx_excel-thrown-when-style-is-set-for-an-empty-cell + lo_worksheet->set_cell_style( ip_column = 'E' ip_row = 6 ip_style = lv_style_filled_green_guid ). + + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_style = lv_style_gr_cornerlb_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerlb ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 10 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 11 ip_style = lv_style_gr_cornerlt_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerlt ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 11 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 12 ip_style = lv_style_gr_cornerrb_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerrb ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 12 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 13 ip_style = lv_style_gr_cornerrt_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_cornerrt ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 13 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 14 ip_style = lv_style_gr_horizontal90_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_horizontal90 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 14 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 15 ip_style = lv_style_gr_horizontal270_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_horizontal270 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 15 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 16 ip_style = lv_style_gr_horizontalb_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_horizontalb ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 16 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 17 ip_style = lv_style_gr_vertical_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_vertical ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 17 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 18 ip_style = lv_style_gr_vertical2_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_vertical ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 18 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 19 ip_style = lv_style_gr_fromcenter_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_fromcenter ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 19 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 20 ip_style = lv_style_gr_diagonal45_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal45 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 20 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 21 ip_style = lv_style_gr_diagonal45b_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal45b ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 21 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 22 ip_style = lv_style_gr_diagonal135_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal135 ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 22 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 23 ip_style = lv_style_gr_diagonal135b_guid ip_value = zcl_excel_style_fill=>c_fill_gradient_diagonal135b ). + lo_row_dim = lo_worksheet->get_row_dimension( ip_row = 23 ). + lo_row_dim->set_row_height( ip_row_height = 30 ). + + + +* CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. +* lv_file = lo_excel_writer->write_file( lo_excel ). +* +* " Convert to binary +* CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' +* EXPORTING +* buffer = lv_file +* IMPORTING +* output_length = lv_bytecount +* TABLES +* binary_tab = lt_file_tab. +** " This method is only available on AS ABAP > 6.40 +** lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +** lv_bytecount = xstrlen( lv_file ). +* +* " Save the file +* cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount +* filename = lv_full_path +* filetype = 'BIN' +* CHANGING data_tab = lt_file_tab ). + + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL22 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel22. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style TYPE REF TO zcl_excel_style, + lo_style_date TYPE REF TO zcl_excel_style, + lo_style_editable TYPE REF TO zcl_excel_style, + lo_data_validation TYPE REF TO zcl_excel_data_validation. + +DATA: lt_field_catalog TYPE zexcel_t_fieldcatalog, + ls_table_settings TYPE zexcel_s_table_settings, + ls_table_settings_out TYPE zexcel_s_table_settings. + +DATA: lv_style_guid TYPE zexcel_cell_style. + +DATA: lv_row TYPE char10. + +FIELD-SYMBOLS: <fs_field_catalog> TYPE zexcel_s_fieldcatalog. + +CONSTANTS: gc_save_file_name TYPE string VALUE '22_itab_fieldcatalog.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'PN_MASSIVE'). + + DATA lt_test TYPE TABLE OF sflight. + SELECT * FROM sflight INTO TABLE lt_test. "#EC CI_NOWHERE + + " sheet style (white background) + lo_style = lo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = zcl_excel_style_color=>c_white. + lv_style_guid = lo_style->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->zif_excel_sheet_properties~set_style( lv_style_guid ). + lo_worksheet->zif_excel_sheet_protection~protected = zif_excel_sheet_protection=>c_protected. + lo_worksheet->zif_excel_sheet_protection~password = zcl_excel_common=>encrypt_password( 'test' ). + lo_worksheet->zif_excel_sheet_protection~sheet = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~objects = zif_excel_sheet_protection=>c_active. + lo_worksheet->zif_excel_sheet_protection~scenarios = zif_excel_sheet_protection=>c_active. + + " Create cell style for display only fields + lo_style = lo_excel->add_new_style( ). + lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style->fill->fgcolor-rgb = zcl_excel_style_color=>c_gray. + lo_style->number_format->format_code = zcl_excel_style_number_format=>c_format_text. + + " Create cell style for display only date field + lo_style_date = lo_excel->add_new_style( ). + lo_style_date->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_date->fill->fgcolor-rgb = zcl_excel_style_color=>c_gray. + lo_style_date->number_format->format_code = zcl_excel_style_number_format=>c_format_date_ddmmyyyy. + + " Create cell style for editable fields + lo_style_editable = lo_excel->add_new_style( ). + lo_style_editable->protection->locked = zcl_excel_style_protection=>c_protection_unlocked. + + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = lt_test ). + + LOOP AT lt_field_catalog ASSIGNING <fs_field_catalog>. + CASE <fs_field_catalog>-fieldname. + WHEN 'CARRID'. + <fs_field_catalog>-position = 3. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style->get_guid( ). + WHEN 'CONNID'. + <fs_field_catalog>-position = 1. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style->get_guid( ). + WHEN 'FLDATE'. + <fs_field_catalog>-position = 2. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style_date->get_guid( ). + WHEN 'PRICE'. + <fs_field_catalog>-position = 4. + <fs_field_catalog>-dynpfld = abap_true. + <fs_field_catalog>-style = lo_style_editable->get_guid( ). + <fs_field_catalog>-totals_function = zcl_excel_table=>totals_function_sum. + WHEN OTHERS. + <fs_field_catalog>-dynpfld = abap_false. + ENDCASE. + ENDLOOP. + + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ls_table_settings-show_row_stripes = abap_true. + + lo_worksheet->bind_table( EXPORTING + ip_table = lt_test + it_field_catalog = lt_field_catalog + is_table_settings = ls_table_settings + IMPORTING + es_table_settings = ls_table_settings_out ). + + lo_worksheet->freeze_panes( ip_num_rows = 3 ). "freeze column headers when scrolling + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_custom. + lv_row = ls_table_settings_out-top_left_row. + CONDENSE lv_row. + CONCATENATE 'ISNUMBER(' ls_table_settings_out-top_left_column lv_row ')' INTO lo_data_validation->formula1. + lo_data_validation->cell_row = ls_table_settings_out-top_left_row. + lo_data_validation->cell_column = ls_table_settings_out-top_left_column. + lo_data_validation->cell_row_to = ls_table_settings_out-bottom_right_row. + lo_data_validation->cell_column_to = ls_table_settings_out-bottom_right_column. + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL21 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel21. + +TYPES: + BEGIN OF t_color_style, + color TYPE zexcel_style_color_argb, + style TYPE zexcel_cell_style, + END OF t_color_style. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_filled TYPE REF TO zcl_excel_style. + +DATA: color_styles TYPE TABLE OF t_color_style. + +FIELD-SYMBOLS: <color_style> LIKE LINE OF color_styles. + +CONSTANTS: max TYPE i VALUE 255, + step TYPE i VALUE 51. + +DATA: red TYPE i, + green TYPE i, + blue TYPE i, + red_hex(1) TYPE x, + green_hex(1) TYPE x, + blue_hex(1) TYPE x, + red_str TYPE string, + green_str TYPE string, + blue_str TYPE string. + +DATA: color TYPE zexcel_style_color_argb, + tint TYPE zexcel_style_color_tint. + +DATA: row TYPE i, + row_tmp TYPE i, + column TYPE zexcel_cell_column VALUE 1, + col_str TYPE zexcel_cell_column_alpha. + +CONSTANTS: gc_save_file_name TYPE string VALUE '21_BackgroundColorPicker.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + WHILE red <= max. + green = 0. + WHILE green <= max. + blue = 0. + WHILE blue <= max. + red_hex = red. + red_str = red_hex. + green_hex = green. + green_str = green_hex. + blue_hex = blue. + blue_str = blue_hex. + " Create filled + CONCATENATE 'FF' red_str green_str blue_str INTO color. + APPEND INITIAL LINE TO color_styles ASSIGNING <color_style>. + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-rgb = color. + <color_style>-color = color. + <color_style>-style = lo_style_filled->get_guid( ). + blue = blue + step. + ENDWHILE. + green = green + step. + ENDWHILE. + red = red + step. + ENDWHILE. + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Color Picker' ). + LOOP AT color_styles ASSIGNING <color_style>. + row_tmp = ( max / step + 1 ) * 3. + IF row = row_tmp. + row = 0. + column = column + 1. + ENDIF. + row = row + 1. + col_str = zcl_excel_common=>convert_column2alpha( column ). + + " Fill the cell and apply one style + lo_worksheet->set_cell( ip_column = col_str + ip_row = row + ip_value = <color_style>-color + ip_style = <color_style>-style ). + ENDLOOP. + + row = row + 2. + tint = '-0.5'. + DO 10 TIMES. + column = 1. + DO 10 TIMES. + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-theme = sy-index - 1. + lo_style_filled->fill->fgcolor-tint = tint. + <color_style>-style = lo_style_filled->get_guid( ). + col_str = zcl_excel_common=>convert_column2alpha( column ). + lo_worksheet->set_cell_style( ip_column = col_str + ip_row = row + ip_style = <color_style>-style ). + + ADD 1 TO column. + ENDDO. + ADD '0.1' TO tint. + ADD 1 TO row. + ENDDO. + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *--------------------------------------------------------------------* +* REPORT ZDEMO_EXCEL20 +* Demo for method zcl_excel_worksheet-bind_alv: +* export data from ALV (CL_GUI_ALV_GRID) object to excel +*--------------------------------------------------------------------* +REPORT zdemo_excel20. + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events DEFINITION. + PUBLIC SECTION. + METHODS: + on_user_command FOR EVENT added_function OF cl_salv_events + IMPORTING e_salv_function. +ENDCLASS. "lcl_handle_events DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events IMPLEMENTATION. + METHOD on_user_command. + PERFORM user_command." using e_salv_function text-i08. + ENDMETHOD. "on_user_command +ENDCLASS. "lcl_handle_events IMPLEMENTATION + +*--------------------------------------------------------------------* +* DATA DECLARATION +*--------------------------------------------------------------------* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_alv TYPE REF TO cl_gui_alv_grid, + lo_salv TYPE REF TO cl_salv_table, + gr_events TYPE REF TO lcl_handle_events, + lr_events TYPE REF TO cl_salv_events_table, + gt_sbook TYPE TABLE OF sbook, + gt_listheader TYPE slis_t_listheader, + wa_listheader LIKE LINE OF gt_listheader. + +DATA: l_path TYPE string, " local dir + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: + lv_default_file_name TYPE string VALUE '20_BindAlv.xlsx'. +*--------------------------------------------------------------------* +*START-OF-SELECTION +*--------------------------------------------------------------------* + +START-OF-SELECTION. + +* get data +* ------------------------------------------ + + SELECT * + INTO TABLE gt_sbook[] + FROM sbook "#EC CI_NOWHERE + UP TO 10 ROWS. + +* Display ALV +* ------------------------------------------ + + TRY. + cl_salv_table=>factory( + EXPORTING + list_display = abap_false + IMPORTING + r_salv_table = lo_salv + CHANGING + t_table = gt_sbook[] ). + CATCH cx_salv_msg . + ENDTRY. + + TRY. + lo_salv->set_screen_status( + EXPORTING + report = sy-repid + pfstatus = 'ALV_STATUS' + set_functions = lo_salv->c_functions_all ). + CATCH cx_salv_msg . + ENDTRY. + + lr_events = lo_salv->get_event( ). + CREATE OBJECT gr_events. + SET HANDLER gr_events->on_user_command FOR lr_events. + + lo_salv->display( ). + + +*&---------------------------------------------------------------------* +*& Form USER_COMMAND +*&---------------------------------------------------------------------* +* ALV user command +*--------------------------------------------------------------------* +FORM user_command . + IF sy-ucomm = 'EXCEL'. + +* get save file path + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = l_path ). + cl_gui_cfw=>flush( ). + cl_gui_frontend_services=>directory_browse( + EXPORTING initial_folder = l_path + CHANGING selected_folder = l_path ). + + IF l_path IS INITIAL. + cl_gui_frontend_services=>get_sapgui_workdir( + CHANGING sapworkdir = lv_workdir ). + l_path = lv_workdir. + ENDIF. + + cl_gui_frontend_services=>get_file_separator( + CHANGING file_separator = lv_file_separator ). + + CONCATENATE l_path lv_file_separator lv_default_file_name + INTO l_path. + +* export file to save file path + + PERFORM export_to_excel. + + ENDIF. +ENDFORM. " USER_COMMAND + +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +FORM export_to_excel. + +* create zcl_excel_worksheet object + + CREATE OBJECT lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + +* get ALV object from screen + + CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR' + IMPORTING + e_grid = lo_alv. + +* build list header + + wa_listheader-typ = 'H'. + wa_listheader-info = sy-title. + APPEND wa_listheader TO gt_listheader. + + wa_listheader-typ = 'S'. + wa_listheader-info = 'Created by: ABAP2XLSX Group'. + APPEND wa_listheader TO gt_listheader. + + wa_listheader-typ = 'A'. + wa_listheader-info = + 'Project hosting at https://cw.sdn.sap.com/cw/groups/abap2xlsx'. + APPEND wa_listheader TO gt_listheader. + +* write to excel using method Bin_ALV + + lo_worksheet->bind_alv_ole2( + EXPORTING +* I_DOCUMENT_URL = SPACE " excel template +* I_XLS = 'X' " create in xls format? + i_save_path = l_path + io_alv = lo_alv + it_listheader = gt_listheader + i_top = 2 + i_left = 1 +* I_COLUMNS_HEADER = 'X' +* I_COLUMNS_AUTOFIT = 'X' +* I_FORMAT_COL_HEADER = +* I_FORMAT_SUBTOTAL = +* I_FORMAT_TOTAL = + EXCEPTIONS + miss_guide = 1 + ex_transfer_kkblo_error = 2 + fatal_error = 3 + inv_data_range = 4 + dim_mismatch_vkey = 5 + dim_mismatch_sema = 6 + error_in_sema = 7 + OTHERS = 8 + ). + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + ENDIF. + +ENDFORM. "EXPORT_TO_EXCEL + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL42 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT ZDEMO_EXCEL42. +type-POOLS: vrm. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_theme TYPE REF TO zcl_excel_theme, + lo_style type ref to zcl_excel_style, + lv_style_guid type ZEXCEL_CELL_STYLE. +DATA: gc_save_file_name TYPE string VALUE '42 Theme Manipulation demo.&'. +include zdemo_excel_outputopt_incl. + +initialization. + + +START-OF-SELECTION. + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create a bold / italic style with usage of major font + lo_style = lo_excel->add_new_style( ). + lo_style->font->bold = abap_true. + lo_style->font->italic = abap_true. + lo_style->font->scheme = zcl_excel_style_font=>c_scheme_major. + lo_style->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_guid = lo_style->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Styles' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Bold text' ip_style = lv_style_guid ). + + "create theme + create object lo_theme. + lo_theme->set_theme_name( iv_name = 'Theme Demo 42 A2X' ). + lo_theme->set_color_scheme_name( iv_name = 'Demo 42 A2X' ). + + "set theme colors + lo_theme->set_color( + exporting + iv_type = zcl_excel_theme_color_scheme=>c_dark1 + iv_srgb = '5F9EA0' +* iv_syscolorname = +* iv_syscolorlast = + ). + lo_theme->set_color( + exporting + iv_type = zcl_excel_theme_color_scheme=>c_dark2 + iv_srgb = 'FFA500' +* iv_syscolorname = +* iv_syscolorlast = + ). + lo_theme->set_color( + exporting + iv_type = zcl_excel_theme_color_scheme=>c_light1 + iv_srgb = '778899' +* iv_syscolorname = +* iv_syscolorlast = + ). + + lo_theme->set_color( + exporting + iv_type = zcl_excel_theme_color_scheme=>c_light1 + iv_srgb = '9932CC' +* iv_syscolorname = +* iv_syscolorlast = + ). + lo_theme->set_font_scheme_name( iv_name = 'Demo 42 A2X' ). + + + "set theme latin fonts - major and minor + lo_theme->set_latin_font( + exporting + iv_type = zcl_excel_theme_font_scheme=>c_major + iv_typeface = 'Britannic Bold' +* iv_panose = +* iv_pitchfamily = +* iv_charset = + ). + lo_theme->set_latin_font( + exporting + iv_type = zcl_excel_theme_font_scheme=>c_minor + iv_typeface = 'Broadway' +* iv_panose = +* iv_pitchfamily = +* iv_charset = + ). + "push theme to file + lo_excel->set_theme( io_theme = lo_theme ). + + "output + lcl_output=>output( cl_excel = lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_style_green TYPE REF TO zcl_excel_style, + lo_style_yellow TYPE REF TO zcl_excel_style, + lo_style_red TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lv_style_title_guid TYPE zexcel_cell_style, + lv_style_green_guid TYPE zexcel_cell_style, + lv_style_yellow_guid TYPE zexcel_cell_style, + lv_style_red_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis, + ls_key TYPE wwwdatatab. + +DATA: lo_send_request TYPE REF TO cl_bcs, + lo_document TYPE REF TO cl_document_bcs, + lo_sender TYPE REF TO cl_sapuser_bcs, + lo_recipient TYPE REF TO cl_sapuser_bcs, + lo_recipient_i TYPE REF TO CL_CAM_ADDRESS_BCS. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lv_bytecount_c TYPE sood-objlen, + lt_file_tab TYPE solix_tab. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_value = 'Total score' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 10 ip_formula = 'SUM(C7:C8)' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " defne conditional styles + lo_style_green = lo_excel->add_new_style( ). + lo_style_green->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_green->fill->bgcolor-rgb = zcl_excel_style_color=>c_green. + lv_style_green_guid = lo_style_green->get_guid( ). + + lo_style_yellow = lo_excel->add_new_style( ). + lo_style_yellow->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_yellow->fill->bgcolor-rgb = zcl_excel_style_color=>c_yellow. + lv_style_yellow_guid = lo_style_yellow->get_guid( ). + + lo_style_red = lo_excel->add_new_style( ). + lo_style_red->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_red->fill->bgcolor-rgb = zcl_excel_style_color=>c_red. + lv_style_red_guid = lo_style_red->get_guid( ). + + " add conditional formatting + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_green_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 1. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_yellow_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '0'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_red_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 3. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + lv_bytecount_c = lv_bytecount. + + " Send via email + lo_document = cl_document_bcs=>create_document( i_type = 'RAW' + i_subject = 'Demo TechEd' ). + + lo_document->add_attachment( i_attachment_type = 'EXT' + i_attachment_subject = 'abap2xlsx.xlsx' + i_attachment_size = lv_bytecount_c + i_att_content_hex = lt_file_tab ). + + lo_sender = cl_sapuser_bcs=>create( sy-uname ). + lo_recipient = cl_sapuser_bcs=>create( sy-uname ). +* lo_recipient_i = cl_cam_address_bcs=>create_internet_address( 'ivan.femia@techedge.it' ). + + lo_send_request = cl_bcs=>create_persistent( ). + lo_send_request->set_document( lo_document ). + lo_send_request->set_sender( lo_sender ). + lo_send_request->add_recipient( lo_recipient ). + lo_send_request->set_send_immediately( abap_true ). + lo_send_request->send( ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel3. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + +DATA: ls_table_settings TYPE zexcel_s_table_settings. + + +DATA: lv_title TYPE zexcel_sheet_title, + lt_carr TYPE TABLE OF scarr, + row TYPE zexcel_cell_row VALUE 2, + lo_range TYPE REF TO zcl_excel_range. +DATA: lo_data_validation TYPE REF TO zcl_excel_data_validation. +FIELD-SYMBOLS: <carr> LIKE LINE OF lt_carr. + +CONSTANTS: c_airlines TYPE string VALUE 'Airlines'. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '03_iTab.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_empty TYPE flag. + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Internal table'). + + DATA lt_test TYPE TABLE OF sflight. + + IF p_empty <> abap_true. + SELECT * FROM sflight INTO TABLE lt_test. "#EC CI_NOWHERE + ENDIF. + + ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium2. + ls_table_settings-show_row_stripes = abap_true. + ls_table_settings-nofilters = abap_true. + + lo_worksheet->bind_table( ip_table = lt_test + is_table_settings = ls_table_settings ). + + lo_worksheet->freeze_panes( ip_num_rows = 3 ). "freeze column headers when scrolling + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'E' ). "make date field a bit wider + column_dimension->set_width( ip_width = 11 ). + " Add another table for data validations + lo_worksheet = lo_excel->add_new_worksheet( ). + lv_title = 'Data Validation'. + lo_worksheet->set_title( lv_title ). + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = c_airlines ). + SELECT * FROM scarr INTO TABLE lt_carr. "#EC CI_NOWHERE + LOOP AT lt_carr ASSIGNING <carr>. + lo_worksheet->set_cell( ip_row = row ip_column = 'A' ip_value = <carr>-carrid ). + row = row + 1. + ENDLOOP. + row = row - 1. + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_airlines. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'A' + ip_start_row = 2 + ip_stop_column = 'A' + ip_stop_row = row ). + " Set Data Validation + lo_excel->set_active_sheet_index( 1 ). + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_airlines. + lo_data_validation->cell_row = 4. + lo_data_validation->cell_column = 'C'. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel30. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + +DATA: lv_value TYPE string, + lv_count TYPE i VALUE 10, + lv_packed TYPE p LENGTH 16 DECIMALS 1 VALUE '1234567890.5'. + +CONSTANTS: lc_typekind_string TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_string, + lc_typekind_packed TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_packed, + lc_typekind_num TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_num, + lc_typekind_date TYPE abap_typekind VALUE cl_abap_typedescr=>typekind_date, + lc_typekind_s_ls TYPE string VALUE 's_leading_blanks'. + +CONSTANTS: gc_save_file_name TYPE string VALUE '30_CellDataTypes.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Cell data types' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'Number as String' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 2 ip_value = '11' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 1 ip_value = 'String' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = ' String with leading spaces' + ip_data_type = lc_typekind_s_ls ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = ' Negative Value' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 1 ip_value = 'Packed' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 2 ip_value = '50000.01-' + ip_abap_type = lc_typekind_packed ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 1 ip_value = 'Number with Percentage' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 2 ip_value = '0 %' + ip_abap_type = lc_typekind_num ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = 1 ip_value = 'Date' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = 2 ip_value = '20110831' + ip_abap_type = lc_typekind_date ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'Positive Value' + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = '5000.02' + ip_abap_type = lc_typekind_packed ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 3 ip_value = '50 %' + ip_abap_type = lc_typekind_num ). + + WHILE lv_count <= 15. + lv_value = lv_count. + CONCATENATE 'Positive Value with' lv_value 'Digits' INTO lv_value SEPARATED BY space. + lo_worksheet->set_cell( ip_column = 'B' ip_row = lv_count ip_value = lv_value + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = lv_count ip_value = lv_packed + ip_abap_type = lc_typekind_packed ). + CONCATENATE 'Positive Value with' lv_value 'Digits formated as string' INTO lv_value SEPARATED BY space. + lo_worksheet->set_cell( ip_column = 'D' ip_row = lv_count ip_value = lv_value + ip_abap_type = lc_typekind_string ). + lo_worksheet->set_cell( ip_column = 'E' ip_row = lv_count ip_value = lv_packed + ip_abap_type = lc_typekind_string ). + lv_packed = lv_packed * 10. + lv_count = lv_count + 1. + ENDWHILE. + + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'D' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( ip_column = 'E' ). + column_dimension->set_auto_size( abap_true ). + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel31. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime. + + +DATA: fieldval TYPE text80, + row TYPE i, + style_column_a TYPE REF TO zcl_excel_style, + style_column_a_guid TYPE zexcel_cell_style, + style_column_b TYPE REF TO zcl_excel_style, + style_column_b_guid TYPE zexcel_cell_style, + style_column_c TYPE REF TO zcl_excel_style, + style_column_c_guid TYPE zexcel_cell_style, + style_font TYPE REF TO zcl_excel_style_font. + +CONSTANTS: gc_save_file_name TYPE string VALUE '31_AutosizeWithDifferentFontSizes.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + " Use active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Regular Font' ). + + style_column_a = lo_excel->add_new_style( ). + style_column_a->font->size = 32. " quite large + style_column_a_guid = style_column_a->get_guid( ). + + style_column_c = lo_excel->add_new_style( ). + style_column_c->font->size = 16. " not so large + style_column_c_guid = style_column_c->get_guid( ). + + + DO 20 TIMES. + row = sy-index. + CLEAR fieldval. + DO sy-index TIMES. + CONCATENATE fieldval 'X' INTO fieldval. + ENDDO. + lo_worksheet->set_cell( ip_column = 'A' ip_row = row ip_value = fieldval ip_style = style_column_a_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = row ip_value = fieldval ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = row ip_value = fieldval ip_style = style_column_c_guid ). + ENDDO. + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Add sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Bold Font' ). + + style_column_a = lo_excel->add_new_style( ). + style_column_a->font->size = 32. " quite large + style_column_a->font->bold = abap_true. + style_column_a_guid = style_column_a->get_guid( ). + + style_column_b = lo_excel->add_new_style( ). + style_column_b->font->bold = abap_true. + style_column_b_guid = style_column_b->get_guid( ). + + style_column_c = lo_excel->add_new_style( ). + style_column_c->font->size = 16. " not so large + style_column_c->font->bold = abap_true. + style_column_c_guid = style_column_c->get_guid( ). + + DO 20 TIMES. + row = sy-index. + CLEAR fieldval. + DO sy-index TIMES. + CONCATENATE fieldval 'X' INTO fieldval. + ENDDO. + lo_worksheet->set_cell( ip_column = 'A' ip_row = row ip_value = fieldval ip_style = style_column_a_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = row ip_value = fieldval ip_style = style_column_b_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = row ip_value = fieldval ip_style = style_column_c_guid ). + ENDDO. + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Add sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Italic Font' ). + + style_column_a = lo_excel->add_new_style( ). + style_column_a->font->size = 32. " quite large + style_column_a->font->italic = abap_true. + style_column_a_guid = style_column_a->get_guid( ). + + style_column_b = lo_excel->add_new_style( ). + style_column_b->font->italic = abap_true. + style_column_b_guid = style_column_b->get_guid( ). + + style_column_c = lo_excel->add_new_style( ). + style_column_c->font->size = 16. " not so large + style_column_c->font->italic = abap_true. + style_column_c_guid = style_column_c->get_guid( ). + + DO 20 TIMES. + row = sy-index. + CLEAR fieldval. + DO sy-index TIMES. + CONCATENATE fieldval 'X' INTO fieldval. + ENDDO. + lo_worksheet->set_cell( ip_column = 'A' ip_row = row ip_value = fieldval ip_style = style_column_a_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = row ip_value = fieldval ip_style = style_column_b_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = row ip_value = fieldval ip_style = style_column_c_guid ). + ENDDO. + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Add sheet for merged cells + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Merged cells' ). + + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = 'This is a very long header text' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 2 ip_value = 'Some data' ). + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = 'Some more data' ). + + lo_worksheet->set_merge( + EXPORTING + ip_column_start = 'A' + ip_column_end = 'C' + ip_row = 1 ). + + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( ip_auto_size = abap_true ). + + lo_excel->set_active_sheet_index( i_active_worksheet = 1 ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *--------------------------------------------------------------------* +* REPORT ZDEMO_EXCEL32 +* Demo for export options from ALV GRID: +* export data from ALV (CL_GUI_ALV_GRID) object or cl_salv_table object +* to Excel. +*--------------------------------------------------------------------* +REPORT zdemo_excel32. + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events DEFINITION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events DEFINITION. + PUBLIC SECTION. + METHODS: + on_user_command FOR EVENT added_function OF cl_salv_events + IMPORTING e_salv_function. +ENDCLASS. "lcl_handle_events DEFINITION + +*----------------------------------------------------------------------* +* CLASS lcl_handle_events IMPLEMENTATION +*----------------------------------------------------------------------* +* +*----------------------------------------------------------------------* +CLASS lcl_handle_events IMPLEMENTATION. + METHOD on_user_command. + PERFORM user_command." using e_salv_function text-i08. + ENDMETHOD. "on_user_command +ENDCLASS. "lcl_handle_events IMPLEMENTATION + +*--------------------------------------------------------------------* +* DATA DECLARATION +*--------------------------------------------------------------------* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_salv TYPE REF TO cl_salv_table, + gr_events TYPE REF TO lcl_handle_events, + lr_events TYPE REF TO cl_salv_events_table, + gt_sbook TYPE TABLE OF sbook. + +DATA: l_path TYPE string, " local dir + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: + lv_default_file_name TYPE string VALUE '32_Export_ALV.xlsx', + lv_default_file_name2 TYPE string VALUE '32_Export_Convert.xlsx'. +*--------------------------------------------------------------------* +*START-OF-SELECTION +*--------------------------------------------------------------------* + +START-OF-SELECTION. + +* get data +* ------------------------------------------ + + SELECT * + INTO TABLE gt_sbook[] + FROM sbook "#EC CI_NOWHERE + UP TO 100 ROWS. + +* Display ALV +* ------------------------------------------ + + TRY. + cl_salv_table=>factory( + EXPORTING + list_display = abap_false + IMPORTING + r_salv_table = lo_salv + CHANGING + t_table = gt_sbook[] ). + CATCH cx_salv_msg . + ENDTRY. + + TRY. + lo_salv->set_screen_status( + EXPORTING + report = sy-repid + pfstatus = 'ALV_STATUS' + set_functions = lo_salv->c_functions_all ). + CATCH cx_salv_msg . + ENDTRY. + + lr_events = lo_salv->get_event( ). + CREATE OBJECT gr_events. + SET HANDLER gr_events->on_user_command FOR lr_events. + + lo_salv->display( ). + + +*&---------------------------------------------------------------------* +*& Form USER_COMMAND +*&---------------------------------------------------------------------* +* ALV user command +*--------------------------------------------------------------------* +FORM user_command . + +* get save file path + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = l_path ). + cl_gui_cfw=>flush( ). + cl_gui_frontend_services=>directory_browse( + EXPORTING initial_folder = l_path + CHANGING selected_folder = l_path ). + + IF l_path IS INITIAL. + cl_gui_frontend_services=>get_sapgui_workdir( + CHANGING sapworkdir = lv_workdir ). + l_path = lv_workdir. + ENDIF. + + cl_gui_frontend_services=>get_file_separator( + CHANGING file_separator = lv_file_separator ). + + + +* export file to save file path + CASE sy-ucomm. + WHEN 'EXCELBIND'. + CONCATENATE l_path lv_file_separator lv_default_file_name + INTO l_path. + PERFORM export_to_excel_bind. + + WHEN 'EXCELCONV'. + + CONCATENATE l_path lv_file_separator lv_default_file_name2 + INTO l_path. + PERFORM export_to_excel_conv. + + ENDCASE. +ENDFORM. " USER_COMMAND +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL_CONV +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +FORM export_to_excel_conv. + DATA: lo_converter TYPE REF TO zcl_excel_converter. + + CREATE OBJECT lo_converter. +*TRY. + lo_converter->convert( + EXPORTING + io_alv = lo_salv + it_table = gt_sbook + i_row_int = 2 + i_column_int = 2 +* i_table = +* i_style_table = +* io_worksheet = +* CHANGING +* co_excel = + ). +* CATCH zcx_excel . +*ENDTRY. + lo_converter->write_file( i_path = l_path ). + +ENDFORM. "EXPORT_TO_EXCEL_CONV + +*--------------------------------------------------------------------* +* FORM EXPORT_TO_EXCEL_BIND +*--------------------------------------------------------------------* +* This subroutine is principal demo session +*--------------------------------------------------------------------* +FORM export_to_excel_bind. +* create zcl_excel_worksheet object + CREATE OBJECT lo_excel. + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + +* write to excel using method Bin_object +*try. + lo_worksheet->bind_alv( + io_alv = lo_salv + it_table = gt_sbook + i_top = 2 + i_left = 1 + ). +* catch zcx_excel . +*endtry. + + + PERFORM write_file. + +ENDFORM. "EXPORT_TO_EXCEL_BIND +*&---------------------------------------------------------------------* +*& Form WRITE_FILE +*&---------------------------------------------------------------------* +* text +*----------------------------------------------------------------------* +* --> p1 text +* <-- p2 text +*----------------------------------------------------------------------* +FORM write_file . + DATA: lt_file TYPE solix_tab, + l_bytecount TYPE i, + l_file TYPE xstring. + + DATA: lo_excel_writer TYPE REF TO zif_excel_writer. + + DATA: ls_seoclass TYPE seoclass. + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + l_file = lo_excel_writer->write_file( lo_excel ). + + SELECT SINGLE * INTO ls_seoclass + FROM seoclass + WHERE clsname = 'CL_BCS_CONVERT'. + + IF sy-subrc = 0. + CALL METHOD (ls_seoclass-clsname)=>xstring_to_solix + EXPORTING + iv_xstring = l_file + RECEIVING + et_solix = lt_file. + + l_bytecount = XSTRLEN( l_file ). + ELSE. + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = l_file + IMPORTING + output_length = l_bytecount + TABLES + binary_tab = lt_file. + ENDIF. + + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = l_bytecount + filename = l_path + filetype = 'BIN' + CHANGING data_tab = lt_file ). + +ENDFORM. " WRITE_FILE + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel33. + +TYPE-POOLS: abap. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_converter TYPE REF TO zcl_excel_converter, + lo_autofilter TYPE REF TO zcl_excel_autofilter. + +DATA lt_test TYPE TABLE OF t005t. + +DATA: l_cell_value TYPE zexcel_cell_value, + ls_area TYPE zexcel_s_autofilter_area. + +CONSTANTS: c_airlines TYPE string VALUE 'Airlines'. + +CONSTANTS: gc_save_file_name TYPE string VALUE '33_autofilter.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Internal table'). + + SELECT * UP TO 2 ROWS FROM t005t INTO TABLE lt_test. "#EC CI_NOWHERE + + CREATE OBJECT lo_converter. + + lo_converter->convert( EXPORTING + it_table = lt_test + i_row_int = 1 + i_column_int = 1 + io_worksheet = lo_worksheet + CHANGING + co_excel = lo_excel ) . + + lo_autofilter = lo_excel->add_new_autofilter( io_sheet = lo_worksheet ) . + + ls_area-row_start = 1. + ls_area-col_start = 1. + ls_area-row_end = lo_worksheet->get_highest_row( ). + ls_area-col_end = lo_worksheet->get_highest_column( ). + + lo_autofilter->set_filter_area( is_area = ls_area ). + + lo_worksheet->get_cell( EXPORTING + ip_column = 'C' + ip_row = 2 + IMPORTING + ep_value = l_cell_value ). + lo_autofilter->set_value( i_column = 3 + i_value = l_cell_value ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL2 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel34. + +CONSTANTS: width TYPE f VALUE '10.14'. +CONSTANTS: height TYPE f VALUE '57.75'. + +DATA: current_row TYPE i, + col TYPE i, + col_alpha TYPE zexcel_cell_column_alpha, + row TYPE i, + row_board TYPE i, + colorflag TYPE i, + color TYPE zexcel_style_color_argb, + + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + row_dimension TYPE REF TO zcl_excel_worksheet_rowdimensi, + + writing1 TYPE string, + writing2 TYPE string. + + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +CONSTANTS: gc_save_file_name TYPE string VALUE '34_Static Styles_Chess.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Spassky_vs_Bronstein' ). + +* Header + current_row = 1. + + ADD 1 TO current_row. + lo_worksheet->set_cell( ip_row = current_row ip_column = 'B' ip_value = 'White' ). + lo_worksheet->set_cell( ip_row = current_row ip_column = 'C' ip_value = 'Spassky, Boris V -- wins in turn 23' ). + + ADD 1 TO current_row. + lo_worksheet->set_cell( ip_row = current_row ip_column = 'B' ip_value = 'Black' ). + lo_worksheet->set_cell( ip_row = current_row ip_column = 'C' ip_value = 'Bronstein, David I' ). + + ADD 1 TO current_row. +* Set size of column + Writing above chessboard + DO 8 TIMES. + + writing1 = zcl_excel_common=>convert_column2alpha( sy-index ). + writing2 = sy-index . + row = current_row + sy-index. + + col = sy-index + 1. + col_alpha = zcl_excel_common=>convert_column2alpha( col ). + +* Set size of column + column_dimension = lo_worksheet->get_column_dimension( col_alpha ). + column_dimension->set_width( width ). + +* Set size of row + row_dimension = lo_worksheet->get_row_dimension( row ). + row_dimension->set_row_height( height ). + +* Set writing on chessboard + lo_worksheet->set_cell( ip_row = row + ip_column = 'A' + ip_value = writing2 ). + lo_worksheet->change_cell_style( ip_column = 'A' + ip_row = row + ip_alignment_vertical = zcl_excel_style_alignment=>c_vertical_center ). + lo_worksheet->set_cell( ip_row = row + ip_column = 'J' + ip_value = writing2 ). + lo_worksheet->change_cell_style( ip_column = 'J' + ip_row = row + ip_alignment_vertical = zcl_excel_style_alignment=>c_vertical_center ). + + row = current_row + 9. + lo_worksheet->set_cell( ip_row = current_row + ip_column = col_alpha + ip_value = writing1 ). + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = current_row + ip_alignment_horizontal = zcl_excel_style_alignment=>c_horizontal_center ). + lo_worksheet->set_cell( ip_row = row + ip_column = col_alpha + ip_value = writing1 ). + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_alignment_horizontal = zcl_excel_style_alignment=>c_horizontal_center ). + ENDDO. + column_dimension = lo_worksheet->get_column_dimension( 'A' ). + column_dimension->set_auto_size( abap_true ). + column_dimension = lo_worksheet->get_column_dimension( 'J' ). + column_dimension->set_auto_size( abap_true ). + +* Set win-position + CONSTANTS: c_pawn TYPE string VALUE 'Pawn'. + CONSTANTS: c_rook TYPE string VALUE 'Rook'. + CONSTANTS: c_knight TYPE string VALUE 'Knight'. + CONSTANTS: c_bishop TYPE string VALUE 'Bishop'. + CONSTANTS: c_queen TYPE string VALUE 'Queen'. + CONSTANTS: c_king TYPE string VALUE 'King'. + + row = current_row + 1. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = c_rook ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_rook ). + lo_worksheet->set_cell( ip_row = row ip_column = 'G' ip_value = c_knight ). + row = current_row + 2. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'D' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_queen ). + lo_worksheet->set_cell( ip_row = row ip_column = 'H' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'I' ip_value = c_king ). + row = current_row + 3. + lo_worksheet->set_cell( ip_row = row ip_column = 'I' ip_value = c_pawn ). + row = current_row + 4. + lo_worksheet->set_cell( ip_row = row ip_column = 'D' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_knight ). + row = current_row + 5. + lo_worksheet->set_cell( ip_row = row ip_column = 'E' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'F' ip_value = c_queen ). + row = current_row + 6. + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = c_bishop ). + row = current_row + 7. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'H' ip_value = c_pawn ). + lo_worksheet->set_cell( ip_row = row ip_column = 'I' ip_value = c_pawn ). + row = current_row + 8. + lo_worksheet->set_cell( ip_row = row ip_column = 'G' ip_value = c_rook ). + lo_worksheet->set_cell( ip_row = row ip_column = 'H' ip_value = c_king ). + +* Set Chessboard + DO 8 TIMES. + IF sy-index <= 3. " Black + color = zcl_excel_style_color=>c_black. + ELSE. + color = zcl_excel_style_color=>c_white. + ENDIF. + row_board = sy-index. + row = current_row + sy-index. + DO 8 TIMES. + col = sy-index + 1. + col_alpha = zcl_excel_common=>convert_column2alpha( col ). + TRY. +* Borders around outer limits + IF row_board = 1. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_top_style = zcl_excel_style_border=>c_border_thick + ip_borders_top_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. + IF row_board = 8. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_down_style = zcl_excel_style_border=>c_border_thick + ip_borders_down_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. + IF col = 2. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_left_style = zcl_excel_style_border=>c_border_thick + ip_borders_left_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. + IF col = 9. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_borders_right_style = zcl_excel_style_border=>c_border_thick + ip_borders_right_color_rgb = zcl_excel_style_color=>c_black ). + ENDIF. +* Style for writing + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_font_color_rgb = color + ip_font_bold = 'X' + ip_font_size = 16 + ip_alignment_horizontal = zcl_excel_style_alignment=>c_horizontal_center + ip_alignment_vertical = zcl_excel_style_alignment=>c_vertical_center + ip_fill_filltype = zcl_excel_style_fill=>c_fill_solid ). +* Color of field + colorflag = ( row + col ) MOD 2. + IF colorflag = 0. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_fill_fgcolor_rgb = 'FFB5866A' + ip_fill_filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal135 ). + ELSE. + lo_worksheet->change_cell_style( ip_column = col_alpha + ip_row = row + ip_fill_fgcolor_rgb = 'FFF5DEBF' + ip_fill_filltype = zcl_excel_style_fill=>c_fill_gradient_diagonal45 ). + ENDIF. + + + + CATCH zcx_excel . + ENDTRY. + + ENDDO. + ENDDO. + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL2 +*& Test Styles for ABAP2XLSX +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel35. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_bold TYPE REF TO zcl_excel_style, + lo_style_underline TYPE REF TO zcl_excel_style, + lo_style_filled TYPE REF TO zcl_excel_style, + lo_style_border TYPE REF TO zcl_excel_style, + lo_style_button TYPE REF TO zcl_excel_style, + lo_border_dark TYPE REF TO zcl_excel_style_border, + lo_border_light TYPE REF TO zcl_excel_style_border. + +DATA: lv_style_bold_guid TYPE zexcel_cell_style, + lv_style_underline_guid TYPE zexcel_cell_style, + lv_style_filled_guid TYPE zexcel_cell_style, + lv_style_filled_green_guid TYPE zexcel_cell_style, + lv_style_border_guid TYPE zexcel_cell_style, + lv_style_button_guid TYPE zexcel_cell_style, + lv_style_filled_turquoise_guid TYPE zexcel_cell_style. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE '35_Static_Styles.xlsx'. + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>GET_DESKTOP_DIRECTORY( CHANGING DESKTOP_DIRECTORY = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + + sy-title = 'ZDEMO_EXCEL2;Issue 139: Change cellstyle retroactivly'. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create border object + CREATE OBJECT lo_border_dark. + lo_border_dark->border_color-rgb = zcl_excel_style_color=>c_black. + lo_border_dark->border_style = zcl_excel_style_border=>c_border_thin. + CREATE OBJECT lo_border_light. + lo_border_light->border_color-rgb = zcl_excel_style_color=>c_gray. + lo_border_light->border_style = zcl_excel_style_border=>c_border_thin. + " Create a bold / italic style + lo_style_bold = lo_excel->add_new_style( ). + lo_style_bold->font->bold = abap_true. + lo_style_bold->font->italic = abap_true. + lo_style_bold->font->name = zcl_excel_style_font=>c_name_arial. + lo_style_bold->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_bold->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_bold_guid = lo_style_bold->get_guid( ). + " Create an underline double style + lo_style_underline = lo_excel->add_new_style( ). + lo_style_underline->font->underline = abap_true. + lo_style_underline->font->underline_mode = zcl_excel_style_font=>c_underline_double. + lo_style_underline->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_underline->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_underline->font->family = zcl_excel_style_font=>c_family_roman. + lv_style_underline_guid = lo_style_underline->get_guid( ). + " Create filled style yellow + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-theme = zcl_excel_style_color=>c_theme_accent6. + lv_style_filled_guid = lo_style_filled->get_guid( ). + " Create border with button effects + lo_style_button = lo_excel->add_new_style( ). + lo_style_button->borders->right = lo_border_dark. + lo_style_button->borders->down = lo_border_dark. + lo_style_button->borders->left = lo_border_light. + lo_style_button->borders->top = lo_border_light. + lv_style_button_guid = lo_style_button->get_guid( ). + "Create style with border + lo_style_border = lo_excel->add_new_style( ). + lo_style_border->borders->allborders = lo_border_dark. + lo_style_border->borders->diagonal = lo_border_dark. + lo_style_border->borders->diagonal_mode = zcl_excel_style_borders=>c_diagonal_both. + lv_style_border_guid = lo_style_border->get_guid( ). + " Create filled style green + lo_style_filled = lo_excel->add_new_style( ). + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-rgb = zcl_excel_style_color=>c_green. + lo_style_filled->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_filled->font->scheme = zcl_excel_style_font=>c_scheme_major. + lv_style_filled_green_guid = lo_style_filled->get_guid( ). + + " Create filled style turquoise using legacy excel ver <= 2003 palette. (https://code.sdn.sap.com/spaces/abap2xlsx/tickets/92) + lo_style_filled = lo_excel->add_new_style( ). + lo_excel->legacy_palette->set_color( "replace built-in color from palette with out custom RGB turquoise + ip_index = 16 + ip_color = '0040E0D0' ). + + lo_style_filled->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_filled->fill->fgcolor-indexed = 16. + lv_style_filled_turquoise_guid = lo_style_filled->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Styles' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = 'Bold text' ip_style = lv_style_bold_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 4 ip_value = 'Underlined text' ip_style = lv_style_underline_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 6 ip_value = 'Borders' ip_style = lv_style_border_guid ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 7 ip_value = 'I''m not a button :)' ip_style = lv_style_button_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 9 ip_value = 'Modified color for Excel 2003' ip_style = lv_style_filled_turquoise_guid ). + " Fill the cell and apply one style + lo_worksheet->set_cell( ip_column = 'B' ip_row = 6 ip_value = 'Filled text' ip_style = lv_style_filled_guid ). + " Change the style + lo_worksheet->set_cell_style( ip_column = 'B' ip_row = 6 ip_style = lv_style_filled_green_guid ). + " Add Style to an empty cell to test Fix for Issue + "#44 Exception ZCX_EXCEL thrown when style is set for an empty cell + " https://code.sdn.sap.com/spaces/abap2xlsx/tickets/44-exception-zcx_excel-thrown-when-style-is-set-for-an-empty-cell + lo_worksheet->set_cell_style( ip_column = 'E' ip_row = 6 ip_style = lv_style_filled_green_guid ). + + +* Demonstrate how to retroactivly change the cellstyle +*Filled text and underlinded text + lo_worksheet->change_cell_style( ip_column = 'B' + ip_row = 5 + ip_font_bold = abap_true + ip_font_italic = abap_true ). + + lo_worksheet->change_cell_style( ip_column = 'D' + ip_row = 4 + ip_font_bold = abap_true + ip_font_italic = abap_true ). + + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + + " Convert to binary + CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' + EXPORTING + buffer = lv_file + IMPORTING + output_length = lv_bytecount + TABLES + binary_tab = lt_file_tab. +* " This method is only available on AS ABAP > 6.40 +* lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). +* lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL36 +REPORT zdemo_excel36. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + col TYPE i. + +DATA: lo_style_arial20 TYPE REF TO zcl_excel_style, + lo_style_times11 TYPE REF TO zcl_excel_style, + lo_style_cambria8red TYPE REF TO zcl_excel_style. + +DATA: lv_style_arial20_guid TYPE zexcel_cell_style, + lv_style_times11_guid TYPE zexcel_cell_style, + lv_style_cambria8red_guid TYPE zexcel_cell_style. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '36_DefaultStyles.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Create a bold / italic style + lo_style_arial20 = lo_excel->add_new_style( ). + lo_style_arial20->font->name = zcl_excel_style_font=>c_name_arial. + lo_style_arial20->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_arial20->font->size = 20. + lv_style_arial20_guid = lo_style_arial20->get_guid( ). + + lo_style_times11 = lo_excel->add_new_style( ). + lo_style_times11->font->name = zcl_excel_style_font=>c_name_roman. + lo_style_times11->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_times11->font->size = 11. + lv_style_times11_guid = lo_style_times11->get_guid( ). + + lo_style_cambria8red = lo_excel->add_new_style( ). + lo_style_cambria8red->font->name = zcl_excel_style_font=>c_name_cambria. + lo_style_cambria8red->font->scheme = zcl_excel_style_font=>c_scheme_none. + lo_style_cambria8red->font->size = 8. + lo_style_cambria8red->font->color-rgb = zcl_excel_style_color=>c_red. + lv_style_cambria8red_guid = lo_style_cambria8red->get_guid( ). + + lo_excel->set_default_style( lv_style_arial20_guid ). " Default for all new worksheets + +* 1st sheet - do not change anything --> defaultstyle from lo_excel should apply + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'Style for complete document' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 4 ip_value = 'All cells in this sheet are set to font Arial, fontsize 20' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 5 ip_value = 'because no separate style was passed for this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 6 ip_value = 'but a default style was set for the complete instance of zcl_excel' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 1 ip_value = space ). " Missing feature "set active cell - use this to simulate that + + +* 2nd sheet - defaultstyle for this sheet set explicitly ( set to Times New Roman 11 ) + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Style for this sheet' ). + lo_worksheet->zif_excel_sheet_properties~set_style( lv_style_times11_guid ). + + lo_worksheet->set_cell( ip_column = 2 ip_row = 4 ip_value = 'All cells in this sheet are set to font Times New Roman, fontsize 11' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 5 ip_value = 'because this style was passed for this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 6 ip_value = 'thus the default style from zcl_excel does not apply to this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 1 ip_value = space ). " Missing feature "set active cell - use this to simulate that + + +* 3rd sheet - defaultstyle for columns ( set to Times New Roman 11 ) + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( 'Style for 3 columns' ). + column_dimension = lo_worksheet->get_column_dimension( 'B' ). + column_dimension->set_column_style_by_guid( ip_style_guid = lv_style_times11_guid ). + column_dimension = lo_worksheet->get_column_dimension( 'C' ). + column_dimension->set_column_style_by_guid( ip_style_guid = lv_style_times11_guid ). + column_dimension = lo_worksheet->get_column_dimension( 'F' ). + column_dimension->set_column_style_by_guid( ip_style_guid = lv_style_times11_guid ). + + lo_worksheet->set_cell( ip_column = 2 ip_row = 4 ip_value = 'The columns B,C and F are set to Times New Roman' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 10 ip_value = 'All other cells in this sheet are set to font Arial, fontsize 20' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 11 ip_value = 'because no separate style was passed for this sheet' ). + lo_worksheet->set_cell( ip_column = 2 ip_row = 12 ip_value = 'but a default style was set for the complete instance of zcl_excel' ). + + lo_worksheet->set_cell( ip_column = 8 ip_row = 1 ip_value = 'Of course' ip_style = lv_style_cambria8red_guid ). + lo_worksheet->set_cell( ip_column = 8 ip_row = 2 ip_value = 'setting a specific style to a cell' ip_style = lv_style_cambria8red_guid ). + lo_worksheet->set_cell( ip_column = 8 ip_row = 3 ip_value = 'takes precedence over all defaults' ip_style = lv_style_cambria8red_guid ). + lo_worksheet->set_cell( ip_column = 8 ip_row = 4 ip_value = 'Here: Cambria 8 in red' ip_style = lv_style_cambria8red_guid ). + + +* Set entry into each of the first 10 columns + DO 20 TIMES. + col = sy-index. + CASE col. + WHEN 2 " B + OR 3 " C + OR 6." F + lo_worksheet->set_cell( ip_column = col ip_row = 6 ip_value = 'Times 11' ). + WHEN OTHERS. + lo_worksheet->set_cell( ip_column = col ip_row = 6 ip_value = 'Arial 20' ). + ENDCASE. + ENDDO. + + lo_worksheet->set_cell( ip_column = 2 ip_row = 1 ip_value = space ). " Missing feature "set active cell - use this to simulate that + + + + lo_excel->set_active_sheet_index( 1 ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + + + + + + + + + + + + + + + + REPORT zdemo_excel37. + +TYPE-POOLS: vrm. + +DATA: excel TYPE REF TO zcl_excel, + reader TYPE REF TO zif_excel_reader, + go_error TYPE REF TO cx_root, + gv_memid_gr8 TYPE text255, + gv_message TYPE string, + lv_extension TYPE string, + gv_error_program_name TYPE syrepid, + gv_error_include_name TYPE syrepid, + gv_error_line TYPE i. + +DATA: gc_save_file_name TYPE string VALUE '37- Read template and output.&'. + +SELECTION-SCREEN BEGIN OF BLOCK blx WITH FRAME. +PARAMETERS: p_upfile TYPE string LOWER CASE MEMORY ID gr8. +SELECTION-SCREEN END OF BLOCK blx. + +INCLUDE zdemo_excel_outputopt_incl. + +SELECTION-SCREEN BEGIN OF BLOCK cls WITH FRAME TITLE text-cls. +PARAMETERS: lb_read TYPE seoclsname AS LISTBOX VISIBLE LENGTH 40 LOWER CASE OBLIGATORY DEFAULT 'Autodetect'(001). +PARAMETERS: lb_write TYPE seoclsname AS LISTBOX VISIBLE LENGTH 40 LOWER CASE OBLIGATORY DEFAULT 'Autodetect'(001). +SELECTION-SCREEN END OF BLOCK cls. + +SELECTION-SCREEN BEGIN OF BLOCK bl_err WITH FRAME TITLE text-err. +PARAMETERS: cb_errl AS CHECKBOX DEFAULT 'X'. +SELECTION-SCREEN BEGIN OF LINE. +PARAMETERS: cb_dump AS CHECKBOX DEFAULT space. +SELECTION-SCREEN COMMENT (60) cmt_dump FOR FIELD cb_dump. +SELECTION-SCREEN END OF LINE. +SELECTION-SCREEN END OF BLOCK bl_err. + +INITIALIZATION. + PERFORM setup_listboxes. + cmt_dump = text-dum. + GET PARAMETER ID 'GR8' FIELD gv_memid_gr8. + p_upfile = gv_memid_gr8. + + IF p_upfile IS INITIAL. + p_upfile = 'c:\temp\whatever.xlsx'. + ENDIF. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_upfile. + PERFORM f4_p_upfile CHANGING p_upfile. + + +START-OF-SELECTION. + IF cb_dump IS INITIAL. + TRY. + PERFORM read_template. + PERFORM write_template. +*** Create output + CATCH cx_root INTO go_error. + MESSAGE 'Error reading excelfile' TYPE 'I'. + gv_message = go_error->get_text( ). + IF cb_errl = ' '. + IF gv_message IS NOT INITIAL. + MESSAGE gv_message TYPE 'I'. + ENDIF. + ELSE. + go_error->get_source_position( IMPORTING program_name = gv_error_program_name + include_name = gv_error_include_name + source_line = gv_error_line ). + WRITE:/ 'Errormessage:' ,gv_message. + WRITE:/ 'Errorposition:', + AT /10 'Program:' ,gv_error_program_name, + AT /10 'include_name:' ,gv_error_include_name, + AT /10 'source_line:' ,gv_error_line. + ENDIF. + ENDTRY. + ELSE. " This will dump if an error occurs. In some cases the information given in cx_root is not helpful - this will show exactly where the problem is + PERFORM read_template. + PERFORM write_template. + ENDIF. + + + +*&---------------------------------------------------------------------* +*& Form F4_P_UPFILE +*&---------------------------------------------------------------------* +FORM f4_p_upfile CHANGING p_upfile TYPE string. + + DATA: lv_repid TYPE syrepid, + lt_fields TYPE dynpread_tabtype, + ls_field LIKE LINE OF lt_fields, + lt_files TYPE filetable, + lv_file_filter TYPE string. + + lv_repid = sy-repid. + + CALL FUNCTION 'DYNP_VALUES_READ' + EXPORTING + dyname = lv_repid + dynumb = '1000' + request = 'A' + TABLES + dynpfields = lt_fields + EXCEPTIONS + invalid_abapworkarea = 01 + invalid_dynprofield = 02 + invalid_dynproname = 03 + invalid_dynpronummer = 04 + invalid_request = 05 + no_fielddescription = 06 + undefind_error = 07. + READ TABLE lt_fields INTO ls_field WITH KEY fieldname = 'P_UPFILE'. + p_upfile = ls_field-fieldvalue. + + lv_file_filter = 'Excel Files (*.XLSX;*.XLSM)|*.XLSX;*.XLSM'. + cl_gui_frontend_services=>file_open_dialog( EXPORTING + default_filename = p_upfile + file_filter = lv_file_filter + CHANGING + file_table = lt_files + rc = sy-tabix + EXCEPTIONS + OTHERS = 1 ). + READ TABLE lt_files INDEX 1 INTO p_upfile. + +ENDFORM. " F4_P_UPFILE + + +*&---------------------------------------------------------------------* +*& Form SETUP_LISTBOXES +*&---------------------------------------------------------------------* +FORM setup_listboxes . + + DATA: lv_id TYPE vrm_id, + lt_values TYPE vrm_values, + lt_implementing_classes TYPE seo_relkeys. + + FIELD-SYMBOLS: <ls_implementing_class> LIKE LINE OF lt_implementing_classes, + <ls_value> LIKE LINE OF lt_values. + +*--------------------------------------------------------------------* +* Possible READER-Classes +*--------------------------------------------------------------------* + lv_id = 'LB_READ'. + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = 'Autodetect'(001). + <ls_value>-text = 'Autodetect'(001). + + + PERFORM get_implementing_classds USING 'ZIF_EXCEL_READER' + CHANGING lt_implementing_classes. + CLEAR lt_values. + LOOP AT lt_implementing_classes ASSIGNING <ls_implementing_class>. + + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = <ls_implementing_class>-clsname. + <ls_value>-text = <ls_implementing_class>-clsname. + + ENDLOOP. + + CALL FUNCTION 'VRM_SET_VALUES' + EXPORTING + id = lv_id + values = lt_values + EXCEPTIONS + id_illegal_name = 1 + OTHERS = 2. + +*--------------------------------------------------------------------* +* Possible WRITER-Classes +*--------------------------------------------------------------------* + lv_id = 'LB_WRITE'. + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = 'Autodetect'(001). + <ls_value>-text = 'Autodetect'(001). + + + PERFORM get_implementing_classds USING 'ZIF_EXCEL_WRITER' + CHANGING lt_implementing_classes. + CLEAR lt_values. + LOOP AT lt_implementing_classes ASSIGNING <ls_implementing_class>. + + APPEND INITIAL LINE TO lt_values ASSIGNING <ls_value>. + <ls_value>-key = <ls_implementing_class>-clsname. + <ls_value>-text = <ls_implementing_class>-clsname. + + ENDLOOP. + + CALL FUNCTION 'VRM_SET_VALUES' + EXPORTING + id = lv_id + values = lt_values + EXCEPTIONS + id_illegal_name = 1 + OTHERS = 2. + +ENDFORM. " SETUP_LISTBOXES + + +*&---------------------------------------------------------------------* +*& Form GET_IMPLEMENTING_CLASSDS +*&---------------------------------------------------------------------* +FORM get_implementing_classds USING iv_interface_name TYPE clike + CHANGING ct_implementing_classes TYPE seo_relkeys. + + DATA: lo_oo_interface TYPE REF TO cl_oo_interface, + lo_oo_class TYPE REF TO cl_oo_class, + lt_implementing_subclasses TYPE seo_relkeys. + + FIELD-SYMBOLS: <ls_implementing_class> LIKE LINE OF ct_implementing_classes. + + TRY. + lo_oo_interface ?= cl_oo_interface=>get_instance( iv_interface_name ). + CATCH cx_class_not_existent. + RETURN. + ENDTRY. + ct_implementing_classes = lo_oo_interface->get_implementing_classes( ). + + LOOP AT ct_implementing_classes ASSIGNING <ls_implementing_class>. + TRY. + lo_oo_class ?= cl_oo_class=>get_instance( <ls_implementing_class>-clsname ). + lt_implementing_subclasses = lo_oo_class->get_subclasses( ). + APPEND LINES OF lt_implementing_subclasses TO ct_implementing_classes. + CATCH cx_class_not_existent. + ENDTRY. + ENDLOOP. + + +ENDFORM. " GET_IMPLEMENTING_CLASSDS + + +*&---------------------------------------------------------------------* +*& Form READ_TEMPLATE +*&---------------------------------------------------------------------* +FORM read_template RAISING zcx_excel . + + CASE lb_read. + WHEN 'Autodetect'(001). + FIND REGEX '(\.xlsx|\.xlsm)\s*$' IN p_upfile SUBMATCHES lv_extension. + TRANSLATE lv_extension TO UPPER CASE. + CASE lv_extension. + + WHEN '.XLSX'. + CREATE OBJECT reader TYPE zcl_excel_reader_2007. + excel = reader->load_file( p_upfile ). + "Use template for charts + excel->use_template = abap_true. + + WHEN '.XLSM'. + CREATE OBJECT reader TYPE zcl_excel_reader_xlsm. + excel = reader->load_file( p_upfile ). + "Use template for charts + excel->use_template = abap_true. + + WHEN OTHERS. + MESSAGE 'Unsupported filetype' TYPE 'I'. + RETURN. + + ENDCASE. + + WHEN OTHERS. + CREATE OBJECT reader TYPE (lb_read). + excel = reader->load_file( p_upfile ). + "Use template for charts + excel->use_template = abap_true. + + ENDCASE. + +ENDFORM. " READ_TEMPLATE + + +*&---------------------------------------------------------------------* +*& Form WRITE_TEMPLATE +*&---------------------------------------------------------------------* +FORM write_template RAISING zcx_excel. + + CASE lb_write. + + WHEN 'Autodetect'(001). + FIND REGEX '(\.xlsx|\.xlsm)\s*$' IN p_upfile SUBMATCHES lv_extension. + TRANSLATE lv_extension TO UPPER CASE. + CASE lv_extension. + + WHEN '.XLSX'. + REPLACE '&' IN gc_save_file_name WITH 'xlsx'. " Pass extension for standard writer + lcl_output=>output( excel ). + + WHEN '.XLSM'. + REPLACE '&' IN gc_save_file_name WITH 'xlsm'. " Pass extension for macro-writer + lcl_output=>output( cl_excel = excel + iv_writerclass_name = 'ZCL_EXCEL_WRITER_XLSM' ). + + WHEN OTHERS. + MESSAGE 'Unsupported filetype' TYPE 'I'. + RETURN. + + ENDCASE. + + WHEN OTHERS. + lcl_output=>output( cl_excel = excel + iv_writerclass_name = lb_write ). + ENDCASE. + +ENDFORM. " WRITE_TEMPLATE + + + + + + + + + REPORT. + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_drawing TYPE REF TO zcl_excel_drawing. + +TYPES: BEGIN OF gty_icon, +* name TYPE icon_name, "Fix #228 + name TYPE iconname, "Fix #228 + objid TYPE w3objid, + END OF gty_icon, + gtyt_icon TYPE STANDARD TABLE OF gty_icon WITH NON-UNIQUE DEFAULT KEY. + +DATA: lt_icon TYPE gtyt_icon, + lv_row TYPE sytabix, + ls_wwwdatatab TYPE wwwdatatab, + lt_mimedata TYPE STANDARD TABLE OF w3mime WITH NON-UNIQUE DEFAULT KEY, + lv_xstring TYPE xstring. + +FIELD-SYMBOLS: <icon> LIKE LINE OF lt_icon, + <mimedata> LIKE LINE OF lt_mimedata. + +CONSTANTS: gc_save_file_name TYPE string VALUE '38_SAP-Icons.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +TABLES: icon. +SELECT-OPTIONS: s_icon FOR icon-name DEFAULT 'ICON_LED_*' OPTION CP. + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo Icons' ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'A' ). + lo_column_dimension->set_auto_size( 'X' ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( 'X' ). + +* Get all icons + SELECT name + INTO TABLE lt_icon + FROM icon + WHERE name IN s_icon + ORDER BY name. + LOOP AT lt_icon ASSIGNING <icon>. + + lv_row = sy-tabix. +*--------------------------------------------------------------------* +* Set name of icon +*--------------------------------------------------------------------* + lo_worksheet->set_cell( ip_row = lv_row + ip_column = 'A' + ip_value = <icon>-name ). +*--------------------------------------------------------------------* +* Check whether the mime-repository holds some icondata for us +*--------------------------------------------------------------------* + +* Get key + SELECT SINGLE objid + INTO <icon>-objid + FROM wwwdata + WHERE text = <icon>-name. + CHECK sy-subrc = 0. " :o( + lo_worksheet->set_cell( ip_row = lv_row + ip_column = 'B' + ip_value = <icon>-objid ). + +* Load mimedata + CLEAR lt_mimedata. + CLEAR ls_wwwdatatab. + ls_wwwdatatab-relid = 'MI' . + ls_wwwdatatab-objid = <icon>-objid. + CALL FUNCTION 'WWWDATA_IMPORT' + EXPORTING + key = ls_wwwdatatab + TABLES + mime = lt_mimedata + EXCEPTIONS + wrong_object_type = 1 + import_error = 2 + OTHERS = 3. + CHECK sy-subrc = 0. " :o( + + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = lv_row + ip_from_col = 'C' ). + CLEAR lv_xstring. + LOOP AT lt_mimedata ASSIGNING <mimedata>. + CONCATENATE lv_xstring <mimedata>-line INTO lv_xstring IN BYTE MODE. + ENDLOOP. + + lo_drawing->set_media( ip_media = lv_xstring + ip_media_type = zcl_excel_drawing=>c_media_type_jpg + ip_width = 16 + ip_height = 14 ). + lo_worksheet->add_drawing( lo_drawing ). + + ENDLOOP. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL16 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel39. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_drawing TYPE REF TO zcl_excel_drawing. + +DATA lv_value TYPE i. + +DATA: ls_io TYPE skwf_io. + +DATA: ls_upper TYPE zexcel_drawing_location, + ls_lower TYPE zexcel_drawing_location. + +DATA: lo_bar1 TYPE REF TO zcl_excel_graph_bars, + lo_bar1_stacked TYPE REF TO zcl_excel_graph_bars, + lo_bar2 TYPE REF TO zcl_excel_graph_bars, + lo_pie TYPE REF TO zcl_excel_graph_pie, + lo_line TYPE REF TO zcl_excel_graph_line. + +CONSTANTS: gc_save_file_name TYPE string VALUE '39_Charts.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + + " Create a pie chart and series + CREATE OBJECT lo_pie. + + CALL METHOD lo_pie->create_serie + EXPORTING + ip_order = 0 + ip_sheet = 'Values' + ip_lbl_from_col = 'B' + ip_lbl_from_row = '1' + ip_lbl_to_col = 'B' + ip_lbl_to_row = '3' + ip_ref_from_col = 'A' + ip_ref_from_row = '1' + ip_ref_to_col = 'A' + ip_ref_to_row = '3' + ip_sername = 'My serie 1'. + + " Set style + lo_pie->set_style( zcl_excel_graph=>c_style_15 ). + + " Create a bar chart, series and axes + CREATE OBJECT lo_bar1. + + CALL METHOD lo_bar1->create_serie + EXPORTING + ip_order = 0 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_no + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_bar1->create_serie + EXPORTING + ip_order = 1 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_no + ip_lbl = 'Values!$B$1:$B$3' + ip_ref = 'Values!$A$1:$A$3' + ip_sername = 'My serie 2'. + + CALL METHOD lo_bar1->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_catax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + CALL METHOD lo_bar1->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_valax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + " Set style + lo_bar1->set_style( zcl_excel_graph=>c_style_default ). + + " Set label to none + lo_bar1->set_print_lbl( zcl_excel_graph_bars=>c_show_false ). + +* Same barchart - but this time stacked + CREATE OBJECT lo_bar1_stacked. + + CALL METHOD lo_bar1_stacked->create_serie + EXPORTING + ip_order = 0 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_no + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_bar1_stacked->create_serie + EXPORTING + ip_order = 1 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_no + ip_lbl = 'Values!$B$1:$B$3' + ip_ref = 'Values!$A$1:$A$3' + ip_sername = 'My serie 2'. + + CALL METHOD lo_bar1_stacked->create_ax + EXPORTING + ip_type = zcl_excel_graph_bars=>c_catax . + + CALL METHOD lo_bar1_stacked->create_ax + EXPORTING + ip_type = zcl_excel_graph_bars=>c_valax. + + " Set style + lo_bar1_stacked->set_style( zcl_excel_graph=>c_style_default ). + + " Set label to none + lo_bar1_stacked->set_print_lbl( zcl_excel_graph_bars=>c_show_false ). + + " Make it stacked + lo_bar1_stacked->ns_groupingval = zcl_excel_graph_bars=>c_groupingval_stacked. + + + " Create a bar chart, series and axes + CREATE OBJECT lo_bar2. + + CALL METHOD lo_bar2->create_serie + EXPORTING + ip_order = 0 + ip_invertifnegative = zcl_excel_graph_bars=>c_invertifnegative_yes + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_bar2->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_catax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + CALL METHOD lo_bar2->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_bars=>c_valax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + " Set layout + lo_bar2->set_show_legend_key( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_values( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_cat_name( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_ser_name( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_show_percent( zcl_excel_graph_bars=>c_show_true ). + lo_bar2->set_varycolor( zcl_excel_graph_bars=>c_show_true ). + + " Create a line chart, series and axes + CREATE OBJECT lo_line. + + CALL METHOD lo_line->create_serie + EXPORTING + ip_order = 0 + ip_symbol = zcl_excel_graph_line=>c_symbol_auto + ip_smooth = zcl_excel_graph_line=>c_show_false + ip_lbl = 'Values!$D$1:$D$3' + ip_ref = 'Values!$C$1:$C$3' + ip_sername = 'My serie 1'. + + CALL METHOD lo_line->create_serie + EXPORTING + ip_order = 1 + ip_symbol = zcl_excel_graph_line=>c_symbol_none + ip_smooth = zcl_excel_graph_line=>c_show_false + ip_lbl = 'Values!$B$1:$B$3' + ip_ref = 'Values!$A$1:$A$3' + ip_sername = 'My serie 2'. + + CALL METHOD lo_line->create_serie + EXPORTING + ip_order = 2 + ip_symbol = zcl_excel_graph_line=>c_symbol_auto + ip_smooth = zcl_excel_graph_line=>c_show_false + ip_lbl = 'Values!$F$1:$F$3' + ip_ref = 'Values!$E$1:$E$3' + ip_sername = 'My serie 3'. + + CALL METHOD lo_line->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_line=>c_catax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + CALL METHOD lo_line->create_ax + EXPORTING +* ip_axid = + ip_type = zcl_excel_graph_line=>c_valax +* ip_orientation = +* ip_delete = +* ip_axpos = +* ip_formatcode = +* ip_sourcelinked = +* ip_majortickmark = +* ip_minortickmark = +* ip_ticklblpos = +* ip_crossax = +* ip_crosses = +* ip_auto = +* ip_lblalgn = +* ip_lbloffset = +* ip_nomultilvllbl = +* ip_crossbetween = + . + + + + + + + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet (Pie sheet) + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( 'PieChart' ). + + " Create global drawing, set type as pie chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART PIE' ). + lo_drawing->graph = lo_pie. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_pie. + + "Set chart position (anchor 2 cells) + ls_lower-row = 30. + ls_lower-col = 20. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " BarChart1 sheet + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'BarChart1' ). + + " Create global drawing, set type as bar chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART BARS WITH 2 SERIES' ). + lo_drawing->graph = lo_bar1. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_bars. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 11. + ls_lower-row = 22. + ls_lower-col = 21. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'Stacked CHART BARS WITH 2 SER.' ). + lo_drawing->graph = lo_bar1_stacked. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_bars. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 1. + ls_lower-row = 22. + ls_lower-col = 10. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " BarChart2 sheet + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'BarChart2' ). + + " Create global drawing, set type as bar chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART BARS WITH 1 SERIE' ). + lo_drawing->graph = lo_bar2. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_bars. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 0. + ls_lower-row = 30. + ls_lower-col = 20. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " LineChart sheet + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'LineChart' ). + + " Create global drawing, set type as line chart, assign chart, set position and media type + lo_drawing = lo_worksheet->excel->add_new_drawing( + ip_type = zcl_excel_drawing=>type_chart + ip_title = 'CHART LINES' ). + lo_drawing->graph = lo_line. + lo_drawing->graph_type = zcl_excel_drawing=>c_graph_line. + + "Set chart position (anchor 2 cells) + ls_upper-row = 0. + ls_upper-col = 0. + ls_lower-row = 30. + ls_lower-col = 20. + lo_drawing->set_position2( + EXPORTING + ip_from = ls_upper + ip_to = ls_lower ). + + lo_drawing->set_media( + EXPORTING + ip_media_type = zcl_excel_drawing=>c_media_type_xml ). + + lo_worksheet->add_drawing( lo_drawing ). + + " Values sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for chart + lv_value = 1. + lo_worksheet->set_cell( ip_column = 'A' ip_row = 1 ip_value = lv_value ). + lv_value = 2. + lo_worksheet->set_cell( ip_column = 'A' ip_row = 2 ip_value = lv_value ). + lv_value = 3. + lo_worksheet->set_cell( ip_column = 'A' ip_row = 3 ip_value = lv_value ). + + " Set labels for chart + lo_worksheet->set_cell( ip_column = 'B' ip_row = 1 ip_value = 'One' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Two' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'Three' ). + + " Set values for chart + lv_value = 3. + lo_worksheet->set_cell( ip_column = 'C' ip_row = 1 ip_value = lv_value ). + lv_value = 2. + lo_worksheet->set_cell( ip_column = 'C' ip_row = 2 ip_value = lv_value ). + lv_value = -1. + lo_worksheet->set_cell( ip_column = 'C' ip_row = 3 ip_value = lv_value ). + + " Set labels for chart + lo_worksheet->set_cell( ip_column = 'D' ip_row = 3 ip_value = 'One (Minus)' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 2 ip_value = 'Two' ). + lo_worksheet->set_cell( ip_column = 'D' ip_row = 1 ip_value = 'Three' ). + + " Set values for chart + lv_value = 3. + lo_worksheet->set_cell( ip_column = 'E' ip_row = 1 ip_value = lv_value ). + lv_value = 1. + lo_worksheet->set_cell( ip_column = 'E' ip_row = 2 ip_value = lv_value ). + lv_value = 2. + lo_worksheet->set_cell( ip_column = 'E' ip_row = 3 ip_value = lv_value ). + + " Set labels for chart + lo_worksheet->set_cell( ip_column = 'F' ip_row = 3 ip_value = 'Two' ). + lo_worksheet->set_cell( ip_column = 'F' ip_row = 2 ip_value = 'One' ). + lo_worksheet->set_cell( ip_column = 'F' ip_row = 1 ip_value = 'Three' ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL4 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel4. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + + lo_hyperlink TYPE REF TO zcl_excel_hyperlink, + + lv_tabcolor TYPE zexcel_s_tabcolor, + + ls_header TYPE zexcel_s_worksheet_head_foot, + ls_footer TYPE zexcel_s_worksheet_head_foot. + +CONSTANTS: gc_save_file_name TYPE string VALUE '04_Sheets.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet1' ). + lo_worksheet->zif_excel_sheet_properties~selected = zif_excel_sheet_properties=>c_selected. + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the first sheet' ). +* Set color to tab with sheetname - Red + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = 'FF' + ip_green = '00' + ip_blu = '00' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet2!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to second sheet' ip_hyperlink = lo_hyperlink ). + + " Page printing settings + lo_worksheet->sheet_setup->set_page_margins( ip_header = '1' ip_footer = '1' ip_unit = 'cm' ). + lo_worksheet->sheet_setup->black_and_white = 'X'. + lo_worksheet->sheet_setup->fit_to_page = 'X'. " you should turn this on to activate fit_to_height and fit_to_width + lo_worksheet->sheet_setup->fit_to_height = 0. " used only if ip_fit_to_page = 'X' + lo_worksheet->sheet_setup->fit_to_width = 2. " used only if ip_fit_to_page = 'X' + lo_worksheet->sheet_setup->orientation = zcl_excel_sheet_setup=>c_orientation_landscape. + lo_worksheet->sheet_setup->page_order = zcl_excel_sheet_setup=>c_ord_downthenover. + lo_worksheet->sheet_setup->paper_size = zcl_excel_sheet_setup=>c_papersize_a4. + lo_worksheet->sheet_setup->scale = 80. " used only if ip_fit_to_page = SPACE + + " Header and Footer + ls_header-right_value = 'print date &D'. + ls_header-right_font-size = 8. + ls_header-right_font-name = zcl_excel_style_font=>c_name_arial. + + ls_footer-left_value = '&Z&F'. "Path / Filename + ls_footer-left_font = ls_header-right_font. + ls_footer-right_value = 'page &P of &N'. "page x of y + ls_footer-right_font = ls_header-right_font. + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet2' ). +* Set color to tab with sheetname - Green + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = '00' + ip_green = 'FF' + ip_blu = '00' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + lo_worksheet->zif_excel_sheet_properties~selected = zif_excel_sheet_properties=>c_selected. + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'This is the second sheet' ). + lo_hyperlink = zcl_excel_hyperlink=>create_internal_link( iv_location = 'Sheet1!B2' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 'This is link to first sheet' ip_hyperlink = lo_hyperlink ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 4 ip_value = 'Sheet3 is hidden' ). + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet3' ). +* Set color to tab with sheetname - Blue + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = '00' + ip_green = '00' + ip_blu = 'FF' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + lo_worksheet->zif_excel_sheet_properties~hidden = zif_excel_sheet_properties=>c_hidden. + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Sheet4' ). +* Set color to tab with sheetname - other color + lv_tabcolor-rgb = zcl_excel_style_color=>create_new_argb( ip_red = '00' + ip_green = 'FF' + ip_blu = 'FF' ). + lo_worksheet->set_tabcolor( lv_tabcolor ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Cell B3 has value 0' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 3 ip_value = 0 ). + lo_worksheet->zif_excel_sheet_properties~show_zeros = zif_excel_sheet_properties=>c_hidezero. + + lo_worksheet->sheet_setup->set_header_footer( ip_odd_header = ls_header + ip_odd_footer = ls_footer ). + + lo_excel->set_active_sheet_index_by_name( 'Sheet1' ). + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + REPORT. + + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lv_row TYPE zexcel_cell_row, + lv_col TYPE i, + lv_row_char TYPE char10, + lv_value TYPE string, + ls_fontcolor TYPE zexcel_style_color_argb. + +CONSTANTS: gc_save_file_name TYPE string VALUE '40_Printsettings.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + + +START-OF-SELECTION. + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo Printsettings' ). + +*--------------------------------------------------------------------* +* Prepare sheet with trivial data +* - first 4 columns will have fontocolor set +* - first 3 rows will have fontcolor set +* These marked cells will be used for repeatable rows/columns on printpages +*--------------------------------------------------------------------* + DO 100 TIMES. " Rows + + lv_row = sy-index . + WRITE lv_row TO lv_row_char. + + DO 20 TIMES. + + lv_col = sy-index - 1. + CONCATENATE sy-abcde+lv_col(1) lv_row_char INTO lv_value. + lv_col = sy-index. + lo_worksheet->set_cell( ip_row = lv_row + ip_column = lv_col + ip_value = lv_value ). + + TRY. + IF lv_row <= 3. + lo_worksheet->change_cell_style( ip_column = lv_col + ip_row = lv_row + ip_fill_filltype = zcl_excel_style_fill=>c_fill_solid + ip_fill_fgcolor_rgb = zcl_excel_style_color=>c_yellow ). + ENDIF. + IF lv_col <= 4. + lo_worksheet->change_cell_style( ip_column = lv_col + ip_row = lv_row + ip_font_color_rgb = zcl_excel_style_color=>c_red ). + ENDIF. + CATCH zcx_excel . + ENDTRY. + + ENDDO. + + + + ENDDO. + + +*--------------------------------------------------------------------* +* Printsettings +*--------------------------------------------------------------------* + TRY. + lo_worksheet->zif_excel_sheet_printsettings~set_print_repeat_columns( iv_columns_from = 'A' + iv_columns_to = 'D' ). + lo_worksheet->zif_excel_sheet_printsettings~set_print_repeat_rows( iv_rows_from = 1 + iv_rows_to = 3 ). + CATCH zcx_excel . + ENDTRY. + + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL5 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel5. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional. + +DATA: ls_iconset TYPE zexcel_conditional_iconset. + + + +CONSTANTS: gc_save_file_name TYPE string VALUE '05_Conditional.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + + + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights2. + ls_iconset-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo1_value = '0'. + ls_iconset-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo2_value = '33'. + ls_iconset-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset-cfvo3_value = '66'. + ls_iconset-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + lo_style_conditional->mode_iconset = ls_iconset. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 4 + ip_stop_column = 'C' + ip_stop_row = 8 ). + + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 100 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 1000 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 150 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 500 ). + + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights2. + ls_iconset-showvalue = zcl_excel_style_conditional=>c_showvalue_false. + lo_style_conditional->mode_iconset = ls_iconset. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 4 + ip_stop_column = 'E' + ip_stop_row = 8 ). + + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = 100 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'E' ip_value = 1000 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'E' ip_value = 150 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'E' ip_value = 500 ). + + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_style_green TYPE REF TO zcl_excel_style, + lo_style_yellow TYPE REF TO zcl_excel_style, + lo_style_red TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional, + lv_style_title_guid TYPE zexcel_cell_style, + lv_style_green_guid TYPE zexcel_cell_style, + lv_style_yellow_guid TYPE zexcel_cell_style, + lv_style_red_guid TYPE zexcel_cell_style, + ls_cellis TYPE zexcel_conditional_cellis, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_value = 'Total score' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 10 ip_formula = 'SUM(C7:C8)' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + +* ls_key-relid = 'MI'. +* ls_key-objid = 'WBLOGO'. +* lo_drawing->set_media_www( ip_key = ls_key +* ip_width = 140 +* ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " defne conditional styles + lo_style_green = lo_excel->add_new_style( ). + lo_style_green->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_green->fill->bgcolor-rgb = zcl_excel_style_color=>c_green. + lv_style_green_guid = lo_style_green->get_guid( ). + + lo_style_yellow = lo_excel->add_new_style( ). + lo_style_yellow->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_yellow->fill->bgcolor-rgb = zcl_excel_style_color=>c_yellow. + lv_style_yellow_guid = lo_style_yellow->get_guid( ). + + lo_style_red = lo_excel->add_new_style( ). + lo_style_red->fill->filltype = zcl_excel_style_fill=>c_fill_solid. + lo_style_red->fill->bgcolor-rgb = zcl_excel_style_color=>c_red. + lv_style_red_guid = lo_style_red->get_guid( ). + + " add conditional formatting + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_green_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 1. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '5'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_equal. + ls_cellis-cell_style = lv_style_yellow_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_cellis. + ls_cellis-formula = '0'. + ls_cellis-operator = zcl_excel_style_conditional=>c_operator_greaterthan. + ls_cellis-cell_style = lv_style_red_guid. + lo_style_conditional->mode_cellis = ls_cellis. + lo_style_conditional->priority = 3. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 10 + ip_stop_column = 'C' + ip_stop_row = 10 ). + + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + lo_worksheet->set_cell( ip_column = 'B' ip_row = 10 ip_value = 'Total score' ). + lo_worksheet->set_cell( ip_column = 'C' ip_row = 10 ip_formula = 'SUM(C7:C8)' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " add autosize (column width) + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'B' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + lo_column_dimension = lo_worksheet->get_column_dimension( ip_column = 'C' ). + lo_column_dimension->set_auto_size( ip_auto_size = abap_true ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 7 ip_value = 'Is abap2xlsx simple' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 8 ip_value = 'Is abap2xlsx CooL' ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " add data validation + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 7. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Select a value' ). + + + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = 'Values'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Select a value' ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lo_range TYPE REF TO zcl_excel_range, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Add new sheet + lo_worksheet = lo_excel->add_new_worksheet( ). + lo_worksheet->set_title( ip_title = 'Values' ). + + " Set values for range + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 1 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 2 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 3 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 4 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 5 ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'Values'. + lo_range->set_value( ip_sheet_name = 'Values' + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 8 ). + + lo_excel->set_active_sheet_index( 1 ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lo_drawing TYPE REF TO zcl_excel_drawing, + lv_style_title_guid TYPE zexcel_cell_style, + ls_key TYPE wwwdatatab. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + + " add logo from SMWO + lo_drawing = lo_excel->add_new_drawing( ). + lo_drawing->set_position( ip_from_row = 2 + ip_from_col = 'B' ). + + ls_key-relid = 'MI'. + ls_key-objid = 'WBLOGO'. + lo_drawing->set_media_www( ip_key = ls_key + ip_width = 140 + ip_height = 64 ). + + " assign drawing to the worksheet + lo_worksheet->add_drawing( lo_drawing ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED2 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched2. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lo_style_title TYPE REF TO zcl_excel_style, + lv_style_title_guid TYPE zexcel_cell_style. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Styles + lo_style_title = lo_excel->add_new_style( ). + lo_style_title->font->bold = abap_true. + lo_style_title->font->color-rgb = zcl_excel_style_color=>c_blue. + lv_style_title_guid = lo_style_title->get_guid( ). + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo TechEd' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 5 ip_value = 'TechEd demo' ip_style = lv_style_title_guid ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL6 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel6. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lv_row TYPE syindex, + lv_formula TYPE string. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '06_Formulas.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + +*--------------------------------------------------------------------* +* Get some testdata +*--------------------------------------------------------------------* + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 100 ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 1000 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 150 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = -10 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 500 ). + + +*--------------------------------------------------------------------* +* Demonstrate using formulas +*--------------------------------------------------------------------* + lo_worksheet->set_cell( ip_row = 9 ip_column = 'C' ip_formula = 'SUM(C4:C8)' ). + + +*--------------------------------------------------------------------* +* Demonstrate standard EXCEL-behaviour when copying a formula to another cell +* by calculating the resulting formula to put into another cell +*--------------------------------------------------------------------* + DO 10 TIMES. + + lv_formula = zcl_excel_common=>shift_formula( iv_reference_formula = 'SUM(C4:C8)' + iv_shift_cols = 0 " Offset in Columns - here we copy in same column --> 0 + iv_shift_rows = sy-index ). " Offset in Row - here we copy downward --> sy-index + lv_row = 9 + sy-index. " Absolute row = sy-index rows below reference cell + lo_worksheet->set_cell( ip_row = lv_row ip_column = 'C' ip_formula = lv_formula ). + + ENDDO. + +*--------------------------------------------------------------------* +*** Create output +*--------------------------------------------------------------------* + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL7 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel7. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_style_conditional TYPE REF TO zcl_excel_style_conditional. + +DATA: ls_iconset3 TYPE zexcel_conditional_iconset, + ls_iconset4 TYPE zexcel_conditional_iconset, + ls_iconset5 TYPE zexcel_conditional_iconset, + ls_databar TYPE zexcel_conditional_databar, + ls_colorscale2 TYPE zexcel_conditional_colorscale, + ls_colorscale3 TYPE zexcel_conditional_colorscale. + +CONSTANTS: gc_save_file_name TYPE string VALUE '07_ConditionalAll.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + ls_iconset3-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset3-cfvo1_value = '0'. + ls_iconset3-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset3-cfvo2_value = '33'. + ls_iconset3-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset3-cfvo3_value = '66'. + ls_iconset3-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + ls_iconset4-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo1_value = '0'. + ls_iconset4-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo2_value = '25'. + ls_iconset4-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo3_value = '50'. + ls_iconset4-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset4-cfvo4_value = '75'. + ls_iconset4-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + ls_iconset5-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo1_value = '0'. + ls_iconset5-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo2_value = '20'. + ls_iconset5-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo3_value = '40'. + ls_iconset5-cfvo4_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo4_value = '60'. + ls_iconset5-cfvo5_type = zcl_excel_style_conditional=>c_cfvo_type_percent. + ls_iconset5-cfvo5_value = '80'. + ls_iconset5-showvalue = zcl_excel_style_conditional=>c_showvalue_true. + + ls_databar-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_min. + ls_databar-cfvo1_value = '0'. + ls_databar-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_max. + ls_databar-cfvo2_value = '0'. + ls_databar-colorrgb = 'FF638EC6'. + + ls_colorscale2-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_min. + ls_colorscale2-cfvo1_value = '0'. + ls_colorscale2-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percentile. + ls_colorscale2-cfvo2_value = '50'. + ls_colorscale2-colorrgb1 = 'FFF8696B'. + ls_colorscale2-colorrgb2 = 'FF63BE7B'. + + ls_colorscale3-cfvo1_type = zcl_excel_style_conditional=>c_cfvo_type_min. + ls_colorscale3-cfvo1_value = '0'. + ls_colorscale3-cfvo2_type = zcl_excel_style_conditional=>c_cfvo_type_percentile. + ls_colorscale3-cfvo2_value = '50'. + ls_colorscale3-cfvo3_type = zcl_excel_style_conditional=>c_cfvo_type_max. + ls_colorscale3-cfvo3_value = '0'. + ls_colorscale3-colorrgb1 = 'FFF8696B'. + ls_colorscale3-colorrgb2 = 'FFFFEB84'. + ls_colorscale3-colorrgb3 = 'FF63BE7B'. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + +* ICONSET + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3arrows. + + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 5 + ip_stop_column = 'B' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'C_ICONSET_3ARROWS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3arrowsgray. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 5 + ip_stop_column = 'C' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'C_ICONSET_3ARROWSGRAY' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'C' ip_value = 50 ). + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3flags. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 5 + ip_stop_column = 'D' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'C_ICONSET_3FLAGS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 5 + ip_stop_column = 'E' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = 'C_ICONSET_3TRAFFICLIGHTS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'E' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'E' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'E' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'E' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3trafficlights2. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'F' + ip_start_row = 5 + ip_stop_column = 'F' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'F' ip_value = 'C_ICONSET_3TRAFFICLIGHTS2' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'F' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'F' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'F' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'F' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'F' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3signs. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'G' + ip_start_row = 5 + ip_stop_column = 'G' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'G' ip_value = 'C_ICONSET_3SIGNS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'G' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'G' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'G' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'G' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'G' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3symbols. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'H' + ip_start_row = 5 + ip_stop_column = 'H' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'H' ip_value = 'C_ICONSET_3SYMBOLS' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'H' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'H' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'H' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'H' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'H' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset3-iconset = zcl_excel_style_conditional=>c_iconset_3symbols2. + lo_style_conditional->mode_iconset = ls_iconset3. + lo_style_conditional->set_range( ip_start_column = 'I' + ip_start_row = 5 + ip_stop_column = 'I' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'I' ip_value = 'C_ICONSET_3SYMBOLS2' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'I' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'I' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'I' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'I' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'I' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4arrows. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 12 + ip_stop_column = 'B' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'B' ip_value = 'C_ICONSET_4ARROWS' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4arrowsgray. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 12 + ip_stop_column = 'C' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'C' ip_value = 'C_ICONSET_4ARROWSGRAY' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'C' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4redtoblack. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 12 + ip_stop_column = 'D' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'D' ip_value = 'C_ICONSET_4REDTOBLACK' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4rating. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 12 + ip_stop_column = 'E' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'E' ip_value = 'C_ICONSET_4RATING' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'E' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'E' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'E' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'E' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'E' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset4-iconset = zcl_excel_style_conditional=>c_iconset_4trafficlights. + lo_style_conditional->mode_iconset = ls_iconset4. + lo_style_conditional->set_range( ip_start_column = 'F' + ip_start_row = 12 + ip_stop_column = 'F' + ip_stop_row = 16 ). + + lo_worksheet->set_cell( ip_row = 11 ip_column = 'F' ip_value = 'C_ICONSET_4TRAFFICLIGHTS' ). + lo_worksheet->set_cell( ip_row = 12 ip_column = 'F' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 13 ip_column = 'F' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 14 ip_column = 'F' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 15 ip_column = 'F' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 16 ip_column = 'F' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5arrows. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 19 + ip_stop_column = 'B' + ip_stop_row = 23 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'B' ip_value = 'C_ICONSET_5ARROWS' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5arrowsgray. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 19 + ip_stop_column = 'C' + ip_stop_row = 23 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'C' ip_value = 'C_ICONSET_5ARROWSGRAY' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'C' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5rating. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 19 + ip_stop_column = 'D' + ip_stop_row = 23 ). + + lo_worksheet->set_cell( ip_row = 18 ip_column = 'D' ip_value = 'C_ICONSET_5RATING' ). + lo_worksheet->set_cell( ip_row = 19 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 20 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 21 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 22 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 23 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_iconset. + lo_style_conditional->priority = 1. + ls_iconset5-iconset = zcl_excel_style_conditional=>c_iconset_5quarters. + lo_style_conditional->mode_iconset = ls_iconset5. + lo_style_conditional->set_range( ip_start_column = 'E' + ip_start_row = 19 + ip_stop_column = 'E' + ip_stop_row = 23 ). + +* DATABAR + + lo_worksheet->set_cell( ip_row = 25 ip_column = 'B' ip_value = 'DATABAR' ). + lo_worksheet->set_cell( ip_row = 26 ip_column = 'B' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 27 ip_column = 'B' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 28 ip_column = 'B' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 29 ip_column = 'B' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 30 ip_column = 'B' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_databar. + lo_style_conditional->priority = 1. + lo_style_conditional->mode_databar = ls_databar. + lo_style_conditional->set_range( ip_start_column = 'B' + ip_start_row = 26 + ip_stop_column = 'B' + ip_stop_row = 30 ). + +* COLORSCALE + + lo_worksheet->set_cell( ip_row = 25 ip_column = 'C' ip_value = 'COLORSCALE 2 COLORS' ). + lo_worksheet->set_cell( ip_row = 26 ip_column = 'C' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 27 ip_column = 'C' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 28 ip_column = 'C' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 29 ip_column = 'C' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 30 ip_column = 'C' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_colorscale. + lo_style_conditional->priority = 1. + lo_style_conditional->mode_colorscale = ls_colorscale2. + lo_style_conditional->set_range( ip_start_column = 'C' + ip_start_row = 26 + ip_stop_column = 'C' + ip_stop_row = 30 ). + + + lo_worksheet->set_cell( ip_row = 25 ip_column = 'D' ip_value = 'COLORSCALE 3 COLORS' ). + lo_worksheet->set_cell( ip_row = 26 ip_column = 'D' ip_value = 10 ). + lo_worksheet->set_cell( ip_row = 27 ip_column = 'D' ip_value = 20 ). + lo_worksheet->set_cell( ip_row = 28 ip_column = 'D' ip_value = 30 ). + lo_worksheet->set_cell( ip_row = 29 ip_column = 'D' ip_value = 40 ). + lo_worksheet->set_cell( ip_row = 30 ip_column = 'D' ip_value = 50 ). + + lo_style_conditional = lo_worksheet->add_new_conditional_style( ). + lo_style_conditional->rule = zcl_excel_style_conditional=>c_rule_colorscale. + lo_style_conditional->priority = 1. + lo_style_conditional->mode_colorscale = ls_colorscale3. + lo_style_conditional->set_range( ip_start_column = 'D' + ip_start_row = 26 + ip_stop_column = 'D' + ip_stop_row = 30 ). + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL8 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel8. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range. + +DATA: lv_title TYPE zexcel_sheet_title. + +CONSTANTS: gc_save_file_name TYPE string VALUE '08_Range.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + + +START-OF-SELECTION. + + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lv_title = 'Sheet1'. + lo_worksheet->set_title( lv_title ). + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'range'. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'C' + ip_start_row = 4 + ip_stop_column = 'C' + ip_stop_row = 8 ). + + + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'Apple' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 'Banana' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 'Blueberry' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Ananas' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Grapes' ). + + " Define another Range with a name longer than 40 characters that + " tests the fix of issue #168 ranges namescan be only up to 20 chars + + lo_range = lo_excel->add_new_range( ). + lo_range->name = 'A_range_with_a_name_that_is_longer_than_20_characters'. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'D' + ip_start_row = 4 + ip_stop_column = 'D' + ip_stop_row = 5 ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'Range Value 1' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 'Range Value 2' ). + + " issue #163 + " Define another Range with sheet visibility + lo_range = lo_worksheet->add_new_range( ). + lo_range->name = 'A_range_with_sheet_visibility'. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'E' + ip_start_row = 4 + ip_stop_column = 'E' + ip_stop_row = 5 ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'E' ip_value = 'Range Value 3' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'E' ip_value = 'Range Value 4' ). + " issue #163 + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_EXCEL9 +*& +*&---------------------------------------------------------------------* +*& abap2xlsx Demo: Data validations +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_excel9. + +CONSTANTS: c_fruits TYPE string VALUE 'Fruits', + c_vegetables TYPE string VALUE 'Vegetables', + c_meat TYPE string VALUE 'Meat', + c_fish TYPE string VALUE 'Fish'. + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_worksheet TYPE REF TO zcl_excel_worksheet, + lo_range TYPE REF TO zcl_excel_range, + lo_data_validation TYPE REF TO zcl_excel_data_validation. + +DATA: row TYPE zexcel_cell_row. + + +DATA: lv_title TYPE zexcel_sheet_title. + + +CONSTANTS: gc_save_file_name TYPE string VALUE '09_DataValidation.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +PARAMETERS: p_sbook TYPE flag. + + +START-OF-SELECTION. + + " Creates active sheet + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lv_title = 'Data Validation'. + lo_worksheet->set_title( lv_title ). + " Set values for dropdown + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = c_fish ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 'Anchovy' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = 'Carp' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'A' ip_value = 'Catfish' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 'Cod' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 'Eel' ). + lo_worksheet->set_cell( ip_row = 9 ip_column = 'A' ip_value = 'Haddock' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_fish. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'A' + ip_start_row = 4 + ip_stop_column = 'A' + ip_stop_row = 9 ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'B' ip_value = c_meat ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'B' ip_value = 'Pork' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'B' ip_value = 'Beef' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'B' ip_value = 'Chicken' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'B' ip_value = 'Turkey' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_meat. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'B' + ip_start_row = 4 + ip_stop_column = 'B' + ip_stop_row = 7 ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'C' ip_value = c_fruits ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'C' ip_value = 'Apple' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'C' ip_value = 'Banana' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'C' ip_value = 'Blueberry' ). + lo_worksheet->set_cell( ip_row = 7 ip_column = 'C' ip_value = 'Ananas' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'C' ip_value = 'Grapes' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_fruits. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'C' + ip_start_row = 4 + ip_stop_column = 'C' + ip_stop_row = 8 ). + + lo_worksheet->set_cell( ip_row = 2 ip_column = 'D' ip_value = c_vegetables ). + lo_worksheet->set_cell( ip_row = 4 ip_column = 'D' ip_value = 'Cucumber' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'D' ip_value = 'Sweet pepper ' ). + lo_worksheet->set_cell( ip_row = 6 ip_column = 'D' ip_value = 'Lettuce' ). + + lo_range = lo_excel->add_new_range( ). + lo_range->name = c_vegetables. + lo_range->set_value( ip_sheet_name = lv_title + ip_start_column = 'D' + ip_start_row = 4 + ip_stop_column = 'D' + ip_stop_row = 6 ). + + lo_worksheet = lo_excel->add_new_worksheet( ). + lv_title = 'Table with Data Validation'. + lo_worksheet->set_title( lv_title ). + + " Maximum Text length + lo_worksheet->set_cell( ip_row = 1 ip_column = 'A' ip_value = 'Validate Maximum Text length of <= 10 in Cell A2:' ). + lo_worksheet->set_cell( ip_row = 2 ip_column = 'A' ip_value = 'abcdefghij' ). + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_textlength. + lo_data_validation->operator = zcl_excel_data_validation=>c_operator_lessthanorequal. + lo_data_validation->formula1 = 10. + lo_data_validation->cell_row = 2. + lo_data_validation->cell_column = 'A'. + + " Integer Value between 1 and 10 + lo_worksheet->set_cell( ip_row = 4 ip_column = 'A' ip_value = 'Validate Integer Value between 1 and 10 in Cell A5:' ). + lo_worksheet->set_cell( ip_row = 5 ip_column = 'A' ip_value = '5' ). + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_whole. + lo_data_validation->operator = zcl_excel_data_validation=>c_operator_between. + lo_data_validation->formula1 = 1. + lo_data_validation->formula2 = 10. + lo_data_validation->prompttitle = 'Range'. + lo_data_validation->prompt = 'Enter a value between 1 and 10'. + lo_data_validation->errortitle = 'Error'. + lo_data_validation->error = 'You have entered a wrong value. Please use only numbers between 1 and 10.'. + lo_data_validation->cell_row = 5. + lo_data_validation->cell_column = 'A'. + + " Evaluation by Formula from issue #161 + lo_worksheet->set_cell( ip_row = 7 ip_column = 'A' ip_value = 'Validate if B8 contains a "-":' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'A' ip_value = 'Text' ). + lo_worksheet->set_cell( ip_row = 8 ip_column = 'B' ip_value = '-' ). + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_custom. + lo_data_validation->formula1 = '"IF(B8<>"""";INDIRECT(LEFT(B8;SEARCH(""-"";B8;1)));EMPTY)"'. + lo_data_validation->cell_row = 8. + lo_data_validation->cell_column = 'A'. + + " There was an error when data validation was combined with cell merges this should test that: + lo_worksheet->set_cell( ip_row = 10 ip_column = 'A' ip_value = 'Demo for data validation with a dropdown list' ). + lo_worksheet->set_merge( ip_row = 10 ip_column_start = 'A' ip_column_end = 'F' ). + + " Headlines + lo_worksheet->set_cell( ip_row = 11 ip_column = 'A' ip_value = c_fruits ). + lo_worksheet->set_cell( ip_row = 11 ip_column = 'B' ip_value = c_vegetables ). + + row = 12. + WHILE row < 20. " Starting with 14500 the data validation is dropped 14000 are still ok + " 1st validation + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_fruits. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'A'. + lo_worksheet->set_cell( ip_row = row ip_column = 'A' ip_value = 'Select a value' ). + " 2nd + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_vegetables. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'B'. + lo_worksheet->set_cell( ip_row = row ip_column = 'B' ip_value = 'Select a value' ). + " 3rd + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_meat. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'C'. + lo_worksheet->set_cell( ip_row = row ip_column = 'C' ip_value = 'Select a value' ). + " 4th + lo_data_validation = lo_worksheet->add_new_data_validation( ). + lo_data_validation->type = zcl_excel_data_validation=>c_type_list. + lo_data_validation->formula1 = c_fish. + lo_data_validation->cell_row = row. + lo_data_validation->cell_column = 'D'. + lo_worksheet->set_cell( ip_row = row ip_column = 'D' ip_value = 'Select a value' ). + " Increment row + row = row + 1. + ENDWHILE. + + IF p_sbook = abap_true. + DATA: bookings type TABLE OF sbook. + + lo_worksheet = lo_excel->add_new_worksheet( ). + lv_title = 'SBOOK'. + lo_worksheet->set_title( lv_title ). + + SELECT * from sbook INTO TABLE bookings UP TO 4000 ROWS. + + lo_worksheet->bind_table( + EXPORTING + ip_table = bookings +* it_field_catalog = " Table binding field catalog +* is_table_settings = " Excel table binding settings +* IMPORTING +* es_table_settings = " Excel table binding settings + ). + ENDIF. + + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED3 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched3. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_reader TYPE REF TO zif_excel_reader, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +DATA: lt_files TYPE filetable, + ls_file TYPE file_table, + lv_rc TYPE i, + lv_value TYPE zexcel_cell_value. + +CONSTANTS: gc_save_file_name TYPE string VALUE 'TechEd01.xlsx'. +INCLUDE zdemo_excel_outputopt_incl. + +START-OF-SELECTION. + +******************************* +* abap2xlsx read XLSX * +******************************* + CREATE OBJECT lo_excel_reader TYPE zcl_excel_reader_2007. + lo_excel = lo_excel_reader->load_file( lv_full_path ). + + lo_excel->set_active_sheet_index( 1 ). + lo_worksheet = lo_excel->get_active_worksheet( ). + + lo_worksheet->get_cell( EXPORTING ip_column = 'C' + ip_row = 10 + IMPORTING ep_value = lv_value ). + + WRITE: 'abap2xlsx total score is ', lv_value. + +*** Create output + lcl_output=>output( lo_excel ). + + + + + + + + + *&---------------------------------------------------------------------* +*& Report ZDEMO_TECHED1 +*& +*&---------------------------------------------------------------------* +*& +*& +*&---------------------------------------------------------------------* + +REPORT zdemo_teched1. + +******************************* +* Data Object declaration * +******************************* + +DATA: lo_excel TYPE REF TO zcl_excel, + lo_excel_writer TYPE REF TO zif_excel_writer, + lo_worksheet TYPE REF TO zcl_excel_worksheet. + +DATA: lv_file TYPE xstring, + lv_bytecount TYPE i, + lt_file_tab TYPE solix_tab. + +DATA: lv_full_path TYPE string, + lv_workdir TYPE string, + lv_file_separator TYPE c. + +CONSTANTS: lv_default_file_name TYPE string VALUE 'TechEd01.xlsx'. + +******************************* +* Selection screen management * +******************************* + +PARAMETERS: p_path TYPE zexcel_export_dir. + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + lv_workdir = p_path. + cl_gui_frontend_services=>directory_browse( EXPORTING initial_folder = lv_workdir + CHANGING selected_folder = lv_workdir ). + p_path = lv_workdir. + +INITIALIZATION. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = lv_workdir ). + cl_gui_cfw=>flush( ). + p_path = lv_workdir. + +START-OF-SELECTION. + + IF p_path IS INITIAL. + p_path = lv_workdir. + ENDIF. + cl_gui_frontend_services=>get_file_separator( CHANGING file_separator = lv_file_separator ). + CONCATENATE p_path lv_file_separator lv_default_file_name INTO lv_full_path. + + +******************************* +* abap2xlsx create XLSX * +******************************* + + " Create excel instance + CREATE OBJECT lo_excel. + + " Get active sheet + lo_worksheet = lo_excel->get_active_worksheet( ). + lo_worksheet->set_title( ip_title = 'Demo01' ). + lo_worksheet->set_cell( ip_column = 'B' ip_row = 2 ip_value = 'Hello world' ). + + " Create xlsx stream + CREATE OBJECT lo_excel_writer TYPE zcl_excel_writer_2007. + lv_file = lo_excel_writer->write_file( lo_excel ). + +******************************* +* Output * +******************************* + + " Convert to binary + lt_file_tab = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_file ). + lv_bytecount = xstrlen( lv_file ). + + " Save the file + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_bytecount + filename = lv_full_path + filetype = 'BIN' + CHANGING data_tab = lt_file_tab ). + + + + + + + + *&---------------------------------------------------------------------* +*& Include ZDEMO_EXCEL_OUTPUTOPT_INCL +*&---------------------------------------------------------------------* +CLASS lcl_output DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS: + output IMPORTING cl_excel TYPE REF TO zcl_excel + iv_writerclass_name TYPE clike OPTIONAL, + f4_path RETURNING VALUE(selected_folder) TYPE string, + parametertexts. + + PRIVATE SECTION. + METHODS: + download_frontend, + download_backend, + display_online, + send_email. + + DATA: xdata TYPE xstring, " Will be used for sending as email + t_rawdata TYPE solix_tab, " Will be used for downloading or open directly + bytecount TYPE i. " Will be used for downloading or open directly +ENDCLASS. "lcl_output DEFINITION + + +SELECTION-SCREEN BEGIN OF BLOCK bl1 WITH FRAME TITLE txt_bl1. +PARAMETERS: rb_down RADIOBUTTON GROUP rb1 USER-COMMAND space. + +PARAMETERS: rb_back RADIOBUTTON GROUP rb1. + +PARAMETERS: rb_show RADIOBUTTON GROUP rb1 DEFAULT 'X' . + +PARAMETERS: rb_send RADIOBUTTON GROUP rb1. + +PARAMETERS: p_path TYPE string LOWER CASE MODIF ID pat. +PARAMETERS: p_email TYPE string LOWER CASE MODIF ID ema OBLIGATORY DEFAULT 'insert_your_emailadress@here'. +PARAMETERS: p_backfn TYPE text40 NO-DISPLAY. +SELECTION-SCREEN END OF BLOCK bl1. + + +AT SELECTION-SCREEN OUTPUT. + LOOP AT SCREEN. + + IF rb_down IS INITIAL AND screen-group1 = 'PAT'. + screen-input = 0. + screen-invisible = 1. + ENDIF. + + IF rb_send IS INITIAL AND screen-group1 = 'EMA'. + screen-input = 0. + screen-invisible = 1. + ENDIF. + + MODIFY SCREEN. + + ENDLOOP. + +INITIALIZATION. + IF sy-batch IS INITIAL. + cl_gui_frontend_services=>get_sapgui_workdir( CHANGING sapworkdir = p_path ). + cl_gui_cfw=>flush( ). + ENDIF. + lcl_output=>parametertexts( ). " If started in language w/o textelements translated set defaults + sy-title = gc_save_file_name. + txt_bl1 = 'Output options'(bl1). + p_backfn = gc_save_file_name. " Use as default if nothing else is supplied by submit + +AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. + p_path = lcl_output=>f4_path( ). + + +*----------------------------------------------------------------------* +* CLASS lcl_output IMPLEMENTATION +*----------------------------------------------------------------------* +CLASS lcl_output IMPLEMENTATION. + METHOD output. + + DATA: cl_output TYPE REF TO lcl_output, + cl_writer TYPE REF TO zif_excel_writer. + + IF iv_writerclass_name IS INITIAL. + CREATE OBJECT cl_output. + CREATE OBJECT cl_writer TYPE zcl_excel_writer_2007. + ELSE. + CREATE OBJECT cl_output. + CREATE OBJECT cl_writer TYPE (iv_writerclass_name). + ENDIF. + cl_output->xdata = cl_writer->write_file( cl_excel ). + +* After 6.40 via cl_bcs_convert + cl_output->t_rawdata = cl_bcs_convert=>xstring_to_solix( iv_xstring = cl_output->xdata ). + cl_output->bytecount = xstrlen( cl_output->xdata ). + +* before 6.40 +* CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' +* EXPORTING +* buffer = cl_output->xdata +* IMPORTING +* output_length = cl_output->bytecount +* TABLES +* binary_tab = cl_output->t_rawdata. + + CASE 'X'. + WHEN rb_down. + IF sy-batch IS INITIAL. + cl_output->download_frontend( ). + ELSE. + MESSAGE e001(00) WITH 'Frontenddownload impossible in background processing'. + ENDIF. + + WHEN rb_back. + cl_output->download_backend( ). + + WHEN rb_show. + IF sy-batch IS INITIAL. + cl_output->display_online( ). + ELSE. + MESSAGE e001(00) WITH 'Online display absurd in background processing'. + ENDIF. + + WHEN rb_send. + cl_output->send_email( ). + + ENDCASE. + ENDMETHOD. "output + + METHOD f4_path. + DATA: new_path TYPE string, + repid TYPE syrepid, + dynnr TYPE sydynnr, + lt_dynpfields TYPE TABLE OF dynpread, + ls_dynpfields LIKE LINE OF lt_dynpfields. + +* Get current value + dynnr = sy-dynnr. + repid = sy-repid. + ls_dynpfields-fieldname = 'P_PATH'. + APPEND ls_dynpfields TO lt_dynpfields. + + CALL FUNCTION 'DYNP_VALUES_READ' + EXPORTING + dyname = repid + dynumb = dynnr + TABLES + dynpfields = lt_dynpfields + EXCEPTIONS + invalid_abapworkarea = 1 + invalid_dynprofield = 2 + invalid_dynproname = 3 + invalid_dynpronummer = 4 + invalid_request = 5 + no_fielddescription = 6 + invalid_parameter = 7 + undefind_error = 8 + double_conversion = 9 + stepl_not_found = 10 + OTHERS = 11. + IF sy-subrc <> 0. + MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno + WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. + EXIT. + ENDIF. + + READ TABLE lt_dynpfields INTO ls_dynpfields INDEX 1. + + new_path = ls_dynpfields-fieldvalue. + selected_folder = new_path. + + cl_gui_frontend_services=>directory_browse( + EXPORTING + window_title = 'Select path to download EXCEL-file' + initial_folder = new_path + CHANGING + selected_folder = new_path + EXCEPTIONS + cntl_error = 1 + error_no_gui = 2 + not_supported_by_gui = 3 + OTHERS = 4 + ). + cl_gui_cfw=>flush( ). + CHECK new_path IS NOT INITIAL. + selected_folder = new_path. + + ENDMETHOD. "f4_path + + METHOD parametertexts. +* If started in language w/o textelements translated set defaults +* Furthermore I don't have to change the selectiontexts of all demoreports. + DEFINE default_parametertext. + if %_&1_%_app_%-text = '&1' or + %_&1_%_app_%-text is initial. + %_&1_%_app_%-text = &2. + endif. + END-OF-DEFINITION. + + default_parametertext: rb_down 'Save to frontend', + rb_back 'Save to backend', + rb_show 'Direct display', + rb_send 'Send via email', + + p_path 'Frontend-path to download to', + p_email 'Email to send xlsx to'. + + ENDMETHOD. "parametertexts + + METHOD: download_frontend. + DATA: filename TYPE string. +* I don't like p_path here - but for this include it's ok + filename = p_path. +* Add trailing "\" or "/" + IF filename CA '/'. + REPLACE REGEX '([^/])\s*$' IN filename WITH '$1/' . + ELSE. + REPLACE REGEX '([^\\])\s*$' IN filename WITH '$1\\'. + ENDIF. + + CONCATENATE filename gc_save_file_name INTO filename. +* Get trailing blank + cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = bytecount + filename = filename + filetype = 'BIN' + CHANGING data_tab = t_rawdata ). + ENDMETHOD. "download_frontend + + METHOD download_backend. + DATA: bytes_remain TYPE i. + FIELD-SYMBOLS: <rawdata> LIKE LINE OF t_rawdata. + + OPEN DATASET p_backfn FOR OUTPUT IN BINARY MODE. + CHECK sy-subrc = 0. + + bytes_remain = bytecount. + + LOOP AT t_rawdata ASSIGNING <rawdata>. + + AT LAST. + CHECK bytes_remain >= 0. + TRANSFER <rawdata> TO p_backfn LENGTH bytes_remain. + EXIT. + ENDAT. + + TRANSFER <rawdata> TO p_backfn. + SUBTRACT 255 FROM bytes_remain. " Solix has length 255 + + ENDLOOP. + + CLOSE DATASET p_backfn. + + + + + IF sy-repid <> sy-cprog AND sy-cprog IS NOT INITIAL. " no need to display anything if download was selected and report was called for demo purposes + LEAVE PROGRAM. + ELSE. + MESSAGE 'Data transferred to default backend directory' TYPE 'S'. + ENDIF. + ENDMETHOD. "download_backend + + METHOD display_online. + DATA:error TYPE REF TO i_oi_error, + t_errors TYPE STANDARD TABLE OF REF TO i_oi_error WITH NON-UNIQUE DEFAULT KEY, + cl_control TYPE REF TO i_oi_container_control, "OIContainerCtrl + cl_document TYPE REF TO i_oi_document_proxy. "Office Dokument + + c_oi_container_control_creator=>get_container_control( IMPORTING control = cl_control + error = error ). + APPEND error TO t_errors. + + cl_control->init_control( EXPORTING inplace_enabled = 'X' + no_flush = 'X' + r3_application_name = 'Demo Document Container' + parent = cl_gui_container=>screen0 + IMPORTING error = error + EXCEPTIONS OTHERS = 2 ). + APPEND error TO t_errors. + + cl_control->get_document_proxy( EXPORTING document_type = 'Excel.Sheet' " EXCEL + no_flush = ' ' + IMPORTING document_proxy = cl_document + error = error ). + APPEND error TO t_errors. +* Errorhandling should be inserted here + + cl_document->open_document_from_table( EXPORTING document_size = bytecount + document_table = t_rawdata + open_inplace = 'X' ). + + WRITE: '.'. " To create an output. That way screen0 will exist + ENDMETHOD. "display_online + + METHOD send_email. +* Needed to send emails + DATA: bcs_exception TYPE REF TO cx_bcs, + errortext TYPE string, + cl_send_request TYPE REF TO cl_bcs, + cl_document TYPE REF TO cl_document_bcs, + cl_recipient TYPE REF TO if_recipient_bcs, + cl_sender TYPE REF TO cl_cam_address_bcs, + t_attachment_header TYPE soli_tab, + wa_attachment_header LIKE LINE OF t_attachment_header, + attachment_subject TYPE sood-objdes, + + sood_bytecount TYPE sood-objlen, + mail_title TYPE so_obj_des, + t_mailtext TYPE soli_tab, + wa_mailtext LIKE LINE OF t_mailtext, + send_to TYPE adr6-smtp_addr, + sent TYPE os_boolean. + + + mail_title = 'Mail title'. + wa_mailtext = 'Mailtext'. + APPEND wa_mailtext TO t_mailtext. + + TRY. +* Create send request + cl_send_request = cl_bcs=>create_persistent( ). +* Create new document with mailtitle and mailtextg + cl_document = cl_document_bcs=>create_document( i_type = 'RAW' "#EC NOTEXT + i_text = t_mailtext + i_subject = mail_title ). +* Add attachment to document +* since the new excelfiles have an 4-character extension .xlsx but the attachment-type only holds 3 charactes .xls, +* we have to specify the real filename via attachment header +* Use attachment_type xls to have SAP display attachment with the excel-icon + attachment_subject = gc_save_file_name. + CONCATENATE '&SO_FILENAME=' attachment_subject INTO wa_attachment_header. + APPEND wa_attachment_header TO t_attachment_header. +* Attachment + sood_bytecount = bytecount. " next method expects sood_bytecount instead of any positive integer *sigh* + cl_document->add_attachment( i_attachment_type = 'XLS' "#EC NOTEXT + i_attachment_subject = attachment_subject + i_attachment_size = sood_bytecount + i_att_content_hex = t_rawdata + i_attachment_header = t_attachment_header ). + +* add document to send request + cl_send_request->set_document( cl_document ). + +* set sender in case if no own email is availabe +* cl_sender = cl_cam_address_bcs=>create_internet_address( 'sender@sender.sender' ). +* cl_send_request->set_sender( cl_sender ). + +* add recipient(s) - here only 1 will be needed + send_to = p_email. + IF send_to IS INITIAL. + send_to = 'no_email@no_email.no_email'. " Place into SOST in any case for demonstration purposes + ENDIF. + cl_recipient = cl_cam_address_bcs=>create_internet_address( send_to ). + cl_send_request->add_recipient( cl_recipient ). + +* Und abschicken + sent = cl_send_request->send( i_with_error_screen = 'X' ). + + COMMIT WORK. + + IF sent IS INITIAL. + MESSAGE i500(sbcoms) WITH p_email. + ELSE. + MESSAGE s022(so). + MESSAGE 'Document ready to be sent - Check SOST or SCOT' TYPE 'I'. + ENDIF. + + CATCH cx_bcs INTO bcs_exception. + errortext = bcs_exception->if_message~get_text( ). + MESSAGE errortext TYPE 'I'. + + ENDTRY. + ENDMETHOD. "send_email + + +ENDCLASS. "lcl_output IMPLEMENTATION + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <?sap.transform simple?> +<tt:transform xmlns:tt="http://www.sap.com/transformation-templates"> + + <tt:root name="ROOT"/> + <tt:root name="SHARED_STRINGS"/> + + <tt:template> + <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> + <tt:attribute name="count" value-ref="ROOT.COUNT"/> + <tt:attribute name="uniqueCount" value-ref="ROOT.UNIQUE_COUNT"/> + <tt:loop ref="SHARED_STRINGS"> + <si> + <t> + <tt:value ref="STRING_VALUE"/> + </t> + </si> + </tt:loop> + </sst> + </tt:template> + +</tt:transform> + + + <?sap.transform simple?> +<tt:transform xmlns:tt="http://www.sap.com/transformation-templates" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> + + <tt:root name="WORKSHEET"/> + <tt:root name="CELLS"/> + <tt:root name="WRITER"/> + <tt:variable name="owriter" ref-type="ZCL_EXCEL_WRITER_HUGE_FILE"/> + + <tt:template> + <tt:assign ref="WRITER" to-var="owriter"/> + <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" + xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" + mc:Ignorable="x14ac"> + <tt:namespace name="r" /> + <tt:namespace name="mc" /> + <tt:namespace name="x14ac" /> + <sheetPr> + <tt:cond check="not-initial(WORKSHEET.TABCOLOR)"> + <tabColor> + <tt:attribute name="rgb" value-ref="WORKSHEET.TABCOLOR" /> + </tabColor> + </tt:cond> + <outlinePr> + <tt:attribute name="summaryRight" value-ref="WORKSHEET.SUMMARYRIGHT" /> + <tt:attribute name="summaryBelow" value-ref="WORKSHEET.SUMMARYBELOW" /> + </outlinePr> + </sheetPr> + <tt:cond check="not-initial(WORKSHEET.FITTOPAGE)"> + <pageSetupPr> + <tt:attribute name="fitToPage" value-ref="WORKSHEET.FITTOPAGE" /> + </pageSetupPr> + </tt:cond> + <dimension> + <tt:attribute name="ref" value-ref="WORKSHEET.DIMENSION" /> + </dimension> + <sheetViews> + <sheetView> + <tt:attribute name="showZeros" value-ref="WORKSHEET.SHOWZEROS" /> + <tt:attribute name="tabSelected" value-ref="WORKSHEET.TABSELECTED" /> + <tt:attribute name="zoomScale" value-ref="WORKSHEET.ZOOMSCALE" /> + <tt:cond check="WORKSHEET.ZOOMSCALENORMAL != 0"> + <tt:attribute name="zoomScaleNormal" value-ref="WORKSHEET.ZOOMSCALENORMAL" /> + </tt:cond> + <tt:cond check="WORKSHEET.ZOOMSCALEPAGEVIEW != 0"> + <tt:attribute name="zoomScalePageLayoutView" value-ref="WORKSHEET.ZOOMSCALEPAGEVIEW" /> + </tt:cond> + <tt:attribute name="zoomScaleSheetLayoutView" value-ref="WORKSHEET.ZOOMSCALESHEETVIEW" /> + <tt:attribute name="workbookViewId" value-ref="WORKSHEET.WORKBOOKVIEWID" /> + <tt:attribute name="showGridLines" value-ref="WORKSHEET.SHOWGRIDLINES" /> + <tt:attribute name="showRowColHeaders" value-ref="WORKSHEET.SHOWROWCOLHEADERS" /> + <tt:cond check="WORKSHEET.YSPLIT != 0 or WORKSHEET.XSPLIT != 0"> + <pane activePane="bottomRight" state="frozen"> + <tt:cond check="WORKSHEET.YSPLIT != 0"> + <tt:attribute name="ySplit" value-ref="WORKSHEET.YSPLIT" /> + </tt:cond> + <tt:cond check="WORKSHEET.XSPLIT != 0"> + <tt:attribute name="xSplit" value-ref="WORKSHEET.XSPLIT" /> + </tt:cond> + <tt:attribute name="topLeftCell" value-ref="WORKSHEET.TOPLEFTCELL" /> + </pane> + </tt:cond> + <selection> + <tt:attribute name="activeCell" value-ref="WORKSHEET.ACTIVECELL" /> + <tt:attribute name="sqref" value-ref="WORKSHEET.ACTIVECELL" /> + </selection> + </sheetView> + </sheetViews> + <sheetFormatPr> + <tt:attribute name="defaultRowHeight" value-ref="WORKSHEET.DEFAULTROWHEIGHT" /> + <tt:cond check="WORKSHEET.DEFAULTCOLWIDTH != 0"> + <tt:attribute name="defaultColWidth" value-ref="WORKSHEET.DEFAULTCOLWIDTH" /> + </tt:cond> + <tt:attribute name="x14ac:outlineLevelRow" value-ref="WORKSHEET.OUTLINELEVELROW" /> + <tt:attribute name="x14ac:outlineLevelCol" value-ref="WORKSHEET.OUTLINELEVELCOL" /> + </sheetFormatPr> + <cols> + <tt:loop ref="WORKSHEET.COLS"> + <col> + <tt:attribute name="min" value-ref="MIN" /> + <tt:attribute name="max" value-ref="MAX" /> + <tt:attribute name="width" value-ref="WIDTH" /> + <tt:cond check="not-initial(HIDDEN)"> + <tt:attribute name="hidden" value-ref="HIDDEN" /> + </tt:cond> + <tt:cond check="not-initial(CUSTOMWIDTH)"> + <tt:attribute name="customWidth" value-ref="CUSTOMWIDTH" /> + </tt:cond> + <tt:cond check="not-initial(BESTFIT)"> + <tt:attribute name="bestFit" value-ref="BESTFIT" /> + </tt:cond> + <tt:cond check="not-initial(COLLAPSED)"> + <tt:attribute name="collapsed" value-ref="COLLAPSED" /> + </tt:cond> + <tt:cond check="OUTLINELEVEL != 0"> + <tt:attribute name="outlineLevel" value-ref="OUTLINELEVEL" /> + </tt:cond> + <tt:cond check="STYLE >= 0"> + <tt:attribute name="style" value-ref="STYLE" /> + </tt:cond> + </col> + </tt:loop> + </cols> + <sheetData> + <tt:loop ref="WORKSHEET.ROWS"> + <row> + <tt:attribute name="r" value-ref="ROW" /> + <tt:attribute name="spans" value-ref="SPANS" /> + <tt:cond check="not-initial(HIDDEN)"> + <tt:attribute name="hidden" value-ref="HIDDEN" /> + </tt:cond> + <tt:cond check="not-initial(CUSTOMHEIGHT)"> + <tt:attribute name="customHeight" value-ref="CUSTOMHIGHT" /> + <tt:attribute name="ht" value-ref="HIGHT" /> + </tt:cond> + <tt:cond check="not-initial(COLLAPSED)"> + <tt:attribute name="collapsed" value-ref="COLLAPSED" /> + </tt:cond> + <tt:cond check="OUTLINELEVEL != 0"> + <tt:attribute name="outlineLevel" value-ref="OUTLINELEVEL" /> + </tt:cond> + <tt:cond check="STYLE != 0"> + <tt:attribute name="customFormat" value-ref="CUSTOMFORMAT" /> + <tt:attribute name="s" value-ref="STYLE" /> + </tt:cond> + <!-- Aufruf get_cells --> + <tt:call-method s-name="GET_CELLS" var="owriter"> + <tt:with-parameter name="I_ROW" ref="ROW" /> + <tt:with-parameter name="I_INDEX" ref="INDEX" /> + </tt:call-method> + <tt:loop ref=".CELLS"> + <c> + <tt:attribute name="r" value-ref="NAME" /> + <tt:cond check="STYLE >= 0"> + <tt:attribute name="s" value-ref="STYLE" /> + </tt:cond> + <tt:cond check="not-initial(FORMULA)"> + <tt:attribute name="f" value-ref="FORMULA" /> + </tt:cond> + <tt:cond check="not-initial(VALUE) and initial(FORMULA)"> + <tt:attribute name="t" value-ref="TYPE" /> + <tt:cond check="TYPE = 'inlineStr'"> + <is> + <t> + <tt:value ref="VALUE" /> + </t> + </is> + </tt:cond> + <tt:cond check="TYPE != 'inlineStr'"> + <v> + <tt:value ref="VALUE" /> + </v> + </tt:cond> + </tt:cond> + </c> + </tt:loop> + </row> + </tt:loop> + </sheetData> + <tt:cond check="WORKSHEET.MERGECELLS_COUNT != 0"> + <mergeCells> + <tt:attribute name="count" value-ref="WORKSHEET.MERGECELLS_COUNT" /> + <tt:loop ref="WORKSHEET.MERGECELLS"> + <mergeCell> + <tt:attribute name="ref" value-ref="REF" /> + </mergeCell> + </tt:loop> + </mergeCells> + </tt:cond> + <tt:cond check="WORKSHEET.HYPERLINKS_COUNT != 0"> + <hyperlinks> + <tt:loop ref="WORKSHEET.HYPERLINKS"> + <hyperlink> + <tt:attribute name="ref" value-ref="REF" /> + <tt:cond check="not-initial(LOCATION)"> + <tt:attribute name="location" value-ref="LOCATION" /> + </tt:cond> + <tt:cond check="not-initial(R_ID)"> + <tt:attribute name="r:id" value-ref="R_ID" /> + </tt:cond> + </hyperlink> + </tt:loop> + </hyperlinks> + </tt:cond> + <tt:cond check="not-initial(WORKSHEET.PRINTOPTIONS)"> + <printOptions> + <tt:ref name="WORKSHEET.PRINTOPTIONS"> + <tt:cond check="not-initial(GRIDLINES)"> + <tt:attribute name="gridLines" value-ref="GRIDLINES" /> + </tt:cond> + <tt:cond check="not-initial(HORIZONTALCENTERED)"> + <tt:attribute name="horizontalCentered" value-ref="HORIZONTALCENTERED" /> + </tt:cond> + <tt:cond check="not-initial(VERTICALCENTERED)"> + <tt:attribute name="verticalCentered" value-ref="VERTICALCENTERED" /> + </tt:cond> + </tt:ref> + </printOptions> + </tt:cond> + <pageMargins> + <tt:ref name="WORKSHEET.PAGEMARGINS"> + <tt:attribute name="left" value-ref="LEFT" /> + <tt:attribute name="right" value-ref="RIGHT" /> + <tt:attribute name="top" value-ref="TOP" /> + <tt:attribute name="bottom" value-ref="BOTTOM" /> + <tt:attribute name="header" value-ref="HEADER" /> + <tt:attribute name="footer" value-ref="FOOTER" /> + </tt:ref> + </pageMargins> + <pageSetup> + <tt:ref name="WORKSHEET.PAGESETUP"> + <tt:cond check="not-initial(BLACKANDWHITE)"> + <tt:attribute name="blackAndWhite" value-ref="BLACKANDWHITE" /> + </tt:cond> + <tt:cond check="not-initial(CELLCOMMENTS)"> + <tt:attribute name="cellComments" value-ref="CELLCOMMENTS" /> + </tt:cond> + <tt:cond check="COPIES != 0"> + <tt:attribute name="copies" value-ref="COPIES" /> + </tt:cond> + <tt:cond check="not-initial(DRAFT)"> + <tt:attribute name="draft" value-ref="DRAFT" /> + </tt:cond> + <tt:cond check="not-initial(ERRORS)"> + <tt:attribute name="errors" value-ref="ERRORS" /> + </tt:cond> + <tt:cond check="FIRSTPAGENUMBER != 0"> + <tt:attribute name="firstPageNumber" value-ref="FIRSTPAGENUMBER" /> + </tt:cond> + <tt:cond check="not-initial(FITTOPAGE)"> + <tt:attribute name="fitToHeight" value-ref="FITTOHIGHT" /> + <tt:attribute name="fitToWidth" value-ref="FITTOWIDTH" /> + </tt:cond> + <tt:cond check="HORIZONTALDPI != 0"> + <tt:attribute name="horizontalDpi" value-ref="HORIZONTALDPI" /> + </tt:cond> + <tt:cond check="not-initial(ORIENTATION)"> + <tt:attribute name="orientation" value-ref="ORIENTATION" /> + </tt:cond> + <tt:cond check="not-initial(PAGEORDER)"> + <tt:attribute name="pageOrder" value-ref="PAGEORDER" /> + </tt:cond> + <tt:cond check="not-initial(PAPERHEIGHT)"> + <tt:attribute name="paperHeight" value-ref="PAPERHEIGHT" /> + </tt:cond> + <tt:cond check="PAPERSIZE != 0"> + <tt:attribute name="paperSize" value-ref="PAPERSIZE" /> + </tt:cond> + <tt:cond check="not-initial(PAPERWIDTH)"> + <tt:attribute name="paperWidth" value-ref="PAPERWIDTH" /> + </tt:cond> + <tt:cond check="SCALE != 0"> + <tt:attribute name="scale" value-ref="SCALE" /> + </tt:cond> + <tt:cond check="not-initial(USEFIRSTPAGENUMBER)"> + <tt:attribute name="useFirstPageNumber" value-ref="USEFIRSTPAGENUMBER" /> + </tt:cond> + <tt:cond check="not-initial(USEPRINTERDEFAULTS)"> + <tt:attribute name="usePrinterDefaults" value-ref="USEPRINTERDEFAULTS" /> + </tt:cond> + <tt:cond check="VERTICALDPI != 0"> + <tt:attribute name="verticalDpi" value-ref="VERTICALDPI" /> + </tt:cond> + </tt:ref> + </pageSetup> + <tt:cond check="not-initial(WORKSHEET.HEADERFOOTER)"> + <headerFooter> + <tt:ref name="WORKSHEET.HEADERFOOTER"> + <tt:cond check="not-initial(WORKSHEET.HEADERFOOTER)"> + <tt:attribute name="differentOddEven" value-ref="DIFFERENTODDEVEN" /> + </tt:cond> + <oddHeader> + <tt:value ref="ODDHEADER" /> + </oddHeader> + <oddFooter> + <tt:value ref="ODDFOOTER" /> + </oddFooter> + <evenHeader> + <tt:value ref="EVENHEADER" /> + </evenHeader> + <evenFooter> + <tt:value ref="EVENFOOTER" /> + </evenFooter> + </tt:ref> + </headerFooter> + </tt:cond> + <tt:cond check="not-initial(WORKSHEET.DRAWINGS)"> + <drawing> + <tt:attribute name="r:id" value-ref="WORKSHEET.DRAWINGS" /> + </drawing> + </tt:cond> + <tt:cond check="WORKSHEET.TABLES_COUNT != 0"> + <tableParts> + <tt:attribute name="count" value-ref="WORKSHEET.TABLES_COUNT" /> + <tt:loop ref="WORKSHEET.TABLES"> + <tablePart> + <tt:attribute name="r:id" value-ref="R_ID" /> + </tablePart> + </tt:loop> + </tableParts> + </tt:cond> + </worksheet> + </tt:template> +</tt:transform> + + diff --git a/build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg.zip b/build/ABAP2XLSX_V_7_0_6 - 2016-04-01.nugg.zip new file mode 100644 index 0000000000000000000000000000000000000000..545711d8681abd0d92e901129e10546c7f07ddab GIT binary patch literal 378711 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