Show code in Nugget ZCL_WORD.nugg
Table of content
Program ZCL_WORD: Include ZCL_WORD
ABAP Code
*----------------------------------------------------------------------*
* CLASS : cl_word
* Author : S. Hermann
* Date : 14.07.2017
* Version : v1.4
*----------------------------------------------------------------------*
* Abstraction class to create MS Word DOCX from ABAP
*----------------------------------------------------------------------*
* 14.07.2017 - v1.4
* Add insert_attachment method
* 23.01.2017 - v1.3.1
* Add Allow direct input of xml into a virtual field
* Add Allow input of table (or other paragraph xml fragment
* into virtual field
* Add Allow breakpage to be virtual" to add breakpage/line
* inside an xml fragment
* 18.04.2016 - v1.3
* Fix bug with table width definition (for word 2007)
* Mod documentation on canvas
* Fix bug on virtual parameter for write_line
* Add write_text can now generate also virtual paragraph
* Fix compatibility issue with old ECC version
* Add option in constructor to create docx from xstring input
* Add line_style_effect option on write_text to close paragraph
* and apply detailed style on it
* Add virtual option on write_table
* Add option on insert_image method to allow the image to be
* inserted in a existing paragraph
* Add float management for images (inline, float, over, behind)
* Add position management for images (left, right, center)
* Add margin management for images
* Add management of forms (rectangle, elipse, rounded rect)
* 24.01.2016 - v1.2
* Add option on set_params to hide spellcheck in document
* Add allow merge cells in write_table
* 13.12.2015 - v1.1
* Add option to keep loaded template content
* Add get_zip_file method
* Add write_note method
* Add write_comment method
* Add image insertion in table
* Add xml insertion in table for complex cell content
* Add option on write_text to insert label number
* Add option on write_line to get XML instead of buffer into doc
* Add option to save zip file on server
* Add options on method write_toc
* Now you can write a toc of specific label(for ex.: figure)
* Fix bug when template path is invalid
* Fix dump when reuse an image
* v1.02 : Initial public release
*----------------------------------------------------------------------*
CLASS cl_word DEFINITION FINAL.
PUBLIC SECTION.
CONSTANTS :
c_true TYPE i VALUE 1,
c_false TYPE i VALUE 0,
* Predefined fields that can be added
c_field_pagecount TYPE string VALUE '##FIELD#PAGE##', " MS Word current page counter
c_field_pagetotal TYPE string VALUE '##FIELD#NUMPAGES##', " MS Word total page counter
c_field_title TYPE string VALUE '##FIELD#TITLE##',
c_field_author TYPE string VALUE '##FIELD#AUTHOR##',
c_field_authorlastmod TYPE string VALUE '##FIELD#LASTSAVEDBY##',
c_field_comments TYPE string VALUE '##FIELD#COMMENTS##',
c_field_keywords TYPE string VALUE '##FIELD#KEYWORDS##',
c_field_category TYPE string VALUE '##FIELD#DOCPROPERTY CATEGORY##',
c_field_subject TYPE string VALUE '##FIELD#SUBJECT##',
c_field_revision TYPE string VALUE '##FIELD#REVNUM##',
c_field_creationdate TYPE string VALUE '##FIELD#CREATEDATE##',
c_field_moddate TYPE string VALUE '##FIELD#SAVEDATE##',
c_field_todaydate TYPE string VALUE '##FIELD#DATE##',
c_field_filename TYPE string VALUE '##FIELD#FILENAME##',
* Anchor for label
c_label_anchor TYPE string VALUE '##LABEL##',
* Prefix for SAPWR url
c_sapwr_prefix(6) TYPE c VALUE 'SAPWR:',
* Predefined fonts
c_font_arial TYPE string VALUE 'Arial', "#EC NOTEXT
c_font_times TYPE string VALUE 'Times New Roman', "#EC NOTEXT
c_font_comic TYPE string VALUE 'Comic Sans MS', "#EC NOTEXT
c_font_calibri TYPE string VALUE 'Calibri', "#EC NOTEXT
c_font_cambria TYPE string VALUE 'Cambria', "#EC NOTEXT
c_font_courier TYPE string VALUE 'Courier New', "#EC NOTEXT
c_font_symbol TYPE string VALUE 'Wingdings', "#EC NOTEXT
* Predefined Styles
* Regarding your document language, style could be named differently
* For example, in french ms document, title1 is labelled "Titre1"
c_style_title TYPE string VALUE 'Title', "#EC NOTEXT
c_style_title1 TYPE string VALUE 'Title1', "#EC NOTEXT
c_style_title2 TYPE string VALUE 'Title2', "#EC NOTEXT
c_style_title3 TYPE string VALUE 'Title3', "#EC NOTEXT
c_style_title4 TYPE string VALUE 'Title4', "#EC NOTEXT
c_style_normal TYPE string VALUE 'Normal', "#EC NOTEXT
* Predefined break types
c_breaktype_line TYPE i VALUE 6,
c_breaktype_page TYPE i VALUE 7,
c_breaktype_column TYPE i VALUE 1, "NOT MANAGED
c_breaktype_section TYPE i VALUE 2,
c_breaktype_section_continuous TYPE i VALUE 3,
* Predefined symbols
c_symbol_checkbox_checked TYPE string VALUE 'þ', "#EC NOTEXT
c_symbol_checkbox TYPE string VALUE 'o', "#EC NOTEXT
* Draw CANVAS objects
c_draw_image TYPE i VALUE 0,
c_draw_rectangle TYPE i VALUE 1,
* Direct draw objects
c_ddraw_rectangle TYPE string VALUE 'rect',
c_ddraw_rectangle_rounded TYPE string VALUE 'roundrect',
c_ddraw_ovale TYPE string VALUE 'oval',
* Text alignment
c_align_left TYPE string VALUE 'left', "#EC NOTEXT
c_align_center TYPE string VALUE 'center', "#EC NOTEXT
c_align_right TYPE string VALUE 'right', "#EC NOTEXT
c_align_justify TYPE string VALUE 'both', "#EC NOTEXT
* Vertical alignment
c_valign_top TYPE string VALUE 'top', "#EC NOTEXT
c_valign_middle TYPE string VALUE 'center', "#EC NOTEXT
c_valign_bottom TYPE string VALUE 'bottom', "#EC NOTEXT
* Image type
* inline : image is included in a line of text
c_imgtype_inline TYPE i VALUE 1,
* float : text is wraping around the image
c_imgtype_float TYPE i VALUE 2,
* over : image is over the text
c_imgtype_over TYPE i VALUE 3,
* behind : image is behind the text
c_imgtype_behind TYPE i VALUE 4,
* Image horizontal position
c_imgposx_left TYPE string VALUE 'left',
c_imgposx_right TYPE string VALUE 'right',
c_imgposx_center TYPE string VALUE 'center',
* Image vertical position
c_imgposy_top TYPE string VALUE 'top',
c_imgposy_middle TYPE string VALUE 'center',
c_imgposy_bottom TYPE string VALUE 'bottom',
* Types for header/footer
c_type_header TYPE string VALUE 'header', "#EC NOTEXT
c_type_footer TYPE string VALUE 'footer', "#EC NOTEXT
* Style type
c_type_paragraph TYPE string VALUE 'paragraph',
c_type_character TYPE string VALUE 'character',
c_type_table TYPE string VALUE 'table',
c_type_numbering TYPE string VALUE 'numbering',
* Image type
c_type_image TYPE string VALUE 'image',
* Page orientation
c_orient_landscape TYPE i VALUE 1, " Landscape
c_orient_portrait TYPE i VALUE 0, " Portrait
* Note type
c_notetype_foot TYPE i VALUE 1, "foot note
c_notetype_end TYPE i VALUE 2, "end note
* Predefined colors
c_color_black TYPE string VALUE '000000',
c_color_blue TYPE string VALUE '0000FF',
c_color_turquoise TYPE string VALUE '00FFFF',
c_color_brightgreen TYPE string VALUE '00FF00',
c_color_pink TYPE string VALUE 'FF00FF',
c_color_red TYPE string VALUE 'FF0000',
c_color_yellow TYPE string VALUE 'FFFF00',
c_color_white TYPE string VALUE 'FFFFFF',
c_color_darkblue TYPE string VALUE '000080',
c_color_teal TYPE string VALUE '008080',
c_color_green TYPE string VALUE '008000',
c_color_violet TYPE string VALUE '800080',
c_color_darkred TYPE string VALUE '800000',
c_color_darkyellow TYPE string VALUE '808000',
c_color_gray TYPE string VALUE '808080',
c_color_lightgray TYPE string VALUE 'C0C0C0',
* Predefined border style
c_border_simple TYPE string VALUE 'single',
c_border_double TYPE string VALUE 'double',
c_border_triple TYPE string VALUE 'triple',
c_border_dot TYPE string VALUE 'dotted',
c_border_dash TYPE string VALUE 'dashed',
c_border_wave TYPE string VALUE 'wave',
* Predefined font highlight color
c_highlight_yellow TYPE string VALUE 'yellow',
c_highlight_green TYPE string VALUE 'green',
c_highlight_cyan TYPE string VALUE 'cyan',
c_highlight_magenta TYPE string VALUE 'magenta',
c_highlight_blue TYPE string VALUE 'blue',
c_highlight_red TYPE string VALUE 'red',
c_highlight_darkblue TYPE string VALUE 'darkBlue',
c_highlight_darkcyan TYPE string VALUE 'darkCyan',
c_highlight_darkgreen TYPE string VALUE 'darkGreen',
c_highlight_darkmagenta TYPE string VALUE 'darkMagenta',
c_highlight_darkred TYPE string VALUE 'darkRed',
c_highlight_darkyellow TYPE string VALUE 'darkYellow',
c_highlight_darkgray TYPE string VALUE 'darkGray',
c_highlight_lightgray TYPE string VALUE 'lightGray',
c_highlight_black TYPE string VALUE 'black'
.
TYPES:
BEGIN OF ty_border,
* Border width
* Integer: 8 = 1pt
* Default: no border
width TYPE i,
* Space between border and content
* Integer
* Default: document default
space TYPE i,
* Border color
* You can use the predefined font color constants or specify any rgb hexa color code
* Default : document default
color TYPE string,
* Border style
* You can use the predefined border style constants
* Default : document default
style TYPE string, "border style
END OF ty_border,
BEGIN OF ty_character_style_effect,
* Font name to use for the character text fragment
* You can use the predefined font constants
* Default : document default
font TYPE string,
* Size of the font in pt
* Default : document default
size TYPE i,
* Font color to apply to the character text fragment
* You can use the predefined font color constants or specify any rgb hexa color code
* Default : document default
color TYPE string,
* Background color to apply to the character text fragment
* You can use the predefined font color constants or specify any rgb hexa color code
* Default : document default
bgcolor TYPE string,
* Highlight color to apply to the character text fragment
* You must use the predefined highlight color constants (limited color choice)
* If you want to use other color, please use bgcolor instead of highlight
* Default : document default
highlight TYPE string,
* Set character text fragment as bold (boolean)
* You must use predefined true/false constants
* Default : not bold
bold TYPE i,
* Set character text fragment as italic (boolean)
* You must use predefined true/false constants
* Default : not italic
italic TYPE i,
* Set character text fragment as underline (boolean)
* You must use predefined true/false constants
* Default : not underline
underline TYPE i,
* Set character text fragment as strike (boolean)
* You must use predefined true/false constants
* Default : not strike
strike TYPE i,
* Set character text fragment as exponent (boolean)
* You must use predefined true/false constants
* Default : not exponent
sup TYPE i,
* Set character text fragment as subscript (boolean)
* You must use predefined true/false constants
* Default : not subscript
sub TYPE i,
* Set character text fragment as upper case (boolean)
* You must use predefined true/false constants
* Default : not upper case
caps TYPE i,
* Set character text fragment as small upper case (boolean)
* You must use predefined true/false constants
* Default : not small upper case
smallcaps TYPE i,
* Letter spacing to apply to the character text fragment
* 0 = normal, +20 = expand 1pt, -20 = condense 1pt
* Default : document default
spacing TYPE string,
* Name of the label to use for this text fragment
* Be carefull that if c_label_anchor is not found in text fragment,
* this attribute is ignored
label TYPE string,
END OF ty_character_style_effect,
BEGIN OF ty_paragraph_style_effect,
* Set alignment for the paragraph (left, right, center, justify)
* Use the predefined alignment constants
* Default : document default
alignment TYPE string,
* Set spacing before paragraph to "auto" (boolean)
* Use the predefined true/false constants
* Default : document default
spacing_before_auto TYPE i, "boolean
* Set spacing before paragraph
* Integer value, 20 = 1pt
* Default : document default
spacing_before TYPE string,
* Set spacing after paragraph to "auto" (boolean)
* Use the predefined true/false constants
* Default : document default
spacing_after_auto TYPE i, "boolean
* Set spacing after paragraph
* Integer value: 20 = 1pt
* Default : document default
spacing_after TYPE string,
* Set interline in paragraph
* Integer value: 240 = normal interline, 120 = multiple x0.5, 480 = multiple x2
* Default : document default
interline TYPE i,
* Set left indentation in paragraph
* Integer value: 567 = 1cm
* Default : document default
leftindent TYPE string,
* Set right indentation in paragraph
* Integer value: 567 = 1cm
* Default : document default
rightindent TYPE string,
* Set left indentation for first line in paragraph
* Integer value: 567 = 1cm. Negative value allowed
* Default : document default
firstindent TYPE string,
* Add a breakpage before paragraph (boolean)
* Use the predefined true/false constants
* Default : no breakpage
break_before TYPE i,
* Set the hierarchical title level of the paragraph
* 1 for title1, 2 for title2...
* Default : not a hierarchical title
hierarchy_level TYPE i,
* Set the left border of the paragraph
* See class type ty_border for details
* Default : No border
border_left TYPE ty_border,
* Set the top border of the paragraph
* See class type ty_border for details
* Default : No border
border_top TYPE ty_border,
* Set the right border of the paragraph
* See class type ty_border for details
* Default : No border
border_right TYPE ty_border,
* Set the bottom border of the paragraph
* See class type ty_border for details
* Default : No border
border_bottom TYPE ty_border,
* Background color to apply to the paragraph
* You can use the predefined font color constants or specify any rgb hexa color code
* Default : document default
bgcolor TYPE string,
END OF ty_paragraph_style_effect,
BEGIN OF ty_list_style,
type TYPE string,
name TYPE string,
END OF ty_list_style,
ty_list_style_table TYPE STANDARD TABLE OF ty_list_style,
BEGIN OF ty_list_object,
id TYPE string,
type TYPE string,
path TYPE string,
END OF ty_list_object,
ty_list_object_table TYPE STANDARD TABLE OF ty_list_object,
BEGIN OF ty_table_style_field,
* Content of the cell
textline TYPE string,
* Character style name
style TYPE string,
* Direct character style effect
style_effect TYPE ty_character_style_effect,
* Paragraph style name
line_style TYPE string,
* Direct paragraph style effect
line_style_effect TYPE ty_paragraph_style_effect,
* Cell background color in hexa RGB
bgcolor TYPE string,
* Set vertical alignment for cell
valign TYPE string,
* Set number of horizontal cell merged
* Start from 2 to merge the next cell with current
* Next cell will be completely ignored
* 0 or 1 to ignore this parameter
merge TYPE i,
* Instead of text, insert an image in the cell
* textline, style, style_effect are ignored
image_id TYPE string,
* For complex cell content, insert xml paragraph fragment
* You cannot insert xml fragment that are not in a (or many) paragraph
* textline, style, style_effect, line_style, line_style_effect, image_id are ignored
xml TYPE string,
END OF ty_table_style_field,
BEGIN OF ty_style_table,
firstcol TYPE i, "boolean, first col is different
firstrow TYPE i, "boolean, first row is different
lastcol TYPE i, "boolean, last col is different
lastrow TYPE i, "boolean, last row is different
nozebra TYPE i, "boolean, no line zebra
novband TYPE i, "boolean, no column zebra
END OF ty_style_table.
METHODS:
*****************************************************************************
* Method constructor
* Constructor method create the word objet and initialize some general data
* - tpl : Empty document to use as a template (docx, dotx, docm, dotm)
* You could use template in SAPWR instead
* Use this syntax : SAPWR:<objname>
* - keep_tpl_content:keep the template content as begin of document content
* (boolean)
* Default : false
* - content : Instead of create docx file from scratch or from template
* create the docx from given docx xstring.
* Must be a valid word document/template
* Fot template, you have to fill "tpl" with template extension (dotx,
* dotm...)
*****************************************************************************
constructor
IMPORTING
tpl TYPE string OPTIONAL
keep_tpl_content TYPE i DEFAULT c_false
content TYPE xstring OPTIONAL,
*****************************************************************************
* Method write_text
* Write any text fragment
* You can specify which character style apply to this fragment
* You can also specify detailed style effect to apply to this fragment
* - textline : the text fragment
* - style : Style name for the text fragment
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect:Detailed style effect to apply to text fragment
* Check documentation of class type ty_character_style_effect
* - line_style: If filled, close the paragraph and apply given paragraph
* style. Be carrefull, you must use "internal" name of the
* style. Generaly, it's the same as external without space
* - line_style_effect:If filled, close the paragraph and apply detailed style
* effect
* Check documentation of class type ty_character_style_effect
* - virtual : Get generated XML fragment instead of buffer it into document
* If you ask this parameter, no xml is written to document
* - invalid_style:Character style name given in importing parameter does not
* exist in document (boolean)
* - invalid_line_style:Paragraph style name given in importing parameter does
* not exist in document (boolean)
*****************************************************************************
write_text
IMPORTING
textline TYPE string
style TYPE string OPTIONAL
style_effect TYPE ty_character_style_effect OPTIONAL
line_style TYPE string OPTIONAL
line_style_effect TYPE ty_paragraph_style_effect OPTIONAL
EXPORTING
virtual TYPE string
invalid_style TYPE i
invalid_line_style TYPE i,
*****************************************************************************
* Method write_line
* Close a paragraph (equivalent to use ENTER in MS Word)
* - style : Style name for the paragraph
* Use only "paragraph" style here.
* you can use predefined style constants
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect:Detailed style effect to apply to paragraph
* Check documentation of class type ty_paragraph_style_effect
* - invalid_style:Paragraph style name given in importing parameter does not
* exist in document (boolean)
* - virtual (input):If filled, given XML fragment is used to write a
* paragraph instead of buffered XML fragment
* - virtual (output):Get generated XML paragraph instead of buffer it into
* document
* If you ask this parameter, no xml is written to document
*****************************************************************************
write_line
IMPORTING
style TYPE string OPTIONAL
style_effect TYPE ty_paragraph_style_effect OPTIONAL
EXPORTING
invalid_style TYPE i
CHANGING
virtual TYPE string OPTIONAL,
*****************************************************************************
* Method write_break
* Insert a break
* - breaktype : Define the type of break to insert (line, page, section)
* Use the predefined breaktype constants
* Default : linebreak
* - write_line: Close current paragraph (boolean)
* Default : false for break line, true for other breaks
* - virtual (input/output): Add a break in a given xml fragment
* If you ask this parameter, no xml is written to document
* Only allowed for brealine and breakpage
*****************************************************************************
write_break
IMPORTING
breaktype TYPE i DEFAULT c_breaktype_line
write_line TYPE i OPTIONAL
CHANGING
virtual TYPE string OPTIONAL,
*****************************************************************************
* Method write_symbol
* Insert a symbol
* - symbol : Define the symbol to insert
* Use the predefined symbol constants
*****************************************************************************
write_symbol
IMPORTING
symbol TYPE string,
*****************************************************************************
* Method write_table
* Write a MS Word table from an abap table
* - content : Datatable to write
* Structure of the table fields can be plain text or like
* ty_table_style_field
* - style : Style name to apply to the table
* Use only "table" style here.
* You can use predefined style constants
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_overwrite:Allow you to redefine some style parameters
* Structure of the parameter : ty_style_table
* You can redefine if first/last line/column is different and
* if there is zebra or vertical band
* - border : Boolean. If no table style is given, display basic border
* Default : true
* - tblwidth : Width of the table
* 9300 correspond to full size for classic portrait page
* Default : min required width for table content
* - virtual : Get generated XML table instead of write it into document
* If you ask this parameter, no xml is written to document
* - invalid_style:Table style name given in importing parameter does not
* exist in document (boolean)
*****************************************************************************
write_table
IMPORTING
content TYPE STANDARD TABLE
style TYPE string OPTIONAL
style_overwrite TYPE ty_style_table OPTIONAL
border TYPE i DEFAULT c_true
tblwidth TYPE i DEFAULT 0
EXPORTING
virtual TYPE string
invalid_style TYPE i,
*****************************************************************************
* Method write_headerfooter
* Create a new header footer. You could define where use this new
* header/footer or use it manually with his ID
* - type : Header or Footer
* You must use the predefined type constants
* Default : header
* - textline : Header/footer content
* - usenow_default:Boolean to define if created header/footer is used in
* current section.
* Default : true
* - usenow_first:Boolean to define if created header/footer is used in
* current section (first page).
* Default : true
* - style : Character style name
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect:Detailed style effect to apply
* Check documentation of class type ty_character_style_effect
* - line_style:Paragraph style name
* Use only "paragraph" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - line_style_effect:Detailed style effect to apply
* Check documentation of class type ty_paragraph_style_effect
* - ID : ID of the new header/footer
* - invalid_style:Character style name given in importing parameter does not
* exist in document (boolean)
* - invalid_line_style:Paragraph style name given in importing parameter does
* not exist in document (boolean)
*****************************************************************************
write_headerfooter
IMPORTING
type TYPE string DEFAULT c_type_header
textline TYPE string
usenow_default TYPE i DEFAULT c_true
usenow_first TYPE i DEFAULT c_true
style TYPE string OPTIONAL
style_effect TYPE ty_character_style_effect OPTIONAL
line_style TYPE string OPTIONAL
line_style_effect TYPE ty_paragraph_style_effect OPTIONAL
EXPORTING
id TYPE string
invalid_style TYPE i
invalid_line_style TYPE i,
*****************************************************************************
* Method set_title #### Obsolete method, please use set_properties ###
* Define title for the document
* - title : title of the document
*****************************************************************************
set_title "obsolete, kept for compatibility
IMPORTING
title TYPE string,
*****************************************************************************
* Method write_newpage #### Obsolete method, please use write_break ###
* Insert a page break
*****************************************************************************
write_newpage, "obsolete, kept for compatibility
*****************************************************************************
* Method write_toc
* Insert a table of content (list of titles in document) or a table of label
* (list of a given specific label in document [figure, table,...])
* Please note that it is the old word 97-2003 toc object
* - default : Default text displayed instead of TOC content
* - label : Name of the label to display toc
* Default : Main document TOC
*****************************************************************************
write_toc
IMPORTING
default TYPE string OPTIONAL
label TYPE string OPTIONAL,
*****************************************************************************
* Method write_note
* Insert a note at end of the page (foot note)
* or at end of the document (end note)
* - text : note to insert.
* - type : foot note or end note
* You must use the predefined note type constant
* Default : foot note
* - style : Style name for the note
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect:Detailed style effect to apply to the note
* Check documentation of class type ty_character_style_effect
* - line_style: Style name for the note
* Use only "paragraph" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - line_style_effect:Detailed style effect to apply to the note
* Check documentation of class type ty_paragraph_style_effect
* - link_style: Style name for the note link in document
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - link_style_effect:Detailed style effect to apply to the note link in document
* Check documentation of class type ty_character_style_effect
* - invalid_style:Character style name given in importing parameter does not
* exist in document (boolean)
* - invalid_link_style:Character style name given in importing parameter does
* not exist in document (boolean)
* - invalid_line_style:Paragraph style name given in importing parameter does
* not exist in document (boolean)
*****************************************************************************
write_note
IMPORTING
text TYPE string
type TYPE i DEFAULT c_notetype_foot
style TYPE string OPTIONAL
style_effect TYPE ty_character_style_effect OPTIONAL
line_style TYPE string OPTIONAL
line_style_effect TYPE ty_paragraph_style_effect OPTIONAL
link_style TYPE string OPTIONAL
link_style_effect TYPE ty_character_style_effect OPTIONAL
EXPORTING
invalid_style TYPE i
invalid_link_style TYPE i
invalid_line_style TYPE i,
*****************************************************************************
* Method write_comment
* Insert a comment at the rigth side of the document
* - text : comment to insert
* - style : Style name for the comment
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect:Detailed style effect to apply to the comment
* Check documentation of class type ty_character_style_effect
* - line_style: Style name for the comment
* Use only "paragraph" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - line_style_effect:Detailed style effect to apply to the comment
* Check documentation of class type ty_paragraph_style_effect
* - head_style: Style name for the comment header
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - head_style_effect:Detailed style effect to apply to the comment header
* Check documentation of class type ty_character_style_effect
* - datum : Date of the comment
* Default : Current date
* - uzeit : Time of the comment
* Default : Current server time
* - author : Author name of the comment
* Default : document author name
* - initials : Initials of the author
* Default : author name
* - invalid_style:Character style name given in importing parameter does not
* exist in document (boolean)
* - invalid_head_style:Character style name given in importing parameter does
* not exist in document (boolean)
* - invalid_line_style:Paragraph style name given in importing parameter does
* not exist in document (boolean)
*****************************************************************************
write_comment
IMPORTING
text TYPE string
style TYPE string OPTIONAL
style_effect TYPE ty_character_style_effect OPTIONAL
line_style TYPE string OPTIONAL
line_style_effect TYPE ty_paragraph_style_effect OPTIONAL
head_style TYPE string OPTIONAL
head_style_effect TYPE ty_character_style_effect OPTIONAL
datum TYPE d DEFAULT sy-datum
uzeit TYPE t DEFAULT sy-uzeit
author TYPE string OPTIONAL
initials TYPE string OPTIONAL
EXPORTING
invalid_style TYPE i
invalid_head_style TYPE i
invalid_line_style TYPE i,
*****************************************************************************
* Method direct_draw
* Draw an object without canvas paperboard.
* This method act like write_text : the object is drawn directly in the
* current paragraph. You have to "write_line" to finally display the object
* Positionning of object could be harder than with canvas
* - type : Type of object to draw
* You must use predefined class constant
* - width : Width of the object
* - height : Height of the object
* - posx : Starting horizontal position of the object.
* Default : Begin of paragraph
* - posy : Starting vertical position of the object.
* Default : Begin of paragraph
* - zindex : Layer where is displayed object
* To display an object over another, simply affect greater zindex
* Default : 100
* - bg_color : Color of the background
* You can use the predefined font color constants or specify
* any rgb hexa color code
* Default : transparent
* - border_color:Color of the border
* You can use the predefined font color constants or specify
* any rgb hexa color code
* Default : document default
* - border_width:Width of the border
* Default : No border
* - unit : Unit of other parameters (width, height, posx, posy, border_width)
* Do not change it if you dont know what you do
* Default : pt
* - text : A text to write inside the object
* - text_style: Style for the text inside the object
* - text_line_style:Line style for the text inside the object
* Default : Normal
* - text_xml : Used to define an xml fragment (must be a valid paragraph)
* to write inside the object
*****************************************************************************
direct_draw
IMPORTING
type TYPE string
width TYPE p
height TYPE p
posx TYPE p OPTIONAL
posy TYPE p OPTIONAL
zindex TYPE i DEFAULT 100
bg_color TYPE string DEFAULT ''
border_color TYPE string OPTIONAL
border_width TYPE p OPTIONAL
unit TYPE string DEFAULT 'pt'
text TYPE string OPTIONAL
text_style TYPE string OPTIONAL
text_line_style TYPE string DEFAULT c_style_normal
text_xml TYPE string OPTIONAL,
*****************************************************************************
* Method draw_init
* Initialize draw CANVAS (the paperboard). All further drawed objects are
* included in this canvas. No one can overflow his size.
* This is working only from Word 2010, but will display a text message
* instead of the canvas in Word 2007.
* - left : Left position to start the canvas (in pt)
* - top : Top position to start the canvas (in pt)
* - width : Length of the canvas
* - height : Height of the canvas
* - bgcolor : Background color of the canvas
* You can use the predefined font color constants
* or specify any rgb hexa color code
* Default : transparent
* - bdcolor : Border color of the canvas
* You can use the predefined font color constants
* or specify any rgb hexa color code
* You must specify both bdcolor & bdwidth to have effect applied
* Default : transparent
* - bdwidth : Border width of the canvas in pt
* You must specify both bdcolor & bdwidth to have effect applied
* Default : none
*****************************************************************************
draw_init
IMPORTING
left TYPE i
top TYPE i
width TYPE i
height TYPE i
bgcolor TYPE string OPTIONAL
bdcolor TYPE string OPTIONAL
bdwidth TYPE f OPTIONAL,
*****************************************************************************
* Method draw
* Draw an object in a canvas (you must create it before with draw_init)
* - object : Type of object to draw
* - left : Left position to start the canvas (in pt)
* - top : Top position to start the canvas (in pt)
* - width : Length of the canvas
* - height : Height of the canvas
* - url : In case of image, url of the picture to load
* You could use image in SAPWR instead
* Use this syntax : SAPWR:<objname>
* - bgcolor : Background color of the object
* You can use the predefined font color constants
* or specify any rgb hexa color code
* Default : transparent for image, white for other objects
* - bdcolor : Border color of the object
* You can use the predefined font color constants
* or specify any rgb hexa color code
* You must specify both bdcolor & bdwidth to have effect applied
* Default : transparent for image, black for other objects
* - bdwidth : Border width of the object in pt
* You must specify both bdcolor & bdwidth to have effect applied
* Default : none for image, 1px for other objects
* - invalid_image:Image to insert does not exist (boolean)
* - ID (input): You could give ID of an existing image in document instead of
* url
* - ID (output): ID of the image in document
*****************************************************************************
draw
IMPORTING
object TYPE i
left TYPE i DEFAULT 0
top TYPE i DEFAULT 0
width TYPE i DEFAULT 0
height TYPE i DEFAULT 0
url TYPE string OPTIONAL
bgcolor TYPE string OPTIONAL
bdcolor TYPE string OPTIONAL
bdwidth TYPE f OPTIONAL
EXPORTING
invalid_image TYPE i
CHANGING
id TYPE string OPTIONAL,
*****************************************************************************
* Method draw_finalize
* Write all the canvas object in document
* Call this method once you have finished your draw all yours objects.
*****************************************************************************
draw_finalize,
*****************************************************************************
* Method insert_custom_field
* Insert a custom field link in the document.
* It is not required that the field exist
* - field : Name of the custom field to insert
*****************************************************************************
insert_custom_field
IMPORTING
field TYPE string,
*****************************************************************************
* Method insert_virtual_field
* Insert a temporary anchor in the document
* The objective of this anchor is to write something here later
* It is usefull when you dont have the content when you write this part,
* but you will have before end of the document
* Use replace_virtual_field to replace the anchor by a viewable content
* - field : Name of the anchor to insert
* - field_as_paragraph:Virtual field is considered as a complete paragraph
* Usefull if you want to replace virtual field by a table
*****************************************************************************
insert_virtual_field
IMPORTING
field TYPE string
field_as_paragraph TYPE i DEFAULT c_false,
*****************************************************************************
* Method replace_virtual_field
* replace an anchor created with insert_virtual_field
* - field : Name of the anchor to replace
* - value : text content to insert
* - value_as_xml:value is not text but xml fragment to insert directly
* If filled, style & style_effet are ignored
* - style : Character style name
* Use only "character" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect:Detailed style effect to apply to text fragment
* Check documentation of class type ty_character_style_effect
* - invalid_style:Character style name given in importing parameter does not
* exist in document (boolean)
*****************************************************************************
replace_virtual_field
IMPORTING
field TYPE string
value TYPE string
value_as_xml TYPE i DEFAULT c_false
style_effect TYPE ty_character_style_effect OPTIONAL
style TYPE string OPTIONAL
EXPORTING
invalid_style TYPE i,
*****************************************************************************
* Method create_custom_field
* Create a custom field in the document properties and assign a value
* - field : Name of the custom field to create
* - value : text content of the field
*****************************************************************************
create_custom_field
IMPORTING
field TYPE string
value TYPE string,
*****************************************************************************
* Method create_character_style
* Create a character style in document for further usage
* - output_name : Name of character style displayed in word
* - style_effect: Detailed style effect
* Check documentation of class type ty_character_style_effect
* - style_ref : Define an existing character style as reference
* - name : Internal name of the created style.
* You have to use this name to apply style from now
* (output name is only usable in word)
* - invalid_style:Character style name given as reference in importing
* parameter does not exist in document (boolean)
*****************************************************************************
create_character_style
IMPORTING
output_name TYPE string
style_effect TYPE ty_character_style_effect
style_ref TYPE string OPTIONAL
EXPORTING
name TYPE string
invalid_style TYPE i,
*****************************************************************************
* Method create_paragraph_style
* Create a paragraph style in document for further usage
* - output_name : Name of paragraph style displayed in word
* - style_effect: Detailed character style effect
* Check documentation of class type ty_character_style_effect
* - line_style_effect: Detailed paragraph style effect
* Check documentation of class type ty_paragraph_style_effect
* - style_ref : Define an existing paragraph style as reference
* - name : Internal name of the created style.
* You have to use this name to apply style from now
* (output name is only usable in word)
* - invalid_style:Paragraph style name given as reference in importing
* parameter does not exist in document (boolean)
*****************************************************************************
create_paragraph_style
IMPORTING
output_name TYPE string
style_effect TYPE ty_character_style_effect
line_style_effect TYPE ty_paragraph_style_effect
style_ref TYPE string OPTIONAL
EXPORTING
name TYPE string
invalid_style TYPE i,
*****************************************************************************
* Method insert_image
* Insert an image as paragraph
* - url : path+name of the image to insert
* You could use image in SAPWR instead
* Optional only if ID supplied
* Use this syntax : SAPWR:<objname>
* If file content is provided, used only to know the file
* name
* - file_content: File content to insert
* - Zoom : Zoom value to apply to the image
* Example : 2 to extend image to 200%, 0.5 to reduce image to 50%
* Default : 1
* - as_paragraph: Write the image alone in a paragraph or with other text
* style & style_effect parameters are ignored if this parameter
* is not true
* Default : true (Alone in a paragraph)
* - Style : Paragraph style to apply to the image
* Use only "paragraph" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect: Detailed style effect to apply
* Check documentation of class type ty_paragraph_style_effect
* - type : Choose type of display
* You must use predefined constant
* Default : inline
* - posx : For float, over and behind image type, you have to specify
* the horizontal image position
* You can use predefined class contant or direct input a
* numerical value
* Default : left
* - posy : For float, over and behind image type, you have to specify
* the vertical image position
* You can use predefined class contant or direct input a
* numerical value
* Default : top
* - margin : For float image type, you can specify a distance between
* image and text
* Default : 0
* - invalid_image:Image to insert does not exist (boolean)
* - invalid_style:Paragraph style name given in importing parameter does
* not exist in document (boolean)
* - virtual : Get generated XML fragment instead of buffer it into document
* If you ask this parameter, no xml is written to document
* - ID (input) : You could give ID of an existing image in document instead of
* url
* - ID (output) : ID of the image in document
*****************************************************************************
insert_image
IMPORTING
url TYPE string OPTIONAL
file_content TYPE xstring OPTIONAL
zoom TYPE f OPTIONAL
as_paragraph TYPE i DEFAULT c_true
style TYPE string OPTIONAL
style_effect TYPE ty_paragraph_style_effect OPTIONAL
type TYPE i DEFAULT c_imgtype_inline
posx TYPE string DEFAULT c_imgposx_left
posy TYPE string DEFAULT c_imgposy_top
margin TYPE i OPTIONAL
EXPORTING
invalid_image TYPE i
invalid_style TYPE i
virtual TYPE string
CHANGING
id TYPE string OPTIONAL,
*****************************************************************************
* Method insert_attachment
* Insert an attached file in the currend document and display it as an icon
* The file could be any type, icon have to be given
* - url : path+name of the file to insert
* You could use file in SAPWR instead
* Use this syntax : SAPWR:<objname>
* If file content is provided, used only to know the file
* name
* - file_content: File content to insert
* - url_img : path+name of the icon of the file to insert
* You could use file in SAPWR instead
* Use this syntax : SAPWR:<objname>
* Optional only if ID_IMG supplied
* - as_paragraph: Write the attachment alone in a paragraph or with other text
* style & style_effect parameters are ignored if this parameter
* is not true
* Default : true (Alone in a paragraph)
* - Style : Paragraph style to apply to the attachment image
* Use only "paragraph" style here.
* Be carrefull, you must use "internal" name of the style
* Generaly, it's the same as external without space
* Default : document default
* - style_effect: Detailed style effect to apply
* Check documentation of class type ty_paragraph_style_effect
* - invalid_image:Icon to insert does not exist (boolean)
* - invalid_file: File to insert does not exist (boolean)
* - invalid_style:Paragraph style name given in importing parameter does
* not exist in document (boolean)
* - virtual : Get generated XML fragment instead of buffer it into document
* If you ask this parameter, no xml is written to document
* - id_img(input):You could give ID of an existing image in document
* instead of url_img
* - id_img(output):ID of the image in document
*****************************************************************************
insert_attachment
IMPORTING
url TYPE string
file_content TYPE xstring OPTIONAL
url_img TYPE string OPTIONAL
as_paragraph TYPE i DEFAULT c_true
style TYPE string OPTIONAL
style_effect TYPE ty_paragraph_style_effect OPTIONAL
EXPORTING
invalid_image TYPE i
invalid_file TYPE i
invalid_style TYPE i
virtual TYPE string
CHANGING
id_img TYPE string OPTIONAL,
*****************************************************************************
* Method set_properties
* Define document properties
* - title : Title of the document
* - author : Creator of the document
* Default : SAP user name (or SAP ID if no name found)
* - description : Description of the document
* - object : Object of the document
* - category : Category of the document
* - keywords : Keywords of the document
* - status : Status of the document
* - creationdate: Creation date of the document
* Default : date of generation
* - creationtime: Creation time of the document
* Default : time of generation
* - revision : Internal revision number
* Default : 1
*****************************************************************************
set_properties
IMPORTING
title TYPE string OPTIONAL
author TYPE string OPTIONAL
description TYPE string OPTIONAL
object TYPE string OPTIONAL
category TYPE string OPTIONAL
keywords TYPE string OPTIONAL
status TYPE string OPTIONAL
creationdate TYPE d OPTIONAL
creationtime TYPE t OPTIONAL
revision TYPE i OPTIONAL,
*****************************************************************************
* Method set_params
* Define options
* - orientation : set page orientation
* you must use predefined orientation constants
* Default : portrait
* - border_left : Set the left border of the section
* See class type ty_border for details
* Default : No border
* - border_top : Set the top border of the section
* See class type ty_border for details
* Default : No border
* - border_right : Set the right border of the section
* See class type ty_border for details
* Default : No border
* - border_bottom : Set the bottom border of the section
* See class type ty_border for details
* Default : No border
*****************************************************************************
set_params
IMPORTING
orientation TYPE i DEFAULT c_orient_portrait
border_left TYPE ty_border OPTIONAL
border_top TYPE ty_border OPTIONAL
border_right TYPE ty_border OPTIONAL
border_bottom TYPE ty_border OPTIONAL
nospellcheck TYPE i DEFAULT c_false,
*****************************************************************************
* Method save
* Save created document
* - url : path+name of the saved document
* - local : url is a local path (boolean)
* Default : true
*****************************************************************************
save
IMPORTING
url TYPE string
local TYPE i DEFAULT c_true,
*****************************************************************************
* Method get_docx_file
* Low level method (for advanced user)
* Get the content of the docx
* - xcontent : content of the docx
*****************************************************************************
get_docx_file
EXPORTING
xcontent TYPE xstring,
*****************************************************************************
* Method header_footer_direct_assign
* Low level method (for advanced user)
* Use existing header/footer directly
* You can get header/footer id with method get_list_headerfooter or when
* creating a new header/footer with method write_headerfooter
* - header : ID of the header to use
* - header_first : ID of the header to use for the first page of the section
* - footer : ID of the footer to use
* - footer_first : ID of the footer to use for the first page of the section
* - invalid_header:ID of the header given is invalid (boolean)
* - invalid_footer:ID of the footer given is invalid (boolean)
*****************************************************************************
header_footer_direct_assign
IMPORTING
header TYPE string OPTIONAL
header_first TYPE string OPTIONAL
footer TYPE string OPTIONAL
footer_first TYPE string OPTIONAL
EXPORTING
invalid_header TYPE i
invalid_footer TYPE i,
*****************************************************************************
* Method get_list_style
* Low level method (for advanced user)
* Get list of existing styles
* - style_list : List of styles in current document
*****************************************************************************
get_list_style
EXPORTING
style_list TYPE ty_list_style_table,
*****************************************************************************
* Method get_list_image
* Low level method (for advanced user)
* Get list of existing images
* - image_list : List of images in current document
*****************************************************************************
get_list_image
EXPORTING
image_list TYPE ty_list_object_table,
*****************************************************************************
* Method get_list_headerfooter
* Low level method (for advanced user)
* Get list of existing header / footer
* - headerfooter_list : List of header / footer in current document
*****************************************************************************
get_list_headerfooter
EXPORTING
headerfooter_list TYPE ty_list_object_table,
*****************************************************************************
* Method insert_xml_fragment
* Low level method (for advanced user)
* If some function is missing, you could inject direct xml fragment in the
* current text line with this method.
* Dont forget you will need to use write_line to write this fragment in
* document
* - xml : XML fragment to insert
*****************************************************************************
insert_xml_fragment
IMPORTING
xml TYPE string,
*****************************************************************************
* Method insert_xml
* Low level method (for advanced user)
* If some function is missing, you could inject direct xml in the document
* with this method.
* Current xml fragment stay untouched and could continue to be builded
* - xml : XML code to insert in document
*****************************************************************************
insert_xml
IMPORTING
xml TYPE string.
PRIVATE SECTION.
DATA : mw_docxml TYPE string,
mw_fragxml TYPE string,
mw_imgmaxid TYPE i VALUE 100,
mw_attach TYPE i VALUE 10000,
mo_zip TYPE REF TO cl_abap_zip,
BEGIN OF ms_section,
landscape TYPE i,
continuous TYPE i,
header_first TYPE string,
header TYPE string,
footer_first TYPE string,
footer TYPE string,
border_left TYPE ty_border,
border_top TYPE ty_border,
border_right TYPE ty_border,
border_bottom TYPE ty_border,
END OF ms_section,
mw_section_xml TYPE string,
mw_tpl_section_xml TYPE string,
mt_list_style TYPE ty_list_style_table,
mt_list_object TYPE ty_list_object_table,
mw_author TYPE string.
CONSTANTS : c_basesize TYPE i VALUE 12700.
METHODS :
* Prepare the section xml part
_write_section,
* Read a zip file and return string content
_get_zip_file
IMPORTING
filename TYPE string
EXPORTING
content TYPE string,
* Replace zip file with string content
_update_zip_file
IMPORTING
filename TYPE string
content TYPE string,
* Load a file and return xstring content
_load_file
IMPORTING
filename TYPE string
EXPORTING
xcontent TYPE xstring,
* Load an image into docx structure. Give ID, image res and extension
_load_image
IMPORTING
url TYPE string
file_content TYPE xstring OPTIONAL
EXPORTING
imgres_x TYPE i
imgres_y TYPE i
extension TYPE string
CHANGING
id TYPE string,
* Create a foot/end note
_create_note
IMPORTING
text TYPE string
type TYPE i
style TYPE string OPTIONAL
style_effect TYPE ty_character_style_effect OPTIONAL
line_style TYPE string OPTIONAL
line_style_effect TYPE ty_paragraph_style_effect OPTIONAL
link_style TYPE string OPTIONAL
link_style_effect TYPE ty_character_style_effect OPTIONAL
EXPORTING
invalid_style TYPE i
invalid_line_style TYPE i
id TYPE string,
* Replace xml reserved character by escaped ones
_protect_string
IMPORTING
in TYPE string
EXPORTING
out TYPE string,
* Replace invalid label character by allowed ones
_protect_label
IMPORTING
in TYPE string
EXPORTING
out TYPE string,
* Write character style xml fragment
_build_character_style
IMPORTING
style TYPE string OPTIONAL
style_effect TYPE ty_character_style_effect OPTIONAL
EXPORTING
xml TYPE string
invalid_style TYPE i,
* Write paragraph style xml fragment
_build_paragraph_style
IMPORTING
style TYPE string OPTIONAL
style_effect TYPE ty_paragraph_style_effect OPTIONAL
EXPORTING
xml TYPE string
invalid_style TYPE i,
_get_xml_ns
EXPORTING
xml TYPE string.
ENDCLASS. "cl_word DEFINITION
*----------------------------------------------------------------------*
* CLASS cl_word IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS cl_word IMPLEMENTATION.
METHOD constructor.
DATA : lw_docx TYPE xstring,
lw_extension TYPE string,
lw_file TYPE string,
lw_string TYPE string,
ls_list_style TYPE ty_list_style,
ls_list_object TYPE ty_list_object,
lt_find_result TYPE match_result_tab,
ls_find_result LIKE LINE OF lt_find_result,
lw_url_begin(6) TYPE c.
CREATE OBJECT mo_zip.
IF content IS SUPPLIED AND NOT content IS INITIAL.
lw_docx = content.
ELSEIF tpl IS SUPPLIED AND NOT tpl IS INITIAL.
* Load template document
CALL METHOD _load_file
EXPORTING
filename = tpl
IMPORTING
xcontent = lw_docx.
IF lw_docx IS INITIAL.
MESSAGE 'Cannot open template, please check' TYPE 'A'.
ENDIF.
ELSE.
* Empty docx creation
TRY.
lw_docx = cl_docx_form=>create_form( ).
CATCH cx_openxml_not_allowed
cx_openxml_not_found
cx_openxml_format
cx_docx_form_not_unicode.
MESSAGE 'Cannot create empty doc, please use template' TYPE 'A'.
ENDTRY.
ENDIF.
* Load docx into zip object
CALL METHOD mo_zip->load
EXPORTING
zip = lw_docx
EXCEPTIONS
zip_parse_error = 1
OTHERS = 2.
* Keep actual content
IF keep_tpl_content = c_true.
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/document.xml' "#EC NOTEXT
IMPORTING
content = lw_file.
FIND FIRST OCCURRENCE OF '<w:body' IN lw_file
MATCH OFFSET sy-fdpos IGNORING CASE.
IF sy-subrc = 0.
lw_file = lw_file+sy-fdpos.
FIND FIRST OCCURRENCE OF '>' IN lw_file
MATCH OFFSET sy-fdpos IGNORING CASE.
ENDIF.
IF sy-subrc = 0.
sy-fdpos = sy-fdpos + 1.
lw_file = lw_file+sy-fdpos.
FIND FIRST OCCURRENCE OF '</w:body' IN lw_file
MATCH OFFSET sy-fdpos IGNORING CASE.
ENDIF.
IF sy-subrc = 0.
mw_docxml = lw_file(sy-fdpos).
FIND ALL OCCURRENCES OF '<w:sectPr' IN mw_docxml
MATCH OFFSET sy-fdpos IGNORING CASE.
IF sy-subrc = 0.
mw_tpl_section_xml = mw_docxml+sy-fdpos.
mw_docxml = mw_docxml(sy-fdpos).
ENDIF.
ELSE.
MESSAGE 'Cannot parse template content: empty document created'
TYPE 'I'.
ENDIF.
ENDIF.
* Remove docx body
CALL METHOD mo_zip->delete
EXPORTING
name = 'word/document.xml' "#EC NOTEXT
EXCEPTIONS
zip_index_error = 1
OTHERS = 2.
* If modele is a template, transform it to document
IF tpl IS SUPPLIED AND NOT tpl IS INITIAL.
lw_url_begin = tpl.
IF lw_url_begin = c_sapwr_prefix.
SELECT SINGLE value INTO lw_extension
FROM wwwparams
WHERE relid = 'MI'
AND objid = tpl+6
AND name = 'fileextension'.
IF NOT lw_extension IS INITIAL AND lw_extension(1) = '.'.
lw_extension = lw_extension+1.
ENDIF.
ELSE.
FIND ALL OCCURRENCES OF '.' IN tpl MATCH OFFSET sy-fdpos.
IF sy-subrc = 0.
sy-fdpos = sy-fdpos + 1.
lw_extension = tpl+sy-fdpos.
ELSE.
lw_extension = tpl.
ENDIF.
ENDIF.
TRANSLATE lw_extension TO LOWER CASE.
* Template without macro
IF lw_extension = 'dotx'.
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml' "#EC NOTEXT
IMPORTING
content = lw_file.
REPLACE ALL OCCURRENCES OF 'wordprocessingml.template'
IN lw_file WITH 'wordprocessingml.document'. "#EC NOTEXT
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
* Template with macro
ELSEIF lw_extension = 'dotm'.
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml' "#EC NOTEXT
IMPORTING
content = lw_file.
REPLACE ALL OCCURRENCES OF 'template.macroEnabledTemplate'
IN lw_file WITH 'document.macroEnabled'. "#EC NOTEXT
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
ENDIF.
ENDIF.
* Get author name
CLEAR mw_author.
SELECT SINGLE name_textc INTO mw_author
FROM user_addr
WHERE bname = sy-uname. "#EC WARNOK
IF sy-subrc NE 0.
mw_author = sy-uname.
ENDIF.
* Set Author, Creation date and Version number properties
CALL METHOD set_properties
EXPORTING
author = mw_author
creationdate = sy-datlo
creationtime = sy-timlo
revision = 1.
* Get style file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/styles.xml' "#EC NOTEXT
IMPORTING
content = lw_file.
* Scan style file to search all styles
FIND ALL OCCURRENCES OF REGEX '<w:style ([^>]*)>'
IN lw_file RESULTS lt_find_result
IGNORING CASE.
LOOP AT lt_find_result INTO ls_find_result.
CLEAR ls_list_style.
FIND FIRST OCCURRENCE OF REGEX 'w:styleId="([^"]*)"'
IN SECTION OFFSET ls_find_result-offset
LENGTH ls_find_result-length
OF lw_file
SUBMATCHES lw_string
IGNORING CASE.
IF sy-subrc NE 0.
CONTINUE.
ENDIF.
ls_list_style-name = lw_string.
FIND FIRST OCCURRENCE OF REGEX 'w:type="(paragraph|character|numbering|table)"'
IN SECTION OFFSET ls_find_result-offset
LENGTH ls_find_result-length
OF lw_file
SUBMATCHES lw_string
IGNORING CASE.
IF sy-subrc = 0.
ls_list_style-type = lw_string.
ENDIF.
APPEND ls_list_style TO mt_list_style.
ENDLOOP.
SORT mt_list_style BY type name.
* Get relation file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels' "#EC NOTEXT
IMPORTING
content = lw_file.
* Scan relation file to get all objects
FIND ALL OCCURRENCES OF REGEX '<Relationship ([^>]*)/>'
IN lw_file RESULTS lt_find_result
IGNORING CASE.
LOOP AT lt_find_result INTO ls_find_result.
CLEAR ls_list_object.
* Search id of object
FIND FIRST OCCURRENCE OF REGEX 'Id="([^"]*)"'
IN SECTION OFFSET ls_find_result-offset
LENGTH ls_find_result-length
OF lw_file
SUBMATCHES lw_string
IGNORING CASE.
IF sy-subrc NE 0.
CONTINUE.
ENDIF.
ls_list_object-id = lw_string.
* Search type of object
FIND FIRST OCCURRENCE OF REGEX 'Type=".*(footer|header|image)"'
IN SECTION OFFSET ls_find_result-offset
LENGTH ls_find_result-length
OF lw_file
SUBMATCHES lw_string
IGNORING CASE.
IF sy-subrc NE 0.
CONTINUE.
ENDIF.
ls_list_object-type = lw_string.
* Search path of file
FIND FIRST OCCURRENCE OF REGEX 'Target="([^"]*)"'
IN SECTION OFFSET ls_find_result-offset
LENGTH ls_find_result-length
OF lw_file
SUBMATCHES lw_string
IGNORING CASE.
IF sy-subrc NE 0.
CONTINUE.
ENDIF.
CONCATENATE 'word/' lw_string INTO ls_list_object-path.
APPEND ls_list_object TO mt_list_object.
ENDLOOP.
SORT mt_list_object BY type id.
ENDMETHOD. "constructor
METHOD write_text.
DATA : lw_style TYPE string,
lw_string TYPE string,
lw_field TYPE string.
DATA : lt_find_result TYPE match_result_tab,
ls_find_result LIKE LINE OF lt_find_result,
lw_off TYPE i,
lw_len TYPE i.
* Get font style section
IF style_effect IS SUPPLIED OR NOT style IS INITIAL.
CALL METHOD _build_character_style
EXPORTING
style = style
style_effect = style_effect
IMPORTING
xml = lw_style
invalid_style = invalid_style.
ENDIF.
* Escape invalid character
CALL METHOD _protect_string
EXPORTING
in = textline
IMPORTING
out = lw_string.
* Replace fields in content
IF lw_string CS '##FIELD#'.
* Regex to search all fields to replace
FIND ALL OCCURRENCES OF REGEX '##FIELD#([A-Z ])*##' IN lw_string RESULTS lt_find_result.
SORT lt_find_result BY offset DESCENDING.
* For each result, replace
LOOP AT lt_find_result INTO ls_find_result.
lw_off = ls_find_result-offset + 8.
lw_len = ls_find_result-length - 10.
CASE lw_string+ls_find_result-offset(ls_find_result-length).
WHEN c_field_pagecount OR c_field_pagetotal.
CONCATENATE lw_string+lw_off(lw_len) '\* Arabic'
INTO lw_field SEPARATED BY space.
WHEN c_field_filename.
CONCATENATE lw_string+lw_off(lw_len) '\p'
INTO lw_field SEPARATED BY space.
WHEN c_field_creationdate OR c_field_moddate
OR c_field_todaydate.
CONCATENATE lw_string+lw_off(lw_len)
'\@ "dd/MM/yyyy"'
INTO lw_field SEPARATED BY space.
WHEN OTHERS.
lw_field = lw_string+lw_off(lw_len).
ENDCASE.
CONCATENATE '<w:fldSimple w:instr="'
lw_field
' \* MERGEFORMAT"/>'
INTO lw_field RESPECTING BLANKS.
REPLACE lw_string+ls_find_result-offset(ls_find_result-length)
IN lw_string WITH lw_field.
ENDLOOP.
ENDIF.
* Replace label anchor by it's value
IF NOT style_effect-label IS INITIAL AND lw_string CS c_label_anchor.
CALL METHOD _protect_label
EXPORTING
in = style_effect-label
IMPORTING
out = lw_field.
CONCATENATE '<w:fldSimple w:instr=" SEQ '
lw_field
' \* ARABIC "/>'
INTO lw_field RESPECTING BLANKS.
REPLACE c_label_anchor IN lw_string WITH lw_field.
ENDIF.
IF virtual IS SUPPLIED.
CONCATENATE '<w:r>'
lw_style
'<w:t xml:space="preserve">'
lw_string
'</w:t>'
'</w:r>'
INTO virtual RESPECTING BLANKS.
IF ( line_style IS SUPPLIED AND line_style IS NOT INITIAL )
OR ( line_style_effect IS SUPPLIED
AND line_style_effect IS NOT INITIAL ).
CALL METHOD write_line
EXPORTING
style = line_style
style_effect = line_style_effect
IMPORTING
invalid_style = invalid_line_style
CHANGING
virtual = virtual.
ENDIF.
RETURN.
ELSE.
CONCATENATE mw_fragxml
'<w:r>'
lw_style
'<w:t xml:space="preserve">'
lw_string
'</w:t>'
'</w:r>'
INTO mw_fragxml RESPECTING BLANKS.
IF ( line_style IS SUPPLIED AND line_style IS NOT INITIAL )
OR ( line_style_effect IS SUPPLIED
AND line_style_effect IS NOT INITIAL ).
CALL METHOD write_line
EXPORTING
style = line_style
style_effect = line_style_effect
IMPORTING
invalid_style = invalid_line_style.
ENDIF.
ENDIF.
ENDMETHOD. "write_text
METHOD write_line.
DATA : lw_style TYPE string.
CLEAR lw_style.
CALL METHOD _build_paragraph_style
EXPORTING
style = style
style_effect = style_effect
IMPORTING
xml = lw_style
invalid_style = invalid_style.
IF virtual IS SUPPLIED.
IF virtual IS INITIAL.
CONCATENATE mw_docxml
'<w:p>'
lw_style
mw_fragxml
'</w:p>'
INTO virtual.
CLEAR mw_fragxml.
ELSE.
CONCATENATE '<w:p>'
lw_style
virtual
'</w:p>'
INTO virtual.
ENDIF.
ELSE.
CONCATENATE mw_docxml
'<w:p>'
lw_style
mw_fragxml
'</w:p>'
INTO mw_docxml.
CLEAR mw_fragxml.
ENDIF.
ENDMETHOD. "write_line
METHOD write_table.
DATA : ls_content TYPE REF TO data,
lw_type(1) TYPE c, "#EC NEEDED
lw_lines TYPE i,
lw_cols TYPE i,
lw_col TYPE i,
lw_col_inc TYPE i,
lw_style_table TYPE i,
lw_xml TYPE string,
lw_tblwidth TYPE string,
lw_merge TYPE string,
lw_string TYPE string,
lw_style TYPE string,
lw_stylep TYPE string.
FIELD-SYMBOLS <field> TYPE any.
FIELD-SYMBOLS <field_style> TYPE ty_table_style_field.
FIELD-SYMBOLS <line> TYPE any.
CREATE DATA ls_content LIKE LINE OF content.
ASSIGN ls_content->* TO <line>.
IF sy-subrc NE 0.
RETURN.
ENDIF.
* count number of lines and columns of the table
DESCRIBE TABLE content LINES lw_lines.
IF lw_lines = 0.
RETURN.
ENDIF.
DESCRIBE FIELD <line> TYPE lw_type COMPONENTS lw_cols.
IF lw_cols = 0.
RETURN.
ENDIF.
* search if data table is simple or have style infos for each field
ASSIGN COMPONENT 1 OF STRUCTURE <line> TO <field>.
IF sy-subrc NE 0.
RETURN.
ENDIF.
DESCRIBE FIELD <field> TYPE lw_type COMPONENTS lw_style_table.
* Write table properties
CLEAR lw_xml.
CONCATENATE '<w:tbl>'
'<w:tblPr>'
INTO lw_xml.
" Styled table : define style
IF style IS SUPPLIED AND NOT style IS INITIAL.
READ TABLE mt_list_style WITH KEY type = c_type_table
name = style
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CONCATENATE lw_xml
'<w:tblStyle w:val="'
style
'"/>'
INTO lw_xml.
ELSE.
invalid_style = c_true.
ENDIF.
* If defined, overwrite style table layout (no effect without table style defined)
CLEAR lw_style.
IF style_overwrite IS SUPPLIED.
lw_tblwidth = style_overwrite-firstrow.
CONDENSE lw_tblwidth NO-GAPS.
CONCATENATE lw_style
' w:firstRow="'
lw_tblwidth
'"'
INTO lw_style RESPECTING BLANKS.
lw_tblwidth = style_overwrite-firstcol.
CONDENSE lw_tblwidth NO-GAPS.
CONCATENATE lw_style
' w:firstColumn="'
lw_tblwidth
'"'
INTO lw_style RESPECTING BLANKS.
lw_tblwidth = style_overwrite-nozebra.
CONDENSE lw_tblwidth NO-GAPS.
CONCATENATE lw_style
' w:noHBand="'
lw_tblwidth
'"'
INTO lw_style RESPECTING BLANKS.
lw_tblwidth = style_overwrite-novband.
CONDENSE lw_tblwidth NO-GAPS.
CONCATENATE lw_style
' w:noVBand="'
lw_tblwidth
'"'
INTO lw_style RESPECTING BLANKS.
lw_tblwidth = style_overwrite-lastrow.
CONDENSE lw_tblwidth NO-GAPS.
CONCATENATE lw_style
' w:lastRow="'
lw_tblwidth
'"'
INTO lw_style RESPECTING BLANKS.
lw_tblwidth = style_overwrite-lastcol.
CONDENSE lw_tblwidth NO-GAPS.
CONCATENATE lw_style
' w:lastColumn="'
lw_tblwidth
'"'
INTO lw_style RESPECTING BLANKS.
CONCATENATE lw_xml
'<w:tblLook'
lw_style
'/>'
INTO lw_xml RESPECTING BLANKS.
CLEAR lw_style.
ENDIF.
ENDIF.
* Default not styled table : add border
IF NOT style IS SUPPLIED.
IF border = c_true.
CONCATENATE lw_xml
'<w:tblBorders>'
'<w:top w:color="auto" w:space="0" w:sz="4" w:val="single"/>'
'<w:left w:color="auto" w:space="0" w:sz="4" w:val="single"/>'
'<w:bottom w:color="auto" w:space="0" w:sz="4" w:val="single"/>'
'<w:right w:color="auto" w:space="0" w:sz="4" w:val="single"/>'
'<w:insideH w:color="auto" w:space="0" w:sz="4" w:val="single"/>'
'<w:insideV w:color="auto" w:space="0" w:sz="4" w:val="single"/>'
'</w:tblBorders>'
INTO lw_xml.
ENDIF.
ENDIF.
* Define table width
lw_tblwidth = tblwidth.
CONDENSE lw_tblwidth NO-GAPS.
IF tblwidth = 0.
* If no table width given, set it to "auto"
CONCATENATE lw_xml
'<w:tblW w:w="'
lw_tblwidth
'" w:type="auto"/>'
'</w:tblPr>'
INTO lw_xml.
ELSE.
CONCATENATE lw_xml
'<w:tblW w:w="'
lw_tblwidth
'" w:type="dxa"/>'
'</w:tblPr>'
INTO lw_xml.
ENDIF.
* Fill table content
LOOP AT content INTO <line>.
CONCATENATE lw_xml
'<w:tr>'
INTO lw_xml.
lw_col = 1.
DO lw_cols TIMES.
lw_col_inc = 1.
*--Filling the cell
IF lw_style_table = 0. "fields are plain text
CONCATENATE lw_xml
'<w:tc>'
INTO lw_xml.
ASSIGN COMPONENT lw_col OF STRUCTURE <line> TO <field>.
lw_string = <field>.
CALL METHOD write_text
EXPORTING
textline = lw_string
IMPORTING
virtual = lw_string.
CONCATENATE lw_xml
'<w:p>'
lw_string
'</w:p>'
INTO lw_xml.
ELSE. " fields have ty_table_style_field structure, apply styles
ASSIGN COMPONENT lw_col OF STRUCTURE <line> TO <field_style>.
IF sy-subrc NE 0. "Occurs when merged cell
EXIT. "exit do
ENDIF.
CONCATENATE lw_xml
'<w:tc>'
INTO lw_xml.
CLEAR : lw_style, lw_stylep.
IF NOT <field_style>-bgcolor IS INITIAL.
CONCATENATE lw_style
'<w:shd w:fill="'
<field_style>-bgcolor
'"/>'
INTO lw_style.
ENDIF.
IF NOT <field_style>-valign IS INITIAL.
CONCATENATE lw_style
'<w:vAlign w:val="'
<field_style>-valign
'"/>'
INTO lw_style.
ENDIF.
IF <field_style>-merge > 1.
lw_col_inc = <field_style>-merge.
lw_merge = <field_style>-merge.
CONDENSE lw_merge NO-GAPS.
CONCATENATE lw_style
'<w:gridSpan w:val="'
lw_merge
'"/>'
INTO lw_style.
ENDIF.
IF NOT lw_style IS INITIAL.
CONCATENATE '<w:tcPr>' lw_style '</w:tcPr>' INTO lw_style.
ENDIF.
CLEAR lw_string.
IF NOT <field_style>-xml IS INITIAL.
CONCATENATE lw_xml
lw_style
<field_style>-xml
INTO lw_xml.
ELSEIF NOT <field_style>-image_id IS INITIAL.
CLEAR lw_string.
CALL METHOD insert_image
EXPORTING
style = <field_style>-line_style
style_effect = <field_style>-line_style_effect
IMPORTING
virtual = lw_string
CHANGING
id = <field_style>-image_id.
CONCATENATE lw_xml
lw_style
lw_string
INTO lw_xml.
ELSE.
CALL METHOD write_text
EXPORTING
textline = <field_style>-textline
style_effect = <field_style>-style_effect
style = <field_style>-style
IMPORTING
virtual = lw_string.
IF NOT <field_style>-line_style IS INITIAL
OR NOT <field_style>-line_style_effect IS INITIAL.
CALL METHOD _build_paragraph_style
EXPORTING
style = <field_style>-line_style
style_effect = <field_style>-line_style_effect
IMPORTING
xml = lw_stylep.
ENDIF.
CONCATENATE lw_xml
lw_style
'<w:p>'
lw_stylep
lw_string
'</w:p>'
INTO lw_xml.
ENDIF.
ENDIF.
CONCATENATE lw_xml '</w:tc>' INTO lw_xml.
lw_col = lw_col + lw_col_inc.
ENDDO.
CONCATENATE lw_xml '</w:tr>' INTO lw_xml.
ENDLOOP.
CONCATENATE lw_xml
'</w:tbl>'
INTO lw_xml.
IF virtual IS SUPPLIED.
virtual = lw_xml.
ELSE.
CONCATENATE mw_docxml
lw_xml
INTO mw_docxml.
ENDIF.
ENDMETHOD. "write_table
METHOD write_newpage.
write_break( breaktype = c_breaktype_page ).
ENDMETHOD. "write_newpage
METHOD write_toc.
DATA : lw_default TYPE string,
lw_content TYPE string.
* Classic TOC
IF label IS INITIAL.
lw_default = '--== Table of content - please refresh ==--'.
lw_content = '\o "1-9"'.
* Table of content for specific label (table, figure, ...)
ELSE.
CONCATENATE '--== Table of '
label
' - please refresh ==--'
INTO lw_default RESPECTING BLANKS.
CALL METHOD _protect_label
EXPORTING
in = label
IMPORTING
out = lw_content.
CONCATENATE '\h \h \c "'
lw_content
'"'
INTO lw_content.
ENDIF.
* If specified, use given default text
IF NOT default IS INITIAL.
lw_default = default.
ENDIF.
* Write TOC
CONCATENATE mw_docxml
'<w:p>'
'<w:r><w:fldChar w:fldCharType="begin"/></w:r>'
'<w:r><w:instrText> TOC '
lw_content
' </w:instrText></w:r>'
'</w:p>'
* Add a default text for initial TOC value
'<w:p>'
'<w:pPr><w:jc w:val="center"/></w:pPr>'
'<w:r>'
'<w:fldChar w:fldCharType="separate"/></w:r>'
'<w:r>'
'<w:rPr><w:sz w:val="36"/><w:szCs w:val="36"/></w:rPr>'
'<w:t>'
lw_default
'</w:t></w:r>'
'</w:p>'
'<w:p>'
'<w:r><w:fldChar w:fldCharType="end"/></w:r>'
'</w:p>'
INTO mw_docxml RESPECTING BLANKS.
ENDMETHOD. "write_toc
METHOD write_note.
DATA : ls_link_style_effect TYPE ty_character_style_effect,
ls_line_style_effect TYPE ty_paragraph_style_effect,
lw_style TYPE string,
lw_string TYPE string,
lw_id TYPE string.
* Define a default style for link
ls_link_style_effect = link_style_effect.
IF link_style IS INITIAL AND ls_link_style_effect IS INITIAL.
ls_link_style_effect-sup = c_true.
ENDIF.
* Define a default style for footnote
ls_line_style_effect = line_style_effect.
IF line_style IS INITIAL AND ls_line_style_effect IS INITIAL.
ls_line_style_effect-spacing_before = '0'.
ls_line_style_effect-spacing_after = '0'.
ls_line_style_effect-interline = 240.
ENDIF.
* Create a new footnote
CALL METHOD _create_note
EXPORTING
text = text
type = type
style = style
style_effect = style_effect
line_style = line_style
line_style_effect = ls_line_style_effect
link_style = link_style
link_style_effect = ls_link_style_effect
IMPORTING
invalid_style = invalid_style
invalid_line_style = invalid_line_style
id = lw_id.
IF lw_id IS INITIAL.
RETURN.
ENDIF.
* Prepare style for the footnote link
CALL METHOD _build_character_style
EXPORTING
style = link_style
style_effect = ls_link_style_effect
IMPORTING
xml = lw_style
invalid_style = invalid_link_style.
* Now insert note in document
IF type = c_notetype_foot.
lw_string = '<w:footnoteReference w:id="'.
ELSEIF type = c_notetype_end.
lw_string = '<w:endnoteReference w:id="'.
ENDIF.
CONCATENATE mw_fragxml
'<w:r>'
lw_style
lw_string
lw_id
'"/>'
'</w:r>'
INTO mw_fragxml.
ENDMETHOD. "write_footnote
METHOD write_comment.
DATA : lw_file TYPE string,
lw_string TYPE string,
lw_id TYPE string,
lw_text TYPE string,
lw_xmlns TYPE string,
lw_head_style TYPE string,
lw_line_style TYPE string,
ls_head_style_effect TYPE ty_character_style_effect,
lw_author TYPE string,
lw_initials TYPE string.
READ TABLE mo_zip->files WITH KEY name = 'word/comments.xml'
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
* If comment file exists, load the file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/comments.xml'
IMPORTING
content = lw_file.
ELSE.
* If comments file doesnt exist, declare it and create it
* Add comments in content_types
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml'
IMPORTING
content = lw_file.
CONCATENATE '<Override'
' ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"'
' PartName="/word/comments.xml"/></Types>'
INTO lw_string RESPECTING BLANKS.
REPLACE '</Types>' WITH lw_string
INTO lw_file.
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
* Add comments in relation file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
IMPORTING
content = lw_file.
* Create comments relation ID
DO.
lw_id = sy-index.
CONDENSE lw_id NO-GAPS.
CONCATENATE 'rId' lw_id INTO lw_id. "#EC NOTEXT
CONCATENATE 'Id="' lw_id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add relation
CONCATENATE '<Relationship Target="comments.xml"'
' Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"'
' Id="'
lw_id
'"/>'
'</Relationships>'
INTO lw_string RESPECTING BLANKS.
REPLACE '</Relationships>' WITH lw_string INTO lw_file.
* Update relation file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
content = lw_file.
CALL METHOD _get_xml_ns
IMPORTING
xml = lw_xmlns.
* Create empty comments file
CONCATENATE '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
"cl_abap_char_utilities=>cr_lf
cl_abap_char_utilities=>newline
'<w:comments '
lw_xmlns
'>'
'</w:comments>'
INTO lw_file RESPECTING BLANKS.
ENDIF.
* Search available comment id
DO.
"sy-index = sy-index + 4.
lw_id = sy-index.
CONDENSE lw_id NO-GAPS.
CONCATENATE 'w:id="' lw_id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add blank at start of note
lw_text = text.
IF lw_text IS INITIAL OR lw_text(1) NE space.
CONCATENATE space lw_text INTO lw_text RESPECTING BLANKS.
ENDIF.
CALL METHOD write_text
EXPORTING
textline = lw_text
style_effect = style_effect
style = style
IMPORTING
virtual = lw_text
invalid_style = invalid_style.
* Define default style for comment head
ls_head_style_effect = head_style_effect.
IF ls_head_style_effect IS INITIAL AND head_style IS INITIAL.
ls_head_style_effect-bold = c_true.
ENDIF.
CALL METHOD _build_character_style
EXPORTING
style = head_style
style_effect = ls_head_style_effect
IMPORTING
xml = lw_head_style
invalid_style = invalid_head_style.
IF NOT line_style_effect IS INITIAL OR NOT line_style IS INITIAL.
CALL METHOD _build_paragraph_style
EXPORTING
style = line_style
style_effect = line_style_effect
IMPORTING
xml = lw_line_style
invalid_style = invalid_line_style.
ENDIF.
* Define author property
IF author IS INITIAL.
lw_author = mw_author.
ELSE.
lw_author = author.
ENDIF.
* Define initial property
IF initials IS INITIAL.
lw_initials = lw_author.
ELSE.
lw_initials = initials.
ENDIF.
CONCATENATE '<w:comment w:initials="'
lw_initials
'"'
' w:date="'
datum(4)
'-'
datum+4(2)
'-'
datum+6(2)
'T'
uzeit(2)
':'
uzeit+2(2)
':'
uzeit+4(2)
'Z"'
' w:author="'
lw_author
'"'
' w:id="'
lw_id
'">'
'<w:p>'
lw_line_style
'<w:r>'
lw_head_style
'<w:annotationRef/>'
'</w:r>'
lw_text
'</w:p>'
'</w:comment>'
'</w:comments>'
INTO lw_string RESPECTING BLANKS.
REPLACE '</w:comments>' WITH lw_string INTO lw_file.
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/comments.xml'
content = lw_file.
* Finally insert reference to comment in current text fragment
CONCATENATE mw_fragxml
'<w:r><w:commentReference w:id="'
lw_id
'"/></w:r>'
INTO mw_fragxml.
ENDMETHOD. "write_comment
METHOD direct_draw.
DATA : lw_texte TYPE string,
lw_style TYPE string,
lw_string TYPE string.
* Prepare text content
IF text_xml IS NOT INITIAL.
lw_texte = text_xml.
ELSEIF text IS NOT INITIAL.
CALL METHOD write_text
EXPORTING
textline = text
style = text_style
line_style = text_line_style
IMPORTING
virtual = lw_texte.
ENDIF.
IF NOT lw_texte IS INITIAL.
CONCATENATE '<v:textbox>'
'<w:txbxContent>'
lw_texte
'</w:txbxContent>'
'</v:textbox>'
INTO lw_texte.
ENDIF.
* Prepare object style
lw_string = posx.
CONDENSE lw_string NO-GAPS.
CONCATENATE ' style="'
'position:absolute;'
'margin-left:'
lw_string
unit
';'
INTO lw_style RESPECTING BLANKS.
lw_string = posy.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'margin-top:'
lw_string
unit
';'
INTO lw_style RESPECTING BLANKS.
lw_string = width.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'width:'
lw_string
unit
';'
INTO lw_style RESPECTING BLANKS.
lw_string = height.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'height:'
lw_string
unit
';'
INTO lw_style RESPECTING BLANKS.
lw_string = zindex.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'z-index:'
lw_string
';"'
INTO lw_style RESPECTING BLANKS.
IF bg_color IS INITIAL.
CONCATENATE lw_style
' filled="f"'
INTO lw_style RESPECTING BLANKS.
ELSE.
CONCATENATE lw_style
' fillcolor="'
bg_color
'"'
INTO lw_style RESPECTING BLANKS.
ENDIF.
IF border_width IS INITIAL.
CONCATENATE lw_style
' stroked="f"'
INTO lw_style RESPECTING BLANKS.
ELSEIF NOT border_color IS INITIAL.
CONCATENATE lw_style
' strokecolor="'
border_color
'"'
INTO lw_style RESPECTING BLANKS.
ENDIF.
lw_string = border_width.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
' strokeweight="'
lw_string
unit
'"'
INTO lw_style RESPECTING BLANKS.
CONCATENATE mw_fragxml
'<w:r>'
'<w:pict>'
'<v:'
type
lw_style
'>'
lw_texte
'</v:'
type
'>'
'</w:pict>'
'</w:r>'
INTO mw_fragxml RESPECTING BLANKS.
ENDMETHOD. "direct_draw
METHOD draw_init.
DATA : lw_style TYPE string,
lw_width TYPE i,
lw_string TYPE string,
lw_string_x TYPE string,
lw_string_y TYPE string,
lw_string_w TYPE string,
lw_string_h TYPE string
.
CLEAR mw_fragxml.
CLEAR lw_style.
IF bgcolor IS SUPPLIED AND NOT bgcolor IS INITIAL.
CONCATENATE lw_style
'<wpc:bg>'
'<a:solidFill>'
'<a:srgbClr val="'
bgcolor
'" />'
'</a:solidFill>'
'</wpc:bg>'
INTO lw_style.
ENDIF.
IF bdcolor IS SUPPLIED AND NOT bdcolor IS INITIAL
AND bdwidth IS SUPPLIED AND NOT bdwidth IS INITIAL.
lw_width = c_basesize * bdwidth.
lw_string = lw_width.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'<wpc:whole>'
'<a:ln w="'
lw_string
'">'
'<a:solidFill>'
'<a:srgbClr val="'
bdcolor
'" />'
'</a:solidFill>'
'</a:ln>'
'</wpc:whole>'
INTO lw_style.
ENDIF.
lw_string_x = lw_width = c_basesize * left.
CONDENSE lw_string_x NO-GAPS.
lw_string_y = lw_width = c_basesize * top.
CONDENSE lw_string_y NO-GAPS.
lw_string_w = lw_width = c_basesize * width.
CONDENSE lw_string_w NO-GAPS.
lw_string_h = lw_width = c_basesize * height.
CONDENSE lw_string_h NO-GAPS.
CONCATENATE '<w:r>'
'<mc:AlternateContent>'
'<mc:Choice Requires="wpc">'
'<w:drawing>'
'<wp:anchor distR="0" distL="0" distB="0" distT="0" allowOverlap="0" layoutInCell="1" locked="0" behindDoc="1" relativeHeight="0" simplePos="0">'
'<wp:simplePos y="0" x="0"/>'
'<wp:positionH relativeFrom="column">'
'<wp:posOffset>'
lw_string_x
'</wp:posOffset>'
'</wp:positionH>'
'<wp:positionV relativeFrom="paragraph">'
'<wp:posOffset>'
lw_string_y
'</wp:posOffset>'
'</wp:positionV>'
'<wp:extent cy="'
lw_string_h
'" cx="'
lw_string_w
'"/>'
'<wp:wrapNone/>'
'<wp:docPr name="Draw container" id="3"/>'
'<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">'
'<a:graphicData uri="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas">'
'<wpc:wpc>'
lw_style
INTO mw_fragxml RESPECTING BLANKS.
ENDMETHOD. "draw_init
METHOD draw.
DATA : lw_width TYPE i,
lw_string_x TYPE string,
lw_string_y TYPE string,
lw_string_w TYPE string,
lw_string_h TYPE string,
lw_style TYPE string,
lw_string TYPE string,
lw_color TYPE string.
lw_string_x = lw_width = c_basesize * left.
CONDENSE lw_string_x NO-GAPS.
lw_string_y = lw_width = c_basesize * top.
CONDENSE lw_string_y NO-GAPS.
lw_string_w = lw_width = c_basesize * width.
CONDENSE lw_string_w NO-GAPS.
lw_string_h = lw_width = c_basesize * height.
CONDENSE lw_string_h NO-GAPS.
CASE object.
WHEN c_draw_image.
invalid_image = c_false.
CALL METHOD _load_image
EXPORTING
url = url
CHANGING
id = id.
IF id IS INITIAL.
invalid_image = c_true.
RETURN.
ENDIF.
CLEAR lw_style.
IF bgcolor IS SUPPLIED AND NOT bgcolor IS INITIAL.
CONCATENATE lw_style
'<a:solidFill>'
'<a:srgbClr val="'
bgcolor
'" />'
'</a:solidFill>'
INTO lw_style.
ENDIF.
IF bdcolor IS SUPPLIED AND NOT bdcolor IS INITIAL
AND bdwidth IS SUPPLIED AND NOT bdwidth IS INITIAL.
lw_width = c_basesize * bdwidth.
lw_string = lw_width.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'<a:ln w="'
lw_string
'">'
'<a:solidFill>'
'<a:srgbClr val="'
bdcolor
'" />'
'</a:solidFill>'
'</a:ln>'
INTO lw_style.
ENDIF.
CONCATENATE mw_fragxml
'<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">'
'<pic:nvPicPr>'
'<pic:cNvPr name="Image" id="1"/>'
'<pic:cNvPicPr>'
'<a:picLocks/>'
'</pic:cNvPicPr>'
'</pic:nvPicPr>'
'<pic:blipFill>'
'<a:blip r:embed="'
id
'">'
'</a:blip>'
'<a:stretch><a:fillRect/></a:stretch>'
'</pic:blipFill>'
'<pic:spPr>'
'<a:xfrm>'
'<a:off y="'
lw_string_y
'" x="'
lw_string_x
'"/>'
'<a:ext cy="'
lw_string_h
'" cx="'
lw_string_w
'"/>'
'</a:xfrm>'
'<a:prstGeom prst="rect"/>'
lw_style
'</pic:spPr>'
'</pic:pic>'
INTO mw_fragxml.
WHEN c_draw_rectangle.
* Default : white rect with 1pt black border
CLEAR lw_style.
IF bgcolor IS SUPPLIED AND NOT bgcolor IS INITIAL.
lw_color = bgcolor.
ELSE.
lw_color = c_color_white.
ENDIF.
CONCATENATE lw_style
'<a:solidFill>'
'<a:srgbClr val="'
lw_color
'" />'
'</a:solidFill>'
INTO lw_style.
IF bdcolor IS SUPPLIED AND NOT bdcolor IS INITIAL.
lw_color = bdcolor.
ELSE.
lw_color = c_color_black.
ENDIF.
IF bdwidth IS SUPPLIED AND NOT bdwidth IS INITIAL.
lw_width = c_basesize * bdwidth.
ELSE.
lw_width = c_basesize.
ENDIF.
lw_string = lw_width.
CONDENSE lw_string NO-GAPS.
CONCATENATE lw_style
'<a:ln w="'
lw_string
'">'
'<a:solidFill>'
'<a:srgbClr val="'
lw_color
'" />'
'</a:solidFill>'
'</a:ln>'
INTO lw_style.
CONCATENATE mw_fragxml
'<wps:wsp>'
'<wps:cNvPr name="Rectangle" id="1"/>'
'<wps:cNvSpPr/>'
'<wps:spPr>'
'<a:xfrm>'
'<a:off y="'
lw_string_y
'" x="'
lw_string_x
'"/>'
'<a:ext cy="'
lw_string_h
'" cx="'
lw_string_w
'"/>'
'</a:xfrm>'
'<a:prstGeom prst="rect"/>'
lw_style
'</wps:spPr>'
'<wps:bodyPr />'
'</wps:wsp>'
INTO mw_fragxml RESPECTING BLANKS.
ENDCASE.
ENDMETHOD. "draw
METHOD draw_finalize.
CONCATENATE mw_docxml
'<w:p>'
mw_fragxml
'</wpc:wpc>'
'</a:graphicData>'
'</a:graphic>'
'</wp:anchor>'
'</w:drawing>'
'</mc:Choice>'
'<mc:Fallback>'
'<w:t>Canvas graphic cannot be loaded (compatible only from Word 2010)</w:t>'
'</mc:Fallback>'
'</mc:AlternateContent>'
'</w:r>'
'</w:p>'
INTO mw_docxml.
CLEAR mw_fragxml.
ENDMETHOD. "draw_finalize
METHOD write_break.
CASE breaktype.
WHEN c_breaktype_line.
IF virtual IS SUPPLIED.
CONCATENATE virtual
'<w:r><w:br/></w:r>'
INTO virtual.
ELSE.
CONCATENATE mw_fragxml
'<w:r><w:br/></w:r>'
INTO mw_fragxml.
ENDIF.
WHEN c_breaktype_page.
IF virtual IS SUPPLIED.
CONCATENATE virtual
'<w:br w:type="page"/>'
INTO virtual.
ELSE.
CONCATENATE mw_fragxml
'<w:br w:type="page"/>'
INTO mw_fragxml.
ENDIF.
WHEN c_breaktype_section.
IF virtual IS SUPPLIED.
sy-subrc = 8.
RETURN.
ENDIF.
CALL METHOD _write_section.
WHEN c_breaktype_section_continuous.
IF virtual IS SUPPLIED.
sy-subrc = 8.
RETURN.
ENDIF.
CALL METHOD _write_section.
ms_section-continuous = c_true.
WHEN OTHERS. "invalid breaktype
sy-subrc = 8.
RETURN.
ENDCASE.
* Write line if required
* But also automatically except for simple break line
IF write_line = c_true
OR ( NOT write_line IS SUPPLIED AND breaktype NE c_breaktype_line ).
CALL METHOD write_line.
ENDIF.
ENDMETHOD. "write_break
METHOD _write_section.
DATA : lw_size TYPE string,
lw_space TYPE string,
lw_substyle TYPE string.
CLEAR mw_section_xml.
* In case of keep template content, first document section is the last
* template section
IF NOT mw_tpl_section_xml IS INITIAL.
mw_section_xml = mw_tpl_section_xml.
CLEAR mw_tpl_section_xml.
CLEAR ms_section.
RETURN.
ENDIF.
* Define header/footer
IF NOT ms_section-header IS INITIAL.
CONCATENATE mw_section_xml
'<w:headerReference w:type="default" r:id="'
ms_section-header
'"/>'
INTO mw_section_xml.
ENDIF.
IF NOT ms_section-footer IS INITIAL.
CONCATENATE mw_section_xml
'<w:footerReference w:type="default" r:id="'
ms_section-footer
'"/>'
INTO mw_section_xml.
ENDIF.
IF NOT ms_section-header_first IS INITIAL.
CONCATENATE mw_section_xml
'<w:headerReference w:type="first" r:id="'
ms_section-header_first
'"/>'
INTO mw_section_xml.
ENDIF.
IF NOT ms_section-footer_first IS INITIAL.
CONCATENATE mw_section_xml
'<w:footerReference w:type="first" r:id="'
ms_section-footer_first
'"/>'
INTO mw_section_xml.
ENDIF.
* Define page orientation
IF ms_section-landscape = c_true.
CONCATENATE mw_section_xml
'<w:pgSz w:w="16838" w:h="11906" w:orient="landscape"/>'
INTO mw_section_xml.
ELSE.
CONCATENATE mw_section_xml
'<w:pgSz w:w="11906" w:h="16838"/>'
INTO mw_section_xml.
ENDIF.
* Border ?
CLEAR lw_substyle.
IF NOT ms_section-border_left-style IS INITIAL
AND NOT ms_section-border_left-width IS INITIAL.
lw_size = ms_section-border_left-width.
CONDENSE lw_size NO-GAPS.
lw_space = ms_section-border_left-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:left w:val="'
ms_section-border_left-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
ms_section-border_left-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT ms_section-border_top-style IS INITIAL
AND NOT ms_section-border_top-width IS INITIAL.
lw_size = ms_section-border_top-width.
CONDENSE lw_size NO-GAPS.
lw_space = ms_section-border_top-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:top w:val="'
ms_section-border_top-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
ms_section-border_top-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT ms_section-border_right-style IS INITIAL
AND NOT ms_section-border_right-width IS INITIAL.
lw_size = ms_section-border_right-width.
CONDENSE lw_size NO-GAPS.
lw_space = ms_section-border_right-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:right w:val="'
ms_section-border_right-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
ms_section-border_right-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT ms_section-border_bottom-style IS INITIAL
AND NOT ms_section-border_bottom-width IS INITIAL.
lw_size = ms_section-border_bottom-width.
CONDENSE lw_size NO-GAPS.
lw_space = ms_section-border_bottom-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:bottom w:val="'
ms_section-border_bottom-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
ms_section-border_bottom-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT lw_substyle IS INITIAL.
CONCATENATE mw_section_xml
'<w:pgBorders w:offsetFrom="page">'
lw_substyle
'</w:pgBorders>'
INTO mw_section_xml RESPECTING BLANKS.
ENDIF.
* Default section values / Standard page
CONCATENATE mw_section_xml
'<w:cols w:space="708"/>'
'<w:docGrid w:linePitch="360"/>'
'<w:pgMar w:top="1417" w:right="1417" w:bottom="1417" w:left="1417" w:header="708" w:footer="708" w:gutter="0"/>'
INTO mw_section_xml.
IF ms_section-continuous = c_true.
CONCATENATE mw_section_xml
'<w:type w:val="continuous"/>'
INTO mw_section_xml.
ENDIF.
IF NOT ms_section-header_first IS INITIAL
OR NOT ms_section-footer_first IS INITIAL.
CONCATENATE mw_section_xml
'<w:titlePg/>'
INTO mw_section_xml.
ENDIF.
CONCATENATE '<w:sectPr>'
mw_section_xml
'</w:sectPr>'
INTO mw_section_xml.
CLEAR ms_section.
ENDMETHOD. "write_section
METHOD write_symbol.
DATA lw_style_effect TYPE ty_character_style_effect.
lw_style_effect-font = c_font_symbol.
CALL METHOD write_text
EXPORTING
textline = symbol
style_effect = lw_style_effect.
ENDMETHOD. "write_symbol
METHOD write_headerfooter.
DATA : lw_filename TYPE string,
lw_string TYPE string,
lw_file TYPE string,
lw_xml TYPE string,
lw_xmlns TYPE string,
lw_style TYPE string,
ls_list_object LIKE LINE OF mt_list_object.
IF type NE c_type_header AND type NE c_type_footer.
RETURN.
ENDIF.
* Build header/footer xml fragment
CALL METHOD write_text
EXPORTING
textline = textline
style_effect = style_effect
style = style
IMPORTING
virtual = lw_xml
invalid_style = invalid_style.
CLEAR lw_style.
IF NOT line_style IS INITIAL OR NOT line_style_effect IS INITIAL.
CALL METHOD _build_paragraph_style
EXPORTING
style = line_style
style_effect = line_style_effect
IMPORTING
xml = lw_style
invalid_style = invalid_line_style.
ENDIF.
CALL METHOD _get_xml_ns
IMPORTING
xml = lw_xmlns.
IF type = c_type_header.
lw_string = 'hdr'.
ELSE.
lw_string = 'ftr'.
ENDIF.
CONCATENATE '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<w:'
lw_string
lw_xmlns
'>'
'<w:p>'
lw_style
lw_xml
'</w:p>'
'</w:'
lw_string
'>'
INTO lw_xml RESPECTING BLANKS.
* Search available header/footer name
DO.
lw_filename = sy-index.
CONCATENATE 'word/'
type
lw_filename
'.xml'
INTO lw_filename.
CONDENSE lw_filename NO-GAPS.
READ TABLE mo_zip->files WITH KEY name = lw_filename
TRANSPORTING NO FIELDS.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add header/footer file into zip
CALL METHOD _update_zip_file
EXPORTING
filename = lw_filename
content = lw_xml.
* Add content type exception for new header/footer
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml'
IMPORTING
content = lw_file.
CONCATENATE '<Override PartName="/'
lw_filename
'" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.'
type
'+xml"/>'
'</Types>'
INTO lw_string.
REPLACE '</Types>' WITH lw_string INTO lw_file.
* Update content type file
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
* Get relation file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
IMPORTING
content = lw_file.
* Create header/footer ID
DO.
id = sy-index.
CONDENSE id NO-GAPS.
CONCATENATE 'rId' id INTO id. "#EC NOTEXT
CONCATENATE 'Id="' id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Update object list
ls_list_object-id = id.
ls_list_object-type = type.
ls_list_object-path = lw_filename.
APPEND ls_list_object TO mt_list_object.
* Add relation
lw_filename = lw_filename+5.
CONCATENATE '<Relationship Id="'
id
'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/'
type
'" Target="'
lw_filename
'"/>'
'</Relationships>'
INTO lw_string.
REPLACE '</Relationships>' WITH lw_string INTO lw_file.
* Update relation file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
content = lw_file.
IF usenow_default = c_true AND type = c_type_header.
CALL METHOD header_footer_direct_assign
EXPORTING
header = id.
ELSEIF usenow_default = c_true AND type = c_type_footer.
CALL METHOD header_footer_direct_assign
EXPORTING
footer = id.
ENDIF.
IF usenow_first = c_true AND type = c_type_header.
CALL METHOD header_footer_direct_assign
EXPORTING
header_first = id.
ELSEIF usenow_first = c_true AND type = c_type_footer.
CALL METHOD header_footer_direct_assign
EXPORTING
footer_first = id.
ENDIF.
ENDMETHOD. "write_headerfooter
METHOD set_title.
set_properties( title = title ).
ENDMETHOD. "set_title
METHOD insert_custom_field.
CONCATENATE mw_fragxml
'<w:fldSimple w:instr=" DOCPROPERTY '
field
' \* MERGEFORMAT "><w:r><w:rPr><w:b/></w:rPr><w:t>Please update field</w:t></w:r></w:fldSimple>'
INTO mw_fragxml RESPECTING BLANKS.
ENDMETHOD. "insert_custom_field
METHOD insert_virtual_field.
IF field_as_paragraph = c_false.
CONCATENATE mw_fragxml
'<w:virtual>'
field
'</w:virtual>'
INTO mw_fragxml.
ELSE.
CONCATENATE mw_docxml
'<w:virtual>'
field
'</w:virtual>'
INTO mw_docxml.
ENDIF.
ENDMETHOD. "insert_virtual_field
METHOD replace_virtual_field.
DATA : lw_field TYPE string,
lw_value TYPE string.
CONCATENATE '<w:virtual>'
field
'</w:virtual>'
INTO lw_field.
IF value_as_xml = c_true.
lw_value = value.
ELSE.
CALL METHOD write_text
EXPORTING
textline = value
style_effect = style_effect
style = style
IMPORTING
virtual = lw_value
invalid_style = invalid_style.
ENDIF.
REPLACE lw_field IN mw_fragxml WITH lw_value IGNORING CASE.
IF sy-subrc NE 0.
REPLACE lw_field IN mw_docxml WITH lw_value IGNORING CASE.
ENDIF.
ENDMETHOD. "replace_virtual_field
METHOD create_custom_field. "not managed
DATA : lw_file TYPE string,
lw_string TYPE string,
lw_id TYPE string.
* If customproperties does not exist, create it
READ TABLE mo_zip->files WITH KEY name = 'docProps/custom.xml'
TRANSPORTING NO FIELDS.
IF sy-subrc NE 0.
* Declare new file in relations
CALL METHOD _get_zip_file
EXPORTING
filename = '_rels/.rels'
IMPORTING
content = lw_file.
* search available id
DO.
lw_id = sy-index.
CONDENSE lw_id NO-GAPS.
CONCATENATE 'rId' lw_id INTO lw_id. "#EC NOTEXT
CONCATENATE 'Id="' lw_id '"' INTO lw_string. "#EC NOTEXT
FIND lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
CONCATENATE '<Relationship Target="docProps/custom.xml"'
' Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"'
' Id="'
lw_id
'"/></Relationships>'
INTO lw_string RESPECTING BLANKS.
REPLACE '</Relationships>' IN lw_file WITH lw_string.
CALL METHOD _update_zip_file
EXPORTING
filename = '_rels/.rels'
content = lw_file.
* Declare new file in content type
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml'
IMPORTING
content = lw_file.
REPLACE '</Types>' IN lw_file
WITH '<Override ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml" PartName="/docProps/custom.xml"/></Types>'.
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
CONCATENATE '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'
'<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"'
' xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">'
'</Properties>'
INTO lw_file RESPECTING BLANKS.
CALL METHOD _update_zip_file
EXPORTING
filename = 'docProps/custom.xml'
content = lw_file.
ENDIF.
* Open custom properties
CALL METHOD _get_zip_file
EXPORTING
filename = 'docProps/custom.xml'
IMPORTING
content = lw_file.
* Search available ID
DO.
IF sy-index = 1.
CONTINUE.
ENDIF.
lw_id = sy-index.
CONDENSE lw_id NO-GAPS.
CONCATENATE 'pid="' lw_id '"' INTO lw_string.
FIND lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add property
CONCATENATE '<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"'
' pid="'
lw_id
'" name="'
field
'">'
'<vt:lpwstr>'
value
'</vt:lpwstr>'
'</property>'
'</Properties>'
INTO lw_string RESPECTING BLANKS.
REPLACE '</Properties>' IN lw_file WITH lw_string.
* Update custopproperties file
CALL METHOD _update_zip_file
EXPORTING
filename = 'docProps/custom.xml'
content = lw_file.
ENDMETHOD. "create_custom_field
METHOD create_character_style.
DATA : lw_style TYPE string,
lw_file TYPE string,
lw_string TYPE string,
ls_list_style LIKE LINE OF mt_list_style.
* Build simple style internal name
name = output_name.
REPLACE ALL OCCURRENCES OF REGEX '[^A-Za-z0-9]' IN name WITH space.
CONDENSE name NO-GAPS.
* Check style internal name is available
READ TABLE mt_list_style WITH KEY type = c_type_character
name = name
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CLEAR name.
RETURN.
ENDIF.
* Build character style
CALL METHOD _build_character_style
EXPORTING
style_effect = style_effect
IMPORTING
xml = lw_style.
IF style_ref IS SUPPLIED AND NOT style_ref IS INITIAL.
READ TABLE mt_list_style WITH KEY type = c_type_character
name = style_ref
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CONCATENATE '<w:basedOn w:val="'
style_ref
'"/>'
INTO lw_string.
ELSE.
invalid_style = c_true.
ENDIF.
ENDIF.
CONCATENATE '<w:style w:type="'
c_type_character
'" w:customStyle="1" w:styleId="'
name
'">'
'<w:name w:val="'
output_name
'"/>'
lw_string
lw_style
'</w:style>'
'</w:styles>'
INTO lw_style.
* Get styles file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/styles.xml'
IMPORTING
content = lw_file.
* Update style file content
REPLACE '</w:styles>' IN lw_file WITH lw_style.
* Update zipped style file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/styles.xml'
content = lw_file.
* Update style list
CLEAR ls_list_style.
ls_list_style-type = c_type_character.
ls_list_style-name = name.
APPEND ls_list_style TO mt_list_style.
ENDMETHOD. "create_character_style
METHOD create_paragraph_style.
DATA : lw_style TYPE string,
lw_stylepr TYPE string,
lw_file TYPE string,
lw_string TYPE string,
ls_list_style LIKE LINE OF mt_list_style.
* Build simple style internal name
name = output_name.
REPLACE ALL OCCURRENCES OF REGEX '[^A-Za-z0-9]' IN name WITH space.
CONDENSE name NO-GAPS.
* Check style internal name is available
READ TABLE mt_list_style WITH KEY type = c_type_paragraph
name = name
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CLEAR name.
RETURN.
ENDIF.
* Build character style
CALL METHOD _build_character_style
EXPORTING
style_effect = style_effect
IMPORTING
xml = lw_style.
* Build paragraph style
CALL METHOD _build_paragraph_style
EXPORTING
style_effect = line_style_effect
IMPORTING
xml = lw_stylepr.
IF style_ref IS SUPPLIED AND NOT style_ref IS INITIAL.
READ TABLE mt_list_style WITH KEY type = c_type_paragraph
name = style_ref
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CONCATENATE '<w:basedOn w:val="'
style_ref
'"/>'
INTO lw_string.
ELSE.
invalid_style = c_true.
ENDIF.
ENDIF.
CONCATENATE '<w:style w:type="'
c_type_paragraph
'" w:customStyle="1" w:styleId="'
name
'">'
'<w:name w:val="'
output_name
'"/>'
lw_string
lw_stylepr
lw_style
'</w:style>'
'</w:styles>'
INTO lw_style.
* Get styles file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/styles.xml'
IMPORTING
content = lw_file.
* Update style file content
REPLACE '</w:styles>' IN lw_file WITH lw_style.
* Update zipped style file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/styles.xml'
content = lw_file.
* Update style list
CLEAR ls_list_style.
ls_list_style-type = c_type_paragraph.
ls_list_style-name = name.
APPEND ls_list_style TO mt_list_style.
ENDMETHOD. "create_paragraph_style
METHOD insert_attachment.
DATA : lw_extension TYPE string,
lw_filex TYPE xstring,
lw_file TYPE string,
lw_filename TYPE string,
lw_string TYPE string,
lw_id TYPE string,
lw_url_begin(6) TYPE c,
lw_ct_string TYPE string,
lw_rel_string TYPE string,
lw_style TYPE string.
invalid_image = c_false.
invalid_file = c_false.
IF url IS INITIAL AND file_content IS INITIAL.
invalid_file = c_true.
RETURN.
ENDIF.
* Load file
IF file_content IS INITIAL.
CALL METHOD _load_file
EXPORTING
filename = url
IMPORTING
xcontent = lw_filex.
IF lw_filex IS INITIAL.
invalid_file = c_true.
RETURN.
ENDIF.
ELSE.
lw_filex = file_content.
ENDIF.
* Get file extension
* For file from sapwr, get file extension from DB
lw_url_begin = url.
IF lw_url_begin = c_sapwr_prefix.
SELECT SINGLE value INTO lw_extension
FROM wwwparams
WHERE relid = 'MI'
AND objid = url+6
AND name = 'fileextension'.
IF NOT lw_extension IS INITIAL AND lw_extension(1) = '.'.
lw_extension = lw_extension+1.
ENDIF.
ELSE.
* For other file, get file extension from filename
FIND ALL OCCURRENCES OF '.' IN url MATCH OFFSET sy-fdpos.
IF sy-subrc = 0.
sy-fdpos = sy-fdpos + 1.
lw_extension = url+sy-fdpos.
TRANSLATE lw_extension TO LOWER CASE.
IF lw_extension = 'jpeg'.
lw_extension = 'jpg'.
ENDIF.
ENDIF.
ENDIF.
TRANSLATE lw_extension TO LOWER CASE.
CASE lw_extension.
WHEN 'pptx'.
lw_ct_string = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/package'.
WHEN 'ppt'.
lw_ct_string = 'application/vnd.ms-powerpoint'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject'.
WHEN 'docx'.
lw_ct_string = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/package'.
WHEN 'docm'.
lw_ct_string = 'application/vnd.ms-word.document.macroEnabled.12'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/package'.
WHEN 'doc'.
lw_ct_string = 'application/msword'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject'.
WHEN 'xlsx'.
lw_ct_string = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/package'.
WHEN 'xls'.
lw_ct_string = 'application/vnd.ms-excel'.
lw_rel_string = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject'.
WHEN OTHERS.
invalid_file = c_true.
RETURN.
ENDCASE.
* Search available file name
DO.
lw_filename = sy-index.
CONDENSE lw_filename NO-GAPS.
CONCATENATE 'word/embeddings/attached' lw_filename '.' lw_extension
INTO lw_filename.
READ TABLE mo_zip->files WITH KEY name = lw_filename
TRANSPORTING NO FIELDS.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add file in ZIP
CALL METHOD mo_zip->add
EXPORTING
name = lw_filename
content = lw_filex.
* Get file extension list
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml'
IMPORTING
content = lw_file.
* Add attachment exception in content type file
CONCATENATE '<Override PartName="/'
lw_filename
'" ContentType="'
lw_ct_string
'"/></Types>'
INTO lw_string.
REPLACE '</Types>' WITH lw_string
INTO lw_file.
* Update file extension list
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
* Get relation file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
IMPORTING
content = lw_file.
* Create file ID
DO.
lw_id = sy-index.
CONDENSE lw_id NO-GAPS.
CONCATENATE 'rId' lw_id INTO lw_id. "#EC NOTEXT
CONCATENATE 'Id="' lw_id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add relation
lw_filename = lw_filename+5.
CONCATENATE '<Relationship Target="'
lw_filename
'" Type="'
lw_rel_string
'" Id="'
lw_id
'"/>'
'</Relationships>'
INTO lw_string.
REPLACE '</Relationships>' WITH lw_string INTO lw_file.
* Update relation file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
content = lw_file.
* Load icon
CALL METHOD _load_image
EXPORTING
url = url_img
* IMPORTING
* imgres_x = lw_imgres_x
* imgres_y = lw_imgres_y
CHANGING
id = id_img.
IF id_img IS INITIAL.
invalid_image = c_true.
RETURN.
ENDIF.
* Search next id for some useless mandatory word attributes
mw_attach = mw_attach + 1.
lw_string = mw_attach.
CONDENSE lw_string NO-GAPS.
* Everything fine, build xml fragment
CONCATENATE '<w:r>'
"lw_style
'<w:object>'
'<v:shape id="_x0000_'
lw_string
'" type="#_x0000_t75" o:ole="">'
'<v:imagedata r:id="'
id_img
'" o:title=""/>'
'</v:shape>'
'<o:OLEObject Type="Embed" ProgID="Package" DrawAspect="Icon" ShapeID="_x0000_'
lw_string
'" ObjectID="_10000'
lw_string
'" r:id="'
lw_id
'"/>'
'</w:object>'
'</w:r>'
INTO virtual RESPECTING BLANKS.
IF as_paragraph = c_true.
* Add paragraphe style
IF NOT style IS INITIAL OR NOT style_effect IS INITIAL.
CALL METHOD _build_paragraph_style
EXPORTING
style = style
style_effect = style_effect
IMPORTING
xml = lw_style
invalid_style = invalid_style.
ENDIF.
CONCATENATE '<w:p>'
lw_style
virtual
'</w:p>'
INTO virtual.
ENDIF.
* Insert attachment in document
IF NOT virtual IS SUPPLIED.
IF as_paragraph = c_true.
CONCATENATE mw_docxml
virtual
INTO mw_docxml.
ELSE.
CONCATENATE mw_fragxml
virtual
INTO mw_fragxml.
ENDIF.
ENDIF.
ENDMETHOD. "insert_attachment
METHOD insert_image.
DATA : lw_string TYPE string,
lw_imgres_x TYPE i,
lw_imgres_y TYPE i.
DATA : lw_scalex TYPE f,
lw_scaley TYPE f,
lw_scale_max TYPE i,
lw_scale TYPE i,
lw_x TYPE i,
lw_y TYPE i,
lw_x_string TYPE string,
lw_y_string TYPE string,
lw_style TYPE string,
lw_type_on TYPE string,
lw_type_in TYPE string,
lw_type_off TYPE string,
lw_posx TYPE string,
lw_posy TYPE string,
lw_margin TYPE string.
invalid_image = c_false.
CALL METHOD _load_image
EXPORTING
url = url
file_content = file_content
IMPORTING
imgres_x = lw_imgres_x
imgres_y = lw_imgres_y
CHANGING
id = id.
IF id IS INITIAL.
invalid_image = c_true.
RETURN.
ENDIF.
* Calculate image scale
IF ms_section-landscape = c_true.
* Max X in landscape : 8877300
* Max Y in landscape : 5743575 "could be less... depend of header/footer
lw_scalex = 8877300 / lw_imgres_x.
lw_scaley = 5762625 / lw_imgres_y.
ELSE.
* Max X in portrait : 5762625
* Max Y in portrait : 8886825 "could be less... depend of header/footer
lw_scalex = 5762625 / lw_imgres_x.
lw_scaley = 8886825 / lw_imgres_y.
ENDIF.
IF lw_scalex < lw_scaley.
lw_scale_max = floor( lw_scalex ).
ELSE.
lw_scale_max = floor( lw_scaley ).
ENDIF.
* Image is smaler than page
IF lw_scale_max GT 9525.
lw_scale = 9525. "no zoom
IF zoom IS SUPPLIED.
lw_scale = lw_scale * zoom.
IF lw_scale GT lw_scale_max.
lw_scale = lw_scale_max.
ENDIF.
ENDIF.
ELSE.
* Image is greater than page
lw_scale = lw_scale_max.
IF zoom IS SUPPLIED AND zoom < 1.
lw_scale_max = 9525 * zoom.
IF lw_scale_max LT lw_scale.
lw_scale = lw_scale_max.
ENDIF.
ENDIF.
ENDIF.
lw_x = lw_imgres_x * lw_scale.
lw_y = lw_imgres_y * lw_scale.
lw_x_string = lw_x.
CONDENSE lw_x_string NO-GAPS.
lw_y_string = lw_y.
CONDENSE lw_y_string NO-GAPS.
* Finally insert image in document
ADD 1 TO mw_imgmaxid.
lw_string = mw_imgmaxid.
CONDENSE lw_string NO-GAPS.
lw_margin = margin.
CONDENSE lw_margin NO-GAPS.
CASE type.
WHEN c_imgtype_inline.
CONCATENATE '<wp:inline distT="'
lw_margin
'" distB="'
lw_margin
'" distL="'
lw_margin
'" distR="'
lw_margin
'">'
INTO lw_type_on.
lw_type_in = ''.
lw_type_off = '</wp:inline>'.
WHEN c_imgtype_float OR c_imgtype_over OR c_imgtype_behind.
IF type = c_imgtype_behind.
lw_type_on = '1'.
ELSE.
lw_type_on = '0'.
ENDIF.
IF posx CO '0123456789-'.
CONCATENATE '<wp:posOffset>' posx '</wp:posOffset>' INTO lw_posx.
ELSE.
CONCATENATE '<wp:align>' posx '</wp:align>' INTO lw_posx.
ENDIF.
IF posy CO '0123456789-'.
CONCATENATE '<wp:posOffset>' posy '</wp:posOffset>' INTO lw_posy.
ELSE.
CONCATENATE '<wp:align>' posy '</wp:align>' INTO lw_posy.
ENDIF.
CONCATENATE '<wp:anchor distT="'
lw_margin
'" distB="'
lw_margin
'" distL="'
lw_margin
'" distR="'
lw_margin
'" behindDoc="'
lw_type_on
'" allowOverlap="1"'
' simplePos="0" locked="0" layoutInCell="1" relativeHeight="251658240" >'
'<wp:simplePos x="0" y="0"/>'
'<wp:positionH relativeFrom="column">'
lw_posx
'</wp:positionH>'
'<wp:positionV relativeFrom="paragraph">'
lw_posy
'</wp:positionV>'
INTO lw_type_on RESPECTING BLANKS.
IF type = c_imgtype_float.
lw_type_in = '<wp:wrapSquare wrapText="bothSides"/>'.
ELSE.
lw_type_in = '<wp:wrapNone/>'.
ENDIF.
lw_type_off = '</wp:anchor>'.
ENDCASE.
* Prepare image insertion xml fragment
CONCATENATE
'<w:r>'
'<w:drawing>'
lw_type_on
'<wp:extent cx="'
lw_x_string
'" cy="'
lw_y_string
'"/>'
lw_type_in
'<wp:docPr id="'
lw_string "mw_imgmaxid
'" name=""/>'
'<wp:cNvGraphicFramePr/>'
'<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">'
'<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">'
'<pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">'
'<pic:nvPicPr>'
'<pic:cNvPr id="0" name=""/>'
'<pic:cNvPicPr/>'
'</pic:nvPicPr>'
'<pic:blipFill>'
'<a:blip r:embed="'
id
'"/>'
'<a:stretch>'
'<a:fillRect/>'
'</a:stretch>'
'</pic:blipFill>'
'<pic:spPr>'
'<a:xfrm>'
'<a:off x="0" y="0"/>'
'<a:ext cx="'
lw_x_string
'" cy="'
lw_y_string
'"/>'
'</a:xfrm>'
'<a:prstGeom prst="rect">'
'<a:avLst/>'
'</a:prstGeom>'
'</pic:spPr>'
'</pic:pic>'
'</a:graphicData>'
'</a:graphic>'
lw_type_off
'</w:drawing>'
'</w:r>'
INTO virtual.
IF as_paragraph = c_true.
* Add paragraphe style
IF NOT style IS INITIAL OR NOT style_effect IS INITIAL.
CALL METHOD _build_paragraph_style
EXPORTING
style = style
style_effect = style_effect
IMPORTING
xml = lw_style
invalid_style = invalid_style.
ENDIF.
CONCATENATE '<w:p>'
lw_style
virtual
'</w:p>'
INTO virtual.
ENDIF.
* Insert image in document
IF NOT virtual IS SUPPLIED.
IF as_paragraph = c_true.
CONCATENATE mw_docxml
virtual
INTO mw_docxml.
ELSE.
CONCATENATE mw_fragxml
virtual
INTO mw_fragxml.
ENDIF.
ENDIF.
ENDMETHOD. "insert_image
METHOD set_properties.
DATA : lw_xml TYPE string,
lw_string TYPE string.
* Get prperties file
CALL METHOD _get_zip_file
EXPORTING
filename = 'docProps/core.xml'
IMPORTING
content = lw_xml.
IF title IS SUPPLIED.
* Replace existing title by new one
CALL METHOD _protect_string
EXPORTING
in = title
IMPORTING
out = lw_string.
CONCATENATE '<dc:title>'
lw_string
'</dc:title>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:title>(.*)</dc:title>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:title\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no title property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF object IS SUPPLIED.
* Replace existing object by new one
CALL METHOD _protect_string
EXPORTING
in = object
IMPORTING
out = lw_string.
CONCATENATE '<dc:subject>'
lw_string
'</dc:subject>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:subject>(.*)</dc:subject>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:subject\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no object property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF author IS SUPPLIED.
* Replace existing author by new one
CALL METHOD _protect_string
EXPORTING
in = author
IMPORTING
out = mw_author.
CONCATENATE '<dc:creator>'
mw_author
'</dc:creator>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:creator>(.*)</dc:creator>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:creator\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no author property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
* Set also last modified property
CALL METHOD _protect_string
EXPORTING
in = author
IMPORTING
out = lw_string.
CONCATENATE '<cp:lastModifiedBy>'
lw_string
'</cp:lastModifiedBy>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:lastModifiedBy>(.*)</cp:lastModifiedBy>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:lastModifiedBy\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no lastmodified property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF creationdate IS SUPPLIED.
* Replace existing creation date by new one
CONCATENATE '<dcterms:created xsi:type="dcterms:W3CDTF">'
creationdate(4)
'-'
creationdate+4(2)
'-'
creationdate+6(2)
'T'
creationtime(2)
':'
creationtime+2(2)
':'
creationtime+2(2)
'Z'
'</dcterms:created>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<dcterms:created(.*)</dcterms:created>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<dcterms:created\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no creation date property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
* Replace also last modification date by new one
CONCATENATE '<dcterms:modified xsi:type="dcterms:W3CDTF">'
creationdate(4)
'-'
creationdate+4(2)
'-'
creationdate+6(2)
'T'
creationtime(2)
':'
creationtime+2(2)
':'
creationtime+2(2)
'Z'
'</dcterms:modified>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<dcterms:modified(.*)</dcterms:modified>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<dcterms:modified\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no modification date property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF description IS SUPPLIED.
* Replace existing description by new one
CALL METHOD _protect_string
EXPORTING
in = description
IMPORTING
out = lw_string.
CONCATENATE '<dc:description>'
lw_string
'</dc:description>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:description>(.*)</dc:description>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<dc:description\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no description property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF category IS SUPPLIED.
* Replace existing category by new one
CALL METHOD _protect_string
EXPORTING
in = category
IMPORTING
out = lw_string.
CONCATENATE '<cp:category>'
lw_string
'</cp:category>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:category>(.*)</cp:category>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:category\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no category property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF keywords IS SUPPLIED.
* Replace existing keywords by new one
CALL METHOD _protect_string
EXPORTING
in = keywords
IMPORTING
out = lw_string.
CONCATENATE '<cp:keywords>'
lw_string
'</cp:keywords>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:keywords>(.*)</cp:keywords>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:keywords\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no keywords property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF status IS SUPPLIED.
* Replace existing status by new one
CALL METHOD _protect_string
EXPORTING
in = status
IMPORTING
out = lw_string.
CONCATENATE '<cp:contentStatus>'
lw_string
'</cp:contentStatus>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:contentStatus>(.*)</cp:contentStatus>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:contentStatus\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no status property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
IF revision IS SUPPLIED.
* Replace existing status by new one
lw_string = revision.
CONDENSE lw_string NO-GAPS.
CONCATENATE '<cp:revision>'
lw_string
'</cp:revision>'
INTO lw_string.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:revision>(.*)</cp:revision>' IN lw_xml WITH lw_string.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF REGEX '<cp:revision\s*/>' IN lw_xml WITH lw_string.
ENDIF.
* If no revision property found, add it at end of xml
IF sy-subrc NE 0.
CONCATENATE lw_string
'</cp:coreProperties>'
INTO lw_string.
REPLACE '</cp:coreProperties>'
WITH lw_string
INTO lw_xml.
ENDIF.
ENDIF.
* Update properties file
CALL METHOD _update_zip_file
EXPORTING
filename = 'docProps/core.xml'
content = lw_xml.
ENDMETHOD. "set_properties
METHOD set_params.
DATA : lw_xml TYPE string,
lw_xmlns TYPE string.
* Define orientation
IF orientation = c_orient_landscape.
ms_section-landscape = c_true.
ENDIF.
* Define Border
IF border_left IS SUPPLIED.
ms_section-border_left = border_left.
ENDIF.
IF border_top IS SUPPLIED.
ms_section-border_top = border_top.
ENDIF.
IF border_right IS SUPPLIED.
ms_section-border_right = border_right.
ENDIF.
IF border_bottom IS SUPPLIED.
ms_section-border_bottom = border_bottom.
ENDIF.
* Hide spellcheck for this document
IF nospellcheck NE c_false.
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/settings.xml'
IMPORTING
content = lw_xml.
* File doesnt exist ? create it !
IF lw_xml IS INITIAL.
CALL METHOD _get_xml_ns
IMPORTING
xml = lw_xmlns.
CONCATENATE '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<w:settings '
lw_xmlns
'>'
'</w:settings>'
INTO lw_xml RESPECTING BLANKS.
ENDIF.
FIND 'hideSpellingErrors' IN lw_xml.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF '</w:settings>'
IN lw_xml
WITH '<w:hideSpellingErrors/></w:settings>'
IGNORING CASE.
ENDIF.
FIND 'hideGrammaticalErrors' IN lw_xml.
IF sy-subrc NE 0.
REPLACE FIRST OCCURRENCE OF '</w:settings>'
IN lw_xml
WITH '<w:hideGrammaticalErrors/></w:settings>'
IGNORING CASE.
ENDIF.
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/settings.xml'
content = lw_xml.
ENDIF.
ENDMETHOD. "set_params
METHOD save.
DATA : lt_data_tab TYPE STANDARD TABLE OF x255,
lw_lraw TYPE x255,
lw_docx TYPE xstring,
lw_xlen TYPE i,
lw_count TYPE i,
lw_off TYPE i,
lw_mod TYPE i.
CALL METHOD get_docx_file
IMPORTING
xcontent = lw_docx.
* Convert docx xString to xTable(255)
REFRESH lt_data_tab.
CLEAR lw_off.
lw_xlen = xstrlen( lw_docx ).
lw_count = lw_xlen DIV 255.
DO lw_count TIMES.
lw_lraw = lw_docx+lw_off(255).
lw_off = lw_off + 255.
APPEND lw_lraw TO lt_data_tab.
ENDDO.
lw_mod = lw_xlen MOD 255.
IF lw_mod > 0.
lw_lraw = lw_docx+lw_off(lw_mod).
APPEND lw_lraw TO lt_data_tab.
ENDIF.
CLEAR lw_docx.
* Save document on server
IF local = c_false.
OPEN DATASET url FOR OUTPUT IN BINARY MODE.
IF sy-subrc NE 0.
* Error opening the file
MESSAGE 'Cannot create remote file' TYPE 'E'.
RETURN.
ENDIF.
LOOP AT lt_data_tab INTO lw_lraw.
IF lw_xlen > 255.
lw_mod = 255.
ELSE.
lw_mod = lw_xlen.
ENDIF.
TRANSFER lw_lraw TO url LENGTH lw_mod.
lw_xlen = lw_xlen - lw_mod.
ENDLOOP.
CLOSE DATASET url.
* Save document on local computer
ELSEIF local = c_true.
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
bin_filesize = lw_xlen
filename = url
filetype = 'BIN'
confirm_overwrite = 'X'
CHANGING
data_tab = lt_data_tab
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
OTHERS = 24.
* Error on save
IF sy-subrc NE 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno.
ENDIF.
ENDIF.
ENDMETHOD. "save
METHOD get_docx_file.
DATA lw_xmlns TYPE string.
CLEAR xcontent.
* Add final section info
CALL METHOD _write_section.
CONCATENATE mw_docxml mw_section_xml INTO mw_docxml.
CALL METHOD _get_xml_ns
IMPORTING
xml = lw_xmlns.
* Add complete xml header
CONCATENATE
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<w:document '
lw_xmlns
'>'
'<w:body>'
mw_docxml
'</w:body></w:document>'
INTO mw_docxml RESPECTING BLANKS.
* Add custom body into docx
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/document.xml'
content = mw_docxml.
* Get final docx
CALL METHOD mo_zip->save
RECEIVING
zip = xcontent.
ENDMETHOD. "get_docx_file
METHOD header_footer_direct_assign.
invalid_header = c_false.
invalid_footer = c_false.
IF header IS SUPPLIED.
sy-subrc = 0.
IF NOT header IS INITIAL.
READ TABLE mt_list_object WITH KEY type = c_type_header
id = header
TRANSPORTING NO FIELDS.
ENDIF.
IF sy-subrc = 0.
ms_section-header = header.
ELSE.
invalid_header = c_true.
ENDIF.
ENDIF.
IF footer IS SUPPLIED.
sy-subrc = 0.
IF NOT footer IS INITIAL.
READ TABLE mt_list_object WITH KEY type = c_type_footer
id = footer
TRANSPORTING NO FIELDS.
ENDIF.
IF sy-subrc = 0.
ms_section-footer = footer.
ELSE.
invalid_footer = c_true.
ENDIF.
ENDIF.
IF header_first IS SUPPLIED.
sy-subrc = 0.
IF NOT header_first IS INITIAL.
READ TABLE mt_list_object WITH KEY type = c_type_header
id = header_first
TRANSPORTING NO FIELDS.
ENDIF.
IF sy-subrc = 0.
ms_section-header_first = header_first.
ELSE.
invalid_header = c_true.
ENDIF.
ENDIF.
IF footer_first IS SUPPLIED.
sy-subrc = 0.
IF NOT footer_first IS INITIAL.
READ TABLE mt_list_object WITH KEY type = c_type_footer
id = footer_first
TRANSPORTING NO FIELDS.
ENDIF.
IF sy-subrc = 0.
ms_section-footer_first = footer_first.
ELSE.
invalid_footer = c_true.
ENDIF.
ENDIF.
ENDMETHOD. "header_footer_direct_assign
METHOD get_list_style.
style_list[] = mt_list_style[].
ENDMETHOD. "get_list_style
METHOD get_list_image.
DATA ls_list_object LIKE LINE OF mt_list_object.
REFRESH image_list.
LOOP AT mt_list_object INTO ls_list_object WHERE type = c_type_image.
APPEND ls_list_object TO image_list.
ENDLOOP.
ENDMETHOD. "get_list_image
METHOD get_list_headerfooter.
DATA ls_list_object LIKE LINE OF mt_list_object.
REFRESH headerfooter_list.
LOOP AT mt_list_object INTO ls_list_object
WHERE type = c_type_header OR type = c_type_footer.
APPEND ls_list_object TO headerfooter_list.
ENDLOOP.
ENDMETHOD. "get_list_headerfooter
METHOD insert_xml_fragment.
CONCATENATE mw_fragxml xml INTO mw_fragxml.
ENDMETHOD. "insert_xml_fragment
METHOD insert_xml.
CONCATENATE mw_docxml xml INTO mw_docxml.
ENDMETHOD. "insert_xml
METHOD _get_zip_file.
DATA : lw_xmlx TYPE xstring,
lw_xmlx_length TYPE i,
lt_xmlx TYPE STANDARD TABLE OF x255.
* Get zipped file
CALL METHOD mo_zip->get
EXPORTING
name = filename
IMPORTING
content = lw_xmlx
EXCEPTIONS
OTHERS = 2.
* Transform xstring to string in 2 steps
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lw_xmlx
IMPORTING
output_length = lw_xmlx_length
TABLES
binary_tab = lt_xmlx.
CALL FUNCTION 'SCMS_BINARY_TO_STRING'
EXPORTING
input_length = lw_xmlx_length
IMPORTING
text_buffer = content
TABLES
binary_tab = lt_xmlx.
ENDMETHOD. "_get_zip_file
METHOD _update_zip_file.
DATA : lw_docx TYPE xstring.
* File content string => xstring
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = content
IMPORTING
buffer = lw_docx.
* If target file already exist, remove it
READ TABLE mo_zip->files WITH KEY name = filename
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CALL METHOD mo_zip->delete
EXPORTING
name = filename.
ENDIF.
* Add modified file into zip
CALL METHOD mo_zip->add
EXPORTING
name = filename
content = lw_docx.
ENDMETHOD. "_update_zip_file
METHOD _load_file.
DATA : lt_data_tab TYPE STANDARD TABLE OF x255,
lw_length TYPE i,
lw_url_begin(6) TYPE c.
DATA : lt_query TYPE TABLE OF w3query,
ls_query TYPE w3query,
lt_html TYPE TABLE OF w3html,
lt_mime TYPE TABLE OF w3mime,
lw_return TYPE w3param-ret_code,
lw_type TYPE w3param-cont_type.
CLEAR xcontent.
lw_url_begin = filename.
* Load image
IF lw_url_begin = c_sapwr_prefix.
* For SAPWR, read file from DB
ls_query-name = '_OBJECT_ID'.
ls_query-value = filename+6.
APPEND ls_query TO lt_query.
CALL FUNCTION 'WWW_GET_MIME_OBJECT'
TABLES
query_string = lt_query
html = lt_html
mime = lt_mime
CHANGING
return_code = lw_return
content_type = lw_type
content_length = lw_length
EXCEPTIONS
OTHERS = 3.
IF sy-subrc NE 0.
RETURN.
ENDIF.
* Convert xchar table to xstring
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lw_length
IMPORTING
buffer = xcontent
TABLES
binary_tab = lt_mime
EXCEPTIONS
OTHERS = 2.
ELSE.
* For others, read file
CALL METHOD cl_gui_frontend_services=>gui_upload
EXPORTING
filename = filename
filetype = 'BIN'
IMPORTING
filelength = lw_length
CHANGING
data_tab = lt_data_tab
EXCEPTIONS
OTHERS = 19.
IF sy-subrc NE 0.
RETURN.
ENDIF.
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lw_length
IMPORTING
buffer = xcontent
TABLES
binary_tab = lt_data_tab
EXCEPTIONS
OTHERS = 2.
ENDIF.
IF sy-subrc NE 0.
RETURN.
ENDIF.
ENDMETHOD. "_load_file
METHOD _load_image.
DATA : lw_filex TYPE xstring,
lw_filename TYPE string,
lw_string TYPE string,
lw_file TYPE string,
lw_url_begin(6) TYPE c,
ls_list_object LIKE LINE OF mt_list_object.
CLEAR : extension, imgres_x, imgres_y.
* For existing image (ID given), just get img_res and extension.
IF NOT id IS INITIAL.
READ TABLE mt_list_object WITH KEY type = c_type_image
id = id
INTO ls_list_object.
IF sy-subrc NE 0.
CLEAR id.
RETURN.
ENDIF.
IF extension IS SUPPLIED.
FIND ALL OCCURRENCES OF '.' IN ls_list_object-path
MATCH OFFSET sy-fdpos.
IF sy-subrc = 0.
sy-fdpos = sy-fdpos + 1.
extension = ls_list_object-path+sy-fdpos.
TRANSLATE extension TO LOWER CASE.
IF extension = 'jpeg'.
extension = 'jpg'.
ENDIF.
ENDIF.
ENDIF.
IF imgres_x IS SUPPLIED OR imgres_y IS SUPPLIED.
CALL METHOD mo_zip->get
EXPORTING
name = ls_list_object-path
IMPORTING
content = lw_filex
EXCEPTIONS
OTHERS = 2.
IF sy-subrc = 0.
CALL METHOD cl_fxs_image_info=>determine_info
EXPORTING
iv_data = lw_filex
IMPORTING
ev_xres = imgres_x
ev_yres = imgres_y.
ENDIF.
ENDIF.
RETURN.
ENDIF.
* For new image, load image
lw_url_begin = url.
TRANSLATE lw_url_begin TO UPPER CASE.
* For image from sapwr, get file extension from DB
IF lw_url_begin = c_sapwr_prefix.
SELECT SINGLE value INTO extension
FROM wwwparams
WHERE relid = 'MI'
AND objid = url+6
AND name = 'fileextension'.
IF NOT extension IS INITIAL AND extension(1) = '.'.
extension = extension+1.
ENDIF.
ELSE.
* For other image, get file extension from filename
FIND ALL OCCURRENCES OF '.' IN url MATCH OFFSET sy-fdpos.
IF sy-subrc = 0.
sy-fdpos = sy-fdpos + 1.
extension = url+sy-fdpos.
TRANSLATE extension TO LOWER CASE.
IF extension = 'jpeg'.
extension = 'jpg'.
ENDIF.
ENDIF.
ENDIF.
* Cannot add image other than jpg/png/gif
IF extension NE 'jpg'
AND extension NE 'png'
AND extension NE 'gif'.
RETURN.
ENDIF.
* Load image
IF file_content IS INITIAL.
CALL METHOD _load_file
EXPORTING
filename = url
IMPORTING
xcontent = lw_filex.
IF lw_filex IS INITIAL.
RETURN.
ENDIF.
ELSE.
lw_filex = file_content.
ENDIF.
* Get image resolution
IF imgres_x IS SUPPLIED OR imgres_y IS SUPPLIED.
CALL METHOD cl_fxs_image_info=>determine_info
EXPORTING
iv_data = lw_filex
IMPORTING
ev_xres = imgres_x
ev_yres = imgres_y.
ENDIF.
* Search available image name
DO.
lw_filename = sy-index.
CONDENSE lw_filename NO-GAPS.
CONCATENATE 'word/media/image' lw_filename '.' extension
INTO lw_filename.
READ TABLE mo_zip->files WITH KEY name = lw_filename
TRANSPORTING NO FIELDS.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add image in ZIP
CALL METHOD mo_zip->add
EXPORTING
name = lw_filename
content = lw_filex.
* Get file extension list
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml'
IMPORTING
content = lw_file.
* Search if file extension exist
CONCATENATE 'extension="' extension '"' INTO lw_string.
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
* If extension is not yet declared, it's time !
CASE extension.
WHEN 'jpg'.
REPLACE '</Types>' WITH '<Default ContentType="image/jpeg" Extension="jpg"/></Types>'
INTO lw_file.
WHEN 'png'.
REPLACE '</Types>' WITH '<Default ContentType="image/png" Extension="png"/></Types>'
INTO lw_file.
WHEN 'gif'.
REPLACE '</Types>' WITH '<Default ContentType="image/gif" Extension="gif"/></Types>'
INTO lw_file.
ENDCASE.
* Update file extension list
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
ENDIF.
* Get relation file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
IMPORTING
content = lw_file.
* Create Image ID
DO.
id = sy-index.
CONDENSE id NO-GAPS.
CONCATENATE 'rId' id INTO id. "#EC NOTEXT
CONCATENATE 'Id="' id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Update object list
CLEAR ls_list_object.
ls_list_object-id = id.
ls_list_object-type = c_type_image.
ls_list_object-path = lw_filename.
APPEND ls_list_object TO mt_list_object.
* Add relation
lw_filename = lw_filename+5.
CONCATENATE '<Relationship Target="'
lw_filename
'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Id="'
id
'"/>'
'</Relationships>'
INTO lw_string.
REPLACE '</Relationships>' WITH lw_string INTO lw_file.
* Update relation file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
content = lw_file.
ENDMETHOD. "_load_image
METHOD _create_note.
DATA : lw_filename TYPE string,
lw_string TYPE string,
lw_file TYPE string,
lw_link_style TYPE string,
lw_line_style TYPE string,
lw_text TYPE string,
lw_xmlns TYPE string,
lw_id TYPE string.
* Search if notes file exist
IF type = c_notetype_foot.
lw_filename = 'word/footnotes.xml'.
ELSEIF type = c_notetype_end.
lw_filename = 'word/endnotes.xml'.
ELSE.
RETURN.
ENDIF.
READ TABLE mo_zip->files WITH KEY name = lw_filename
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
* If foot/end notes exists, load the file
CALL METHOD _get_zip_file
EXPORTING
filename = lw_filename
IMPORTING
content = lw_file.
ELSE.
* If footnotes doesnt exist, declare it and create it
* Add footnotes in content_types
CALL METHOD _get_zip_file
EXPORTING
filename = '[Content_Types].xml'
IMPORTING
content = lw_file.
IF type = c_notetype_foot.
CONCATENATE '<Override'
' ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"'
' PartName="/word/footnotes.xml"/></Types>'
INTO lw_string RESPECTING BLANKS.
ELSEIF type = c_notetype_end.
CONCATENATE '<Override'
' ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"'
' PartName="/word/endnotes.xml"/></Types>'
INTO lw_string RESPECTING BLANKS.
ENDIF.
REPLACE '</Types>' WITH lw_string
INTO lw_file.
CALL METHOD _update_zip_file
EXPORTING
filename = '[Content_Types].xml'
content = lw_file.
* Add footnotes in relation file
CALL METHOD _get_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
IMPORTING
content = lw_file.
* Create footnotes relation ID
DO.
lw_id = sy-index.
CONDENSE lw_id NO-GAPS.
CONCATENATE 'rId' lw_id INTO lw_id. "#EC NOTEXT
CONCATENATE 'Id="' lw_id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add relation
IF type = c_notetype_foot.
CONCATENATE '<Relationship Target="footnotes.xml"'
' Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"'
' Id="'
lw_id
'"/>'
'</Relationships>'
INTO lw_string RESPECTING BLANKS.
ELSEIF type = c_notetype_end.
CONCATENATE '<Relationship Target="endnotes.xml"'
' Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes"'
' Id="'
lw_id
'"/>'
'</Relationships>'
INTO lw_string RESPECTING BLANKS.
ENDIF.
REPLACE '</Relationships>' WITH lw_string INTO lw_file.
* Update relation file
CALL METHOD _update_zip_file
EXPORTING
filename = 'word/_rels/document.xml.rels'
content = lw_file.
CALL METHOD _get_xml_ns
IMPORTING
xml = lw_xmlns.
* Create notes file
IF type = c_notetype_foot.
CONCATENATE '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<w:footnotes '
lw_xmlns
'>'
'<w:footnote w:id="-1" w:type="separator">'
'<w:p>'
'<w:pPr><w:spacing w:lineRule="auto" w:line="240" w:after="0"/></w:pPr>'
'<w:r><w:separator/></w:r>'
'</w:p>'
'</w:footnote>'
'<w:footnote w:id="0" w:type="continuationSeparator">'
'<w:p>'
'<w:pPr><w:spacing w:lineRule="auto" w:line="240" w:after="0"/></w:pPr>'
'<w:r><w:continuationSeparator/></w:r>'
'</w:p>'
'</w:footnote>'
'</w:footnotes>'
INTO lw_file RESPECTING BLANKS.
ELSEIF type = c_notetype_end.
CONCATENATE '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<w:endnotes '
lw_xmlns
'>'
'<w:endnote w:id="-1" w:type="separator">'
'<w:p>'
'<w:pPr><w:spacing w:lineRule="auto" w:line="240" w:after="0"/></w:pPr>'
'<w:r><w:separator/></w:r>'
'</w:p>'
'</w:endnote>'
'<w:endnote w:id="0" w:type="continuationSeparator">'
'<w:p>'
'<w:pPr><w:spacing w:lineRule="auto" w:line="240" w:after="0"/></w:pPr>'
'<w:r><w:continuationSeparator/></w:r>'
'</w:p>'
'</w:endnote>'
'</w:endnotes>'
INTO lw_file RESPECTING BLANKS.
ENDIF.
ENDIF.
* Search available note id
DO.
id = sy-index.
CONDENSE id NO-GAPS.
CONCATENATE 'w:id="' id '"' INTO lw_string. "#EC NOTEXT
FIND FIRST OCCURRENCE OF lw_string IN lw_file IGNORING CASE.
IF sy-subrc NE 0.
EXIT. "exit do
ENDIF.
ENDDO.
* Add blank at start of note
lw_text = text.
IF lw_text IS INITIAL OR lw_text(1) NE space.
CONCATENATE space lw_text INTO lw_text RESPECTING BLANKS.
ENDIF.
CALL METHOD write_text
EXPORTING
textline = lw_text
style_effect = style_effect
style = style
IMPORTING
virtual = lw_text
invalid_style = invalid_style.
IF NOT link_style_effect IS INITIAL OR NOT link_style IS INITIAL.
CALL METHOD _build_character_style
EXPORTING
style = link_style
style_effect = link_style_effect
IMPORTING
xml = lw_link_style.
ENDIF.
IF NOT line_style_effect IS INITIAL OR NOT line_style IS INITIAL.
CALL METHOD _build_paragraph_style
EXPORTING
style = line_style
style_effect = line_style_effect
IMPORTING
xml = lw_line_style
invalid_style = invalid_line_style.
ENDIF.
* Add note
IF type = c_notetype_foot.
CONCATENATE '<w:footnote w:id="'
id
'">'
'<w:p>'
lw_line_style
'<w:r>'
lw_link_style
'<w:footnoteRef/>'
'</w:r>'
lw_text
'</w:p>'
'</w:footnote>'
'</w:footnotes>'
INTO lw_string RESPECTING BLANKS.
REPLACE FIRST OCCURRENCE OF '</w:footnotes>' IN lw_file WITH lw_string.
ELSEIF type = c_notetype_end.
CONCATENATE '<w:endnote w:id="'
id
'">'
'<w:p>'
lw_line_style
'<w:r>'
lw_link_style
'<w:endnoteRef/>'
'</w:r>'
lw_text
'</w:p>'
'</w:endnote>'
'</w:endnotes>'
INTO lw_string RESPECTING BLANKS.
REPLACE FIRST OCCURRENCE OF '</w:endnotes>' IN lw_file WITH lw_string.
ENDIF.
* Update footnotes file
CALL METHOD _update_zip_file
EXPORTING
filename = lw_filename
content = lw_file.
ENDMETHOD. "_create_footnote
METHOD _protect_string.
out = in.
REPLACE ALL OCCURRENCES OF '&' IN out WITH '&'.
REPLACE ALL OCCURRENCES OF '<' IN out WITH '<'.
REPLACE ALL OCCURRENCES OF '>' IN out WITH '>'.
REPLACE ALL OCCURRENCES OF '"' IN out WITH '"'.
ENDMETHOD. "_protect_string
METHOD _protect_label.
out = in.
TRANSLATE out USING ' _'.
ENDMETHOD. "_protect_label
METHOD _build_character_style.
DATA : lw_string TYPE string,
lw_char6(6) TYPE c,
lw_intsize TYPE i.
CLEAR xml.
IF style_effect IS SUPPLIED.
IF NOT style_effect-color IS INITIAL.
CONCATENATE xml
'<w:color w:val="'
style_effect-color
'"/>'
INTO xml.
ENDIF.
IF NOT style_effect-bgcolor IS INITIAL.
CONCATENATE xml
'<w:shd w:val="clear" w:color="auto" w:fill="'
style_effect-bgcolor
'"/>'
INTO xml.
ENDIF.
IF style_effect-bold = c_true.
CONCATENATE xml
'<w:b/>'
INTO xml.
ENDIF.
IF style_effect-italic = c_true.
CONCATENATE xml
'<w:i/>'
INTO xml.
ENDIF.
IF style_effect-underline = c_true.
CONCATENATE xml
'<w:u w:val="single"/>'
INTO xml.
ENDIF.
IF style_effect-strike = c_true.
CONCATENATE xml
'<w:strike/>'
INTO xml.
ENDIF.
IF style_effect-caps = c_true.
CONCATENATE xml
'<w:caps/>'
INTO xml.
ENDIF.
IF style_effect-smallcaps = c_true.
CONCATENATE xml
'<w:smallCaps/>'
INTO xml.
ENDIF.
IF NOT style_effect-highlight IS INITIAL.
CONCATENATE xml
'<w:highlight w:val="'
style_effect-highlight
'"/>'
INTO xml.
ENDIF.
IF NOT style_effect-spacing IS INITIAL AND style_effect-spacing CO '0123456789 -'.
IF style_effect-spacing GT 0.
lw_string = style_effect-spacing.
CONDENSE lw_string NO-GAPS.
ELSE.
lw_string = - style_effect-spacing.
CONDENSE lw_string NO-GAPS.
CONCATENATE '-' lw_string INTO lw_string.
ENDIF.
CONCATENATE xml
'<w:spacing w:val="'
lw_string
'"/>'
INTO xml.
ENDIF.
IF style_effect-size IS NOT INITIAL.
lw_intsize = style_effect-size * 2.
lw_char6 = lw_intsize.
CONDENSE lw_char6 NO-GAPS.
CONCATENATE xml
'<w:sz w:val="'
lw_char6
'"/>'
'<w:szCs w:val="'
lw_char6
'"/>'
INTO xml.
ENDIF.
IF style_effect-sup = c_true.
CONCATENATE xml
'<w:vertAlign w:val="superscript"/>'
INTO xml.
ELSEIF style_effect-sub = c_true.
CONCATENATE xml
'<w:vertAlign w:val="subscript"/>'
INTO xml.
ENDIF.
IF NOT style_effect-font IS INITIAL.
CONCATENATE xml
'<w:rFonts w:ascii="'
style_effect-font
'" w:hAnsi="'
style_effect-font
'"/>'
INTO xml.
ENDIF.
ENDIF.
IF style IS SUPPLIED AND style IS NOT INITIAL.
READ TABLE mt_list_style WITH KEY type = c_type_character
name = style
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CONCATENATE xml
'<w:rStyle w:val="'
style
'"/>'
INTO xml.
ELSE.
invalid_style = c_true.
ENDIF.
ENDIF.
IF NOT xml IS INITIAL.
CONCATENATE '<w:rPr>'
xml
'</w:rPr>'
INTO xml.
ENDIF.
ENDMETHOD. "_build_character_style
METHOD _build_paragraph_style.
DATA : lw_substyle TYPE string,
lw_size TYPE string,
lw_space TYPE string,
lw_indent TYPE string.
IF style IS SUPPLIED AND NOT style IS INITIAL.
READ TABLE mt_list_style WITH KEY type = c_type_paragraph
name = style
TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
CONCATENATE xml
'<w:pStyle w:val="'
style
'"/>'
INTO xml.
ELSE.
invalid_style = c_true.
ENDIF.
ENDIF.
IF style_effect-break_before = c_true.
CONCATENATE xml
'<w:pageBreakBefore/>'
INTO xml.
ENDIF.
IF NOT style_effect-hierarchy_level IS INITIAL.
lw_size = style_effect-hierarchy_level - 1.
CONDENSE lw_size NO-GAPS.
CONCATENATE xml
'<w:outlineLvl w:val="'
lw_size
'"/>'
INTO xml.
ENDIF.
IF NOT style_effect-alignment IS INITIAL.
CONCATENATE xml
'<w:jc w:val="'
style_effect-alignment
'"/>'
INTO xml.
ENDIF.
IF NOT style_effect-bgcolor IS INITIAL.
CONCATENATE xml
'<w:shd w:val="clear" w:color="auto" w:fill="'
style_effect-bgcolor
'"/>'
INTO xml.
ENDIF.
CLEAR lw_substyle.
IF style_effect-spacing_before_auto = c_true.
lw_substyle = ' w:beforeAutospacing="1"'.
ELSEIF NOT style_effect-spacing_before IS INITIAL AND style_effect-spacing_before CO '0123456789 '.
lw_space = style_effect-spacing_before.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
' w:beforeAutospacing="0" w:before="'
lw_space
'"'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF style_effect-spacing_after_auto = c_true.
CONCATENATE lw_substyle
' w:afterAutospacing="1"'
INTO lw_substyle RESPECTING BLANKS.
ELSEIF NOT style_effect-spacing_after IS INITIAL AND style_effect-spacing_after CO '0123456789 '.
lw_space = style_effect-spacing_after.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
' w:afterAutospacing="0" w:after="'
lw_space
'"'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT style_effect-interline IS INITIAL.
lw_space = style_effect-interline.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
' w:line="'
lw_space
'"'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT lw_substyle IS INITIAL.
CONCATENATE xml
'<w:spacing '
lw_substyle
'/>'
INTO xml RESPECTING BLANKS.
ENDIF.
CLEAR lw_substyle.
IF NOT style_effect-leftindent IS INITIAL AND style_effect-leftindent CO '0123456789 '.
lw_indent = style_effect-leftindent.
CONDENSE lw_indent NO-GAPS.
CONCATENATE ' w:left="'
lw_indent
'"'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT style_effect-rightindent IS INITIAL AND style_effect-rightindent CO '0123456789 '.
lw_indent = style_effect-rightindent.
CONDENSE lw_indent NO-GAPS.
CONCATENATE lw_substyle
' w:right="'
lw_indent
'"'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT style_effect-firstindent IS INITIAL AND style_effect-firstindent CO '-0123456789 '.
IF style_effect-firstindent < 0.
lw_indent = - style_effect-firstindent.
CONDENSE lw_indent NO-GAPS.
CONCATENATE lw_substyle
' w:hanging="'
lw_indent
'"'
INTO lw_substyle RESPECTING BLANKS.
ELSE.
lw_indent = style_effect-firstindent.
CONDENSE lw_indent NO-GAPS.
CONCATENATE lw_substyle
' w:firstLine="'
lw_indent
'"'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
ENDIF.
IF NOT lw_substyle IS INITIAL.
CONCATENATE xml
'<w:ind '
lw_substyle
'/>'
INTO xml RESPECTING BLANKS.
ENDIF.
* Borders
CLEAR lw_substyle.
IF NOT style_effect-border_left-style IS INITIAL
AND NOT style_effect-border_left-width IS INITIAL.
lw_size = style_effect-border_left-width.
CONDENSE lw_size NO-GAPS.
lw_space = style_effect-border_left-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:left w:val="'
style_effect-border_left-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
style_effect-border_left-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT style_effect-border_top-style IS INITIAL
AND NOT style_effect-border_top-width IS INITIAL.
lw_size = style_effect-border_top-width.
CONDENSE lw_size NO-GAPS.
lw_space = style_effect-border_top-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:top w:val="'
style_effect-border_top-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
style_effect-border_top-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT style_effect-border_right-style IS INITIAL
AND NOT style_effect-border_right-width IS INITIAL.
lw_size = style_effect-border_right-width.
CONDENSE lw_size NO-GAPS.
lw_space = style_effect-border_right-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:right w:val="'
style_effect-border_right-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
style_effect-border_right-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT style_effect-border_bottom-style IS INITIAL
AND NOT style_effect-border_bottom-width IS INITIAL.
lw_size = style_effect-border_bottom-width.
CONDENSE lw_size NO-GAPS.
lw_space = style_effect-border_bottom-space.
CONDENSE lw_space NO-GAPS.
CONCATENATE lw_substyle
'<w:bottom w:val="'
style_effect-border_bottom-style
'" w:sz="'
lw_size
'" w:space="'
lw_space
'" w:color="'
style_effect-border_bottom-color
'"/>'
INTO lw_substyle RESPECTING BLANKS.
ENDIF.
IF NOT lw_substyle IS INITIAL.
CONCATENATE xml
'<w:pBdr>'
lw_substyle
'</w:pBdr>'
INTO xml RESPECTING BLANKS.
ENDIF.
* Add section info if required
IF NOT mw_section_xml IS INITIAL.
CONCATENATE xml
mw_section_xml
INTO xml.
CLEAR mw_section_xml.
ENDIF.
IF NOT xml IS INITIAL.
CONCATENATE '<w:pPr>'
xml
'</w:pPr>'
INTO xml.
ENDIF.
ENDMETHOD. "_build_paragraph_style
METHOD _get_xml_ns.
CLEAR xml.
CONCATENATE
' xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"'
' xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"'
' xmlns:o="urn:schemas-microsoft-com:office:office"'
' xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"'
' xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"'
' xmlns:v="urn:schemas-microsoft-com:vml"'
' xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"'
' xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"'
' xmlns:w10="urn:schemas-microsoft-com:office:word"'
' xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"'
' xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"'
' xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"'
' xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"'
' xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"'
' xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"'
' mc:Ignorable="w14 wp14" ' "#EC NOTEXT
INTO xml RESPECTING BLANKS.
ENDMETHOD. "_get_xml_ns
ENDCLASS. "cl_word IMPLEMENTATION
Program ZDEMO_DOCX: Test Creation docx
ABAP Code
**----------------------------------------------------------------------*
* Demo program to show how to use the class CL_WORD (DOCX version)
* Author : S. Hermann
* Date : 27.11.2015
*---------------------------------------------------------------------*
* Generate DOCX document
* Strongly recommanded to use template because empty sap docx document
* dont have any style embed
*
* To update toc & custom fields, you have to update manually, or add a
* macro in your template :
* Private Sub Document_Open()
* ActiveDocument.Fields.Update
* End Sub
*---------------------------------------------------------------------*
* Enhancement list (TODO) :
* - Create table style
* - Manage bullets
*---------------------------------------------------------------------*
REPORT zdemo_docx.
include zcl_word.
START-OF-SELECTION.
DATA : o_doc TYPE REF TO cl_word,
s_char_style TYPE cl_word=>ty_character_style_effect,
s_para_style TYPE cl_word=>ty_paragraph_style_effect.
CREATE OBJECT o_doc
EXPORTING
tpl = 'C:\test_word_ole\template.dotx'
. "keep_tpl_content = cl_word=>c_true
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Sample usage of CL_WORD'
line_style = 'Titre'. "cl_word=>c_style_title.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Write text and apply style effect'
line_style = 'Titre1'. "cl_word=>c_style_title1.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'There is a simple text paragraph with the "Normal" style applied, without any special effect.'
line_style = cl_word=>c_style_normal.
CLEAR s_char_style.
s_char_style-color = cl_word=>c_color_blue.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Now there is a text, written in blue.'
style_effect = s_char_style.
CALL METHOD o_doc->write_note
EXPORTING
text = 'Please note that the blue is not red'.
CLEAR s_char_style.
s_char_style-color = cl_word=>c_color_black.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'And another in black. Note that without the line_style parameter, all texts will be in the same paragraph.'
style_effect = s_char_style.
CALL METHOD o_doc->write_comment
EXPORTING
text = 'this is a comment'
initials = 'SHN'.
* You could close mannually paragraph with write_line
CALL METHOD o_doc->write_line.
CLEAR s_char_style.
s_char_style-color = cl_word=>c_color_green.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Now there is a text, written in green.'
style_effect = s_char_style.
CALL METHOD o_doc->write_note
EXPORTING
text = 'And the green is not yellow'.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Text go back to default color if no color specified mannually'.
CALL METHOD o_doc->write_line.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Now write a paragraph directly from write_text (line_style)'
line_style = cl_word=>c_style_normal.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'You could play with:'.
CLEAR s_char_style.
s_char_style-italic = cl_word=>c_true.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'italic,'
style_effect = s_char_style.
CLEAR s_char_style.
s_char_style-bold = cl_word=>c_true.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'bold,'
style_effect = s_char_style.
CLEAR s_char_style.
s_char_style-underline = cl_word=>c_true.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'underline.'
style_effect = s_char_style.
CALL METHOD o_doc->write_line
EXPORTING
style = cl_word=>c_style_normal.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'You can add line break'.
* Add a break line
o_doc->write_break( ).
CLEAR s_char_style.
s_char_style-size = 18.
s_char_style-font = cl_word=>c_font_comic.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Or play also with font name or font size'
style_effect = s_char_style.
CALL METHOD o_doc->write_line.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Custom field'
line_style = 'Titre2'. "cl_word=>c_style_title2.
o_doc->write_text( 'You could add custom field : ' ).
o_doc->insert_custom_field( 'Billy_the_Kid' ).
o_doc->write_text( '. Field value could be define later in the program process' ).
o_doc->write_line( ).
* Insert a page break
o_doc->write_break( breaktype = cl_word=>c_breaktype_page ).
* You could use header/footer embbed in template
CALL METHOD o_doc->header_footer_direct_assign
EXPORTING
header = 'rId8'
header_first = 'rId11'
footer = 'rId10'
footer_first = 'rId12'.
* Now add table
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Table section'
line_style = 'Titre1'. "cl_word=>c_style_title1.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'A styled table (defined in the template)'
line_style = 'Titre2'. "cl_word=>c_style_title2.
DATA : BEGIN OF ls_carac,
f1(80) TYPE c,
f2(80) TYPE c,
END OF ls_carac,
lt_carac LIKE TABLE OF ls_carac.
ls_carac-f1 = 'Header col 1'.
ls_carac-f2 = 'Header col 2'.
APPEND ls_carac TO lt_carac.
ls_carac-f1 = 'C1'.
ls_carac-f2 = 'V1'.
APPEND ls_carac TO lt_carac.
ls_carac-f1 = 'C2'.
ls_carac-f2 = 'V2'.
APPEND ls_carac TO lt_carac.
ls_carac-f1 = 'C3'.
ls_carac-f2 = 'V3'.
APPEND ls_carac TO lt_carac.
CALL METHOD o_doc->write_table
EXPORTING
content = lt_carac
style = 'Trameclaire-Accent1'.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Basic table with style effect inside'
line_style = cl_word=>c_style_title2.
DATA : BEGIN OF ls_cle,
f1 TYPE cl_word=>ty_table_style_field,
f2 TYPE cl_word=>ty_table_style_field,
END OF ls_cle,
lt_cle LIKE TABLE OF ls_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'blue'.
ls_cle-f1-bgcolor = cl_word=>c_color_blue.
ls_cle-f1-style_effect-bold = cl_word=>c_true.
ls_cle-f1-line_style_effect-alignment = cl_word=>c_align_left.
ls_cle-f1-valign = cl_word=>c_valign_top.
ls_cle-f2-textline = 'turquoise'.
ls_cle-f2-bgcolor = cl_word=>c_color_turquoise.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'brightgreen'.
ls_cle-f1-bgcolor = cl_word=>c_color_brightgreen.
ls_cle-f1-style_effect-italic = cl_word=>c_true.
ls_cle-f1-line_style_effect-alignment = cl_word=>c_align_center.
ls_cle-f1-valign = cl_word=>c_valign_middle.
ls_cle-f2-style_effect-underline = cl_word=>c_true.
ls_cle-f2-textline = 'pink'.
ls_cle-f2-bgcolor = cl_word=>c_color_pink.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'red'.
ls_cle-f1-bgcolor = cl_word=>c_color_red.
ls_cle-f1-line_style_effect-alignment = cl_word=>c_align_right.
ls_cle-f1-valign = cl_word=>c_valign_bottom.
ls_cle-f2-style_effect-bold = cl_word=>c_true.
ls_cle-f2-textline = 'yellow'.
ls_cle-f2-bgcolor = cl_word=>c_color_yellow.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'darkblue'.
ls_cle-f1-bgcolor = cl_word=>c_color_darkblue.
ls_cle-f1-style_effect-bold = cl_word=>c_true.
ls_cle-f1-line_style_effect-alignment = cl_word=>c_align_justify.
ls_cle-f2-textline = 'teal'.
ls_cle-f2-bgcolor = cl_word=>c_color_teal.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'green'.
ls_cle-f1-bgcolor = cl_word=>c_color_green.
ls_cle-f1-style_effect-size = 40.
ls_cle-f2-style_effect-bold = cl_word=>c_true.
ls_cle-f2-textline = 'violet'.
ls_cle-f2-bgcolor = cl_word=>c_color_violet.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'darkred'.
ls_cle-f1-bgcolor = cl_word=>c_color_darkred.
ls_cle-f1-style_effect-color = cl_word=>c_color_yellow.
ls_cle-f2-style_effect-bold = cl_word=>c_true.
ls_cle-f2-textline = 'darkyellow'.
ls_cle-f2-bgcolor = cl_word=>c_color_darkyellow.
ls_cle-f2-style_effect-font = cl_word=>c_font_comic.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = 'gray'.
ls_cle-f1-bgcolor = cl_word=>c_color_gray.
ls_cle-f1-style_effect-bold = cl_word=>c_true.
ls_cle-f2-style_effect-bold = cl_word=>c_true.
ls_cle-f2-textline = 'lightgray'.
ls_cle-f2-bgcolor = cl_word=>c_color_lightgray.
APPEND ls_cle TO lt_cle.
CLEAR ls_cle.
ls_cle-f1-textline = '2 merged cells'.
ls_cle-f1-merge = 2.
APPEND ls_cle TO lt_cle.
CALL METHOD o_doc->write_table
EXPORTING
content = lt_cle
tblwidth = 9300.
* Insert a page break
o_doc->write_break( breaktype = cl_word=>c_breaktype_page ).
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Insert image'
line_style = 'Titre2'. "cl_word=>c_style_title2.
CALL METHOD o_doc->insert_image( url = 'C:\test_word_ole\image1.jpg' ).
* Insert a page break
o_doc->write_break( breaktype = cl_word=>c_breaktype_page ).
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Write table of content'
line_style = 'Titre1'. "cl_word=>c_style_title1.
CALL METHOD o_doc->write_toc.
clear s_char_style.
s_char_style-label = 'labelled content'.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Label ##LABEL##: This is a label'
style_effect = s_char_style
line_style = 'Normal'.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Label ##LABEL##: This is another'
style_effect = s_char_style
line_style = 'Normal'.
* Insert a page break
o_doc->write_break( breaktype = cl_word=>c_breaktype_page ).
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Write table of content for label "labelled content"'
line_style = 'Titre1'. "cl_word=>c_style_title1.
CALL METHOD o_doc->write_toc
exporting
label = 'labelled content'.
* Here we define the value of the custom field inserted before !
o_doc->create_custom_field( field = 'Billy_the_Kid' value = 'Billy was my hero' ).
* To change orientation of a part of the doc (and not of the entire doc)
* You have to insert a break type "section"
o_doc->write_break( breaktype = cl_word=>c_breaktype_section ).
* After the break, you could change the orientation
CALL METHOD o_doc->set_params
EXPORTING
orientation = cl_word=>c_orient_landscape.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Canvas and landscape'.
CALL METHOD o_doc->write_note
EXPORTING
text = 'An endnote on a title'
type = cl_word=>c_notetype_end.
CALL METHOD o_doc->write_line
EXPORTING
style = 'Titre1'. "cl_word=>c_style_title1.
* Draw the "paperboard" where you will draw some objects
CALL METHOD o_doc->draw_init
EXPORTING
left = 0
top = 0
width = 685
height = 350.
* Draw rectangles...
CALL METHOD o_doc->draw
EXPORTING
object = cl_word=>c_draw_rectangle
left = 436
top = 45
width = 47
height = 12.
CALL METHOD o_doc->draw
EXPORTING
object = cl_word=>c_draw_rectangle
left = 40
top = 25
width = 47
height = 12.
* Draw images...
CALL METHOD o_doc->draw
EXPORTING
object = cl_word=>c_draw_image
url = 'C:\test_word_ole\image2.jpg'
left = 230
top = 70
width = 47
height = 12.
CALL METHOD o_doc->draw
EXPORTING
object = cl_word=>c_draw_image
url = 'C:\test_word_ole\image3.png'
left = 20
top = 50
width = 600
height = 300.
* Mandatory method at end of draw
CALL METHOD o_doc->draw_finalize.
* Switch back to portrait
o_doc->write_break( breaktype = cl_word=>c_breaktype_section ).
CALL METHOD o_doc->set_params
EXPORTING
orientation = cl_word=>c_orient_portrait.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'Table with image inserted'
line_style = 'Titre1'. "cl_word=>c_style_title1.
refresh lt_cle.
clear ls_cle.
ls_cle-f1-textline = 'The second column contain the previously used image called "Variant"'.
ls_cle-f2-textline = ''.
ls_cle-f2-image_id = 'rId17'.
APPEND ls_cle TO lt_cle.
CALL METHOD o_doc->write_table
EXPORTING
content = lt_cle.
CALL METHOD o_doc->write_text
EXPORTING
textline = 'End of the doc'
line_style = 'Titre1'. "cl_word=>c_style_title1.
* You could save the doc
o_doc->save( 'C:\test_word_ole\test_doc.docx' ).