diff --git a/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk b/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk index 4e832ab..4e6e762 100644 --- a/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk +++ b/ZA2X/CLAS/ZCL_EXCEL_READER_2007.slnk @@ -1023,50 +1023,50 @@ endmethod. - method LOAD_STYLES. + METHOD load_styles. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (wip ) 2012-11-11 +* - Stefan Schmöcker, (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, + 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, + 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, + hidden TYPE string, + locked TYPE string, END OF lty_protection. - DATA: - lo_styles_xml TYPE REF TO if_ixml_document, + DATA: lo_styles_xml TYPE REF TO if_ixml_document, lo_style TYPE REF TO zcl_excel_style, lt_num_formats TYPE t_num_formats, @@ -1092,14 +1092,51 @@ endmethod. 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 ). - lt_num_formats = load_style_num_formats( lo_styles_xml ). - lt_fills = load_style_fills( lo_styles_xml ). - lt_borders = load_style_borders( lo_styles_xml ). - lt_fonts = load_style_fonts( lo_styles_xml ). +*--------------------------------------------------------------------* +* 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 - "we have all the components of style, now build the style objects +*--------------------------------------------------------------------* +* 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' ). @@ -1112,6 +1149,9 @@ endmethod. 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. @@ -1120,6 +1160,9 @@ endmethod. 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. @@ -1127,6 +1170,9 @@ endmethod. 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. @@ -1135,6 +1181,9 @@ endmethod. 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. @@ -1143,6 +1192,9 @@ endmethod. 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 @@ -1174,6 +1226,9 @@ endmethod. 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 @@ -1201,49 +1256,85 @@ endmethod. ENDWHILE. ENDIF. -endmethod. +ENDMETHOD. - method LOAD_STYLE_BORDERS. + METHOD load_style_borders. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (wip ) 2012-11-18 +* - Stefan Schmöcker, (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 TYPE REF TO if_ixml_element, - lo_node2 TYPE REF TO if_ixml_element, - lo_node3 TYPE REF TO if_ixml_element, + 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. - lo_node ?= ip_xml->find_from_name( 'border' ). - WHILE lo_node IS BOUND. +*--------------------------------------------------------------------* +* 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. - IF lo_node->get_attribute( 'diagonalDown' ) IS NOT INITIAL. - lo_cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_down. +*--------------------------------------------------------------------* +* 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->get_attribute( 'diagonalUp' ) IS NOT INITIAL. - IF lo_cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_down. - lo_cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_both. - ELSE. - lo_cell_border->diagonal_mode = zcl_excel_style_borders=>c_diagonal_up. - 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_node2 ?= lo_node->get_first_child( ). - WHILE lo_node2 IS BOUND. + 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_node2->get_name( ). + CASE lo_node_bordertype->get_name( ). WHEN 'left'. lo_cell_border->left = lo_border. @@ -1262,11 +1353,14 @@ endmethod. ENDCASE. - lo_border->border_style = lo_node2->get_attribute( 'style' ). - lo_node3 ?= lo_node2->find_from_name( 'color' ). - IF lo_node3 IS BOUND. +*--------------------------------------------------------------------* +* §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_node3 + ip_element = lo_node_bordercolor CHANGING cp_structure = ls_color ). @@ -1281,23 +1375,23 @@ endmethod. lo_border->border_color-tint = ls_color-tint. ENDIF. - lo_node2 ?= lo_node2->get_next( ). + lo_node_bordertype ?= lo_node_bordertype->get_next( ). ENDWHILE. INSERT lo_cell_border INTO TABLE ep_borders. - lo_node ?= lo_node->get_next( ). + lo_node_border ?= lo_node_border->get_next( ). ENDWHILE. -endmethod. +ENDMETHOD. - method LOAD_STYLE_FILLS. + METHOD load_style_fills. *--------------------------------------------------------------------* * ToDos: * 2do§1 Support gradientFill @@ -1305,33 +1399,57 @@ endmethod. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (wip ) 2012-11-18 +* - Stefan Schmöcker, (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 TYPE REF TO if_ixml_element, - lo_node2 TYPE REF TO if_ixml_element, - lo_node3 TYPE REF TO if_ixml_element, + 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_fill TYPE REF TO zcl_excel_style_fill, ls_color TYPE t_color. - lo_node ?= ip_xml->find_from_name( 'fill' ). - WHILE lo_node IS BOUND. +*--------------------------------------------------------------------* +* 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_node2 ?= lo_node->get_first_child( ). - lv_value = lo_node2->get_name( ). + 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_node2->get_attribute( 'patternType' ). - lo_node3 = lo_node2->find_from_name( 'bgColor' ). - IF lo_node3 IS BOUND. + 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_node3 + ip_element = lo_node_bgcolor CHANGING cp_structure = ls_color ). @@ -1346,10 +1464,13 @@ endmethod. lo_fill->bgcolor-tint = ls_color-tint. ENDIF. - lo_node3 = lo_node->find_from_name( 'fgColor' ). - IF lo_node3 IS BOUND. +*--------------------------------------------------------------------* +* 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_node3 + ip_element = lo_node_fgcolor CHANGING cp_structure = ls_color ). @@ -1364,6 +1485,10 @@ endmethod. lo_fill->fgcolor-tint = ls_color-tint. ENDIF. + +*--------------------------------------------------------------------* +* gradientFill +*--------------------------------------------------------------------* WHEN 'gradientFill'. " 2do§1 Support gradientFill @@ -1371,76 +1496,117 @@ endmethod. ENDCASE. + INSERT lo_fill INTO TABLE ep_fills. - lo_node ?= lo_node->get_next( ). + + lo_node_fill ?= lo_node_fill->get_next( ). ENDWHILE. -endmethod. +ENDMETHOD. - method LOAD_STYLE_FONTS. + METHOD load_style_fonts. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (wip ) 2012-11-18 +* - Stefan Schmöcker, (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 TYPE REF TO if_ixml_element, + 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. - lo_node ?= ip_xml->find_from_name( 'font' ). - WHILE lo_node IS BOUND. +*--------------------------------------------------------------------* +* 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. - - IF lo_node->find_from_name( 'b' ) IS BOUND. +*--------------------------------------------------------------------* +* Bold +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'b' ) IS BOUND. lo_font->bold = abap_true. ENDIF. - IF lo_node->find_from_name( 'i' ) IS BOUND. +*--------------------------------------------------------------------* +* Italic +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'i' ) IS BOUND. lo_font->italic = abap_true. ENDIF. - lo_node2 = lo_node->find_from_name( 'u' ). +*--------------------------------------------------------------------* +* 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. - IF lo_node->find_from_name( 'strike' ) IS BOUND. +*--------------------------------------------------------------------* +* StrikeThrough +*--------------------------------------------------------------------* + IF lo_node_font->find_from_name( 'strike' ) IS BOUND. lo_font->strikethrough = abap_true. ENDIF. - lo_node2 = lo_node->find_from_name( 'sz' ). +*--------------------------------------------------------------------* +* Fontsize +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'sz' ). IF lo_node2 IS BOUND. lo_font->size = lo_node2->get_attribute( 'val' ). ENDIF. - lo_node2 = lo_node->find_from_name( 'name' ). +*--------------------------------------------------------------------* +* Fontname +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'name' ). IF lo_node2 IS BOUND. lo_font->name = lo_node2->get_attribute( 'val' ). ENDIF. - lo_node2 = lo_node->find_from_name( 'family' ). +*--------------------------------------------------------------------* +* Fontfamily +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'family' ). IF lo_node2 IS BOUND. lo_font->family = lo_node2->get_attribute( 'val' ). ENDIF. - lo_node2 = lo_node->find_from_name( 'scheme' ). +*--------------------------------------------------------------------* +* Fontscheme +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'scheme' ). IF lo_node2 IS BOUND. lo_font->scheme = lo_node2->get_attribute( 'val' ). ENDIF. - lo_node2 = lo_node->find_from_name( 'color' ). +*--------------------------------------------------------------------* +* Fontcolor +*--------------------------------------------------------------------* + lo_node2 = lo_node_font->find_from_name( 'color' ). IF lo_node2 IS BOUND. fill_struct_from_attributes( EXPORTING ip_element = lo_node2 @@ -1459,12 +1625,12 @@ endmethod. INSERT lo_font INTO TABLE ep_fonts. - lo_node ?= lo_node->get_next( ). + lo_node_font ?= lo_node_font->get_next( ). ENDWHILE. -endmethod. +ENDMETHOD. @@ -1477,14 +1643,30 @@ endmethod. *--------------------------------------------------------------------* * issue #230 - Pimp my Code -* - Stefan Schmöcker, (done) 2012-11-11 +* - Stefan Schmöcker, (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 t_num_format. +*--------------------------------------------------------------------* +* We need a table of used numberformats to build up our styles +* there are two kinds of numberformats +* §1 those that have been explicitly added by the createor of the excel-file +* §2 and built-in numberformats +*--------------------------------------------------------------------* + +*--------------------------------------------------------------------* +* §1 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. @@ -1506,6 +1688,9 @@ endmethod. insert ls_num_format into table ep_num_formats. END-OF-DEFINITION. +*--------------------------------------------------------------------* +* §1 Get internal predefined numberformats +*--------------------------------------------------------------------* predefined_format '1' '0'. predefined_format '2' '0.00'. predefined_format '3' '#,##0'. @@ -1555,7 +1740,7 @@ endmethod. predefined_format '47' 'mm:ss.0'. predefined_format '48' '##0.0E+0'. predefined_format '49' '@'. -* 2do§1 Is 49 really the last redefined format? +* 2do§1 Is 49 really the last predefined format? endmethod. @@ -2500,6 +2685,7 @@ endmethod. * 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