Quelquepart

Blog d'un développeur ABAP

Vous êtes ici : Accueil>Show code in Nugget

Show code in Nugget ZAUTODOC.nugg

Table of content

Program ZAUTODOC: Technical BW Documentation

Text Elements

Text symbols

Text symbolLanguageTextLength
E01EFor workbook, please enter a reference50
E02EFor multiprovider, please enter a reference50
E04ENo object match with selection50
E05EFlow cannot be used when 1 document is created by object100
E06EFlow or main object is mandatory in case of many objects and no split100
E07EWhen you enter a workbook, please do not choose other selections100
E08EMain object must be specified in the object list (infoprovider, datasource...)100
E09EMain object cannot be used when 1 document is created by object100
E10EFor bex Web Template, please enter a reference100
E11EWhen you enter a Bex Web Template, please do not choose other selections100
E12EFor infoset, please enter a reference50
M01ECheck50
M02EInitialization of the document...50
M03EWriting multiprovider info...50
M04EWriting cube info...50
M05EWriting DSO info...50
M06EWriting update rules50
M07EWriting infosource info...50
M08EWriting Datasource info...50
M09EGet list of objects to process...50
M10EFinalizing document...50
M11ESearch process chains usage...50
M12EWriting transformation...50
M13EWriting workbook info...50
M14EWriting DTP50
M15EWriting IP50
M16EWriting WAD info...50
M17EWriting Query info...50
M18EWriting InfoSet info...50
M19EWriting OpenHub info...50
M20EWriting Process chain...50
T01EObjects list50
T02EAuto save generated document50
T03EOptions50

Selection texts

NameLanguageText
P_DATEEOlder loads date to consider
P_DESTESource system (for datasource)
P_FILEEFolder where save documents
P_FLOWEFlow name
P_IPDISPEIP/DTP
P_MAINEMain object
P_RECQRYERecursive over query
P_RECURSERecursive flow
P_REFEReference
P_SKIPESkip object if file exists
P_SPLITESplit documents by object
P_WADEBex Web Template
P_WBEWorkbook
SO_CHAINEProcess Chain
SO_CUBEEInfoCubes
SO_DSEDatasources
SO_DSOEDSO
SO_IOBJEInfoObject
SO_ISEInfosources
SO_ISETEInfoSet
SO_MULTIEMultiprovider
SO_OPENEOpen Hub Destination
SO_QUERYEQuery

Dynpros

Dynpro 0007: Dummy screen for dataflow generation

Attributes
  • Type:0007
  • Number of lines defined/occupied:35
  • Number of columns defined/occupied:208
Screen fields
Field nameLabelType
CUSTOMCuCtr
____________________OK
Flow logic
PROCESS BEFORE OUTPUT.
  MODULE generate_dataflow.
*
PROCESS AFTER INPUT.
* MODULE USER_COMMAND_0007.

GUI Status

GUI Status

CodeModalTitle

Function code

CodeTextIcon

Title bar

CodeText
GENERIC&1

ABAP Code

*&---------------------------------------------------------------------*
*& Program : ZAUTODOC
*& Author  : S. Hermann
*& Date    : 30.07.2017
*& Version : 3.4
*& Required: zcl_word 1.4
*&---------------------------------------------------------------------*
*& This program allow you to generate documentation from BW system
*&
*& To add manual documentation, you can upload files in BW system.
*& Following file format are added as attachment inside the generated
*& document : DOC, DOCX, DOCM, XLS, XLSX, PPT, PPTX
*& Following file format (image) are inserted : JPG, PNG, GIF, BMP
*& You can also write direct comment (without formarting !), there are
*& also inserted inside the generated document
*& All theses manual input are added inside a "special purpose" section
*&---------------------------------------------------------------------*
*& History :
*& 2017.07.30 v3.4  :Add BW embbeded documents insertion
*&                   Add ABAP includes documentation
*&                   Add Recursive over query option
*&                   Add InfoSet quick documentation
*&                   Add Open Hub Destination documentation
*&                   Add "How to regenerate this doc" section
*&                   Mod Allow to add manually process chain in a flow
*&                   Mod Replace arbitrary object constant val by TLOGO
*&                   Mod Datasource selection changed
*&                   Mod Recursive mode is now the default mode
*&                   Fix error message for some queries
*&                   Fix translate program title in english
*&                   Fix Transformation issue with "field" targets
*&                   Fix Code cleaning
*&                   Require CL_WORD v1.4
*& 2017.03.22 v3.3 : Add Wad documentation
*&                   Add Query documentation
*&                   Add Process chain documentation
*&                   Mod Bex workbook now display also query
*&                       documentation instead of multiprovider
*&                   Add Main object management : in case of many
*&                       objects, you can specify the main which is
*&                       used for title, dataflow and filename
*&                   Add Specific documentation for each type of IOBJ
*&                       (characteristic, key figure, unit)
*&                   Add User exit search for datasource (if managed
*&                       with include/perform by datasource)
*&                   Mod Little changes in comments
*&                   Fix Rule group & segment management in transformation
*&                   Fix Issue on individual routine in transformation
*&                   Fix issue in multiprovider partprovider display
*&                   Fix dump with inactive transformation & dtp
*&                   Fix issue on dataflow generation in case of
*&                       multiple objects
*&                   Fix sy-langu <-> c_lang_default not used everywhere
*&                   Require CL_WORD v1.3.1
*& 2016.03.15 v3.2 : Add workbook label on selection screen
*&                   Add Manage reference in infopackage targets
*& 2016.01.24 v3.1 : Fix Workbook title
*&                   Add informations on InfoObject
*&                   Mod Use of external class cl_word instead of embed
*&                       Class could now be updated without change in
*&                       ZAUTODOC
*&                   Fix allow usage of DSO & MD in multi provider
*&                   Add code_display form to avoid code duplication
*&                   Add Management of duplicated objects (dso/cubes)
*&                   Add data flow image
*&                   Add auto hide spellcheck in generated document
*& 2015.11.01 v3.0 : Complete rewrite to use cl_word class (v1.01)
*& 2008       v2.0 : BI7 adaptation by Daniel Lemee
*& 2006       v1.0 : Initial release
*&---------------------------------------------------------------------*
* TODO : Query add main properties in row/col/free sel
* More complete documentation for infoset... (like multi)

REPORT  zautodoc.

*----------------------------------------------------------------------*
* Customization section
*----------------------------------------------------------------------*
CONSTANTS : BEGIN OF cs_custo,
* Display document generation progression with a detailed popup
* Instead of simple bottom messages
              progress_popup(1)      TYPE c VALUE space,

* If you want to restrict workbook to those inserted in a role, you
* could give role template
* If you dont want role restriction, leave the field empty
              workbook_role_template TYPE string VALUE space,

* Name of the word template document
* You could use local/network path like 'C:\ZAUTODOC\template.dotx'
* or SAP Web repository storage by use SAPWR: prefix 'SAPWR:ZAUTODOCTPL'
              doc_template           TYPE string VALUE 'SAPWR:ZAUTODOC_TPL',
* Document extension to generate (use .docx except if you use dotm tpl)
              doc_extension          TYPE string VALUE '.docm',
* Image cover url
* You could use local/network path like 'C:\ZAUTODOC\cover.jpg'
* or SAP Web repository storage by use SAPWR: prefix 'SAPWR:ZAUTODOCCVR'
              cover_image            TYPE string VALUE 'SAPWR:ZAUTODOC_COVER',

* Attachment Image
* You could use local/network path like 'C:\ZAUTODOC\attach.jpg'
* or SAP Web repository storage by use SAPWR: prefix 'SAPWR:ZAUTODOC_ATTACH'
              attach_image           TYPE string VALUE 'SAPWR:ZAUTODOC_ATTACH',

* Template header/footer to use
* You must use header/footer Id defined in your dotx template
              header                 TYPE string VALUE 'rId10',
              header_first           TYPE string VALUE 'rId12',
              footer                 TYPE string VALUE 'rId11',
              footer_first           TYPE string VALUE 'rId13',

* Number of empty lines to display in following table on cover page
              table_following_empty  TYPE i VALUE 1,

* Add manual pagebreak between each title1 section
* Set 'X' only if your title1 style doesnt have embed page break
              force_pagebreak_title1 TYPE c VALUE space,

* Default value for IP/DTP display
* 0 : Display
* 1 : Display only if used in process chain
* 2 : Display only if used in process chain in a node
* 3 : No display
              ip_display             TYPE c VALUE '1',

* Force usage of P_REF for workbook and multiprovider
* Usefull only if you have some duplicate structure, for exemple
* 1 infocube by region or by country or by factory...
* P_REF allow you to specify which object use
* For example : EMEA, Factory 35...
* You may have to change the P_REF data type, regarding your usage
              use_ref                TYPE c VALUE space,

* Understandable name of the reference object (factory, country...)
* Will be used in the presentation chapter of the document if p_ref is
* filled
              ref_object_name        TYPE string VALUE space,

* Default folder for generated documents
              zautodoc_default_path  TYPE string VALUE 'D:',

* Dataflow is generated on local computer. It require a temp folder
* If system cannot find a valid temp folder, use the following path
              dataflow_default_path  TYPE string VALUE 'D:',

* If ECC user exit is managed with include / external perform by datasource
* You can specify the program template of the include.
* If found, you will have the information in datasource documentation
              r3_exit_tpl            TYPE string VALUE 'ZBWI_<ds>',

* Document style
* Be carefull with style name, word suppress _ in name. It mean that
* the style labelled "My_Style" have technical name "MyStyle"
* Title styles
              style_title            TYPE string VALUE 'Titre',
              style_title1           TYPE string VALUE 'Titre1',
              style_title2           TYPE string VALUE 'Titre2',
              style_title3           TYPE string VALUE 'Titre3',
* Table Style in document for the tables with 1 line header
              table_with_head        TYPE string VALUE 'TBLWH',
* Table Style in document for the tables without header
              table_without_head     TYPE string VALUE 'TBLNH',
* Table Style in document for following table header on cover page
* Leave empty to not display following table header
              table_following_head   TYPE string VALUE 'TableauSuivi1',
* Table Style in document for following table body on cover page
* Leave empty to not display following table body
              table_following_body   TYPE string VALUE 'TableauSuivi2',
* Font Style in document for ABAP comment
              style_comment          TYPE string VALUE 'Codecomment',
* Paragraphe Style in document for ABAP code
              style_code             TYPE string VALUE 'Code',
* Font style in document for Author subtitle on cover page
              style_author           TYPE string VALUE 'Sous-titre',

            END OF cs_custo.




*----------------------------------------------------------------------*
* End of customization section - Do not change anything bellow
*----------------------------------------------------------------------*

INCLUDE zcl_word.

TYPE-POOLS rsd.

DATA : BEGIN OF s_used_pc,
         id TYPE rspcchain-chain_id,
       END OF s_used_pc,
       t_used_pc            LIKE TABLE OF s_used_pc,
       w_progress_winid(10) TYPE c.

TYPES  ty_code_table TYPE STANDARD TABLE OF string.

* Dummy declaration required for select-options declaration...
DATA : BEGIN OF so_decl,
         iobj  TYPE rsd_iobjnm,
         dso   TYPE rsd_s_odso-odsobject,
         cube  TYPE rsdgsccube-infocube,
         is    TYPE rsupdea-isource,
         ds    TYPE rsds_s_guidssele-datasource,
         multi TYPE rsd_infocube,
         query TYPE rszcompid,
         chain TYPE rspc_chain,
         iset  TYPE rsqinfoset,
         open  TYPE rsohdest,
       END OF so_decl.

DATA : w_logsys TYPE rsbasidoc-slogsys.
DATA : o_doc TYPE REF TO cl_word.

DATA : BEGIN OF s_object,
         objtype   TYPE rstlogo,
         object    TYPE string,
         subobject TYPE string,
       END OF s_object,
       s_object_main        LIKE s_object,
       t_objects_to_process LIKE TABLE OF s_object,
       t_objects_processed  LIKE TABLE OF s_object,
       t_include_to_process TYPE TABLE OF string,
       t_include_processed  TYPE TABLE OF string,
       w_doc_title          TYPE string,
       w_skip               TYPE c,
       w_lines              TYPE i,
       w_len                TYPE i,
       w_doc_filename       TYPE string.

* Domain values buffer
DATA : BEGIN OF t_buffer_domvalue OCCURS 0,
         domname  TYPE dd07t-domname,
         domvalue TYPE dd07t-domvalue_l,
         ddtext   TYPE dd07t-ddtext,
       END OF t_buffer_domvalue.

* Value list for ip/dtp display parameter
DATA : t_ip_option_list TYPE vrm_values,
       s_list           LIKE LINE OF t_ip_option_list.

* Structure to transfer data for dataflow generation
DATA : BEGIN OF s_df,
         object   TYPE string,
         objtp    TYPE rstlogo,
         url(255) TYPE c,
       END OF s_df.

CONSTANTS : c_dso              TYPE rstlogo VALUE 'ODSO',
            c_cube             TYPE rstlogo VALUE 'CUBE',
            c_iobj             TYPE rstlogo VALUE 'IOBJ',
            c_is3              TYPE rstlogo VALUE 'ISTD',
            c_is7              TYPE rstlogo VALUE 'TRCS',
            c_ds               TYPE rstlogo  VALUE 'RSDS', "tlogo datasource 7 (ISFS for 3x)
            c_multi            TYPE rstlogo VALUE 'MPRO',
            c_wb               TYPE rstlogo  VALUE 'XLWB',
            c_wad              TYPE rstlogo VALUE 'BTMP',
            c_ip               TYPE rstlogo  VALUE 'ISIP',
            c_dtp              TYPE rstlogo VALUE 'DTPA',
            c_chain            TYPE rstlogo VALUE 'RSPC',
            c_query            TYPE rstlogo VALUE 'ELEM',
            c_iset             TYPE rstlogo VALUE 'ISET',
            c_oh               TYPE rstlogo  VALUE 'DEST',
            c_msg_success      TYPE c VALUE 'S',
            c_msg_error        TYPE c VALUE 'E',
            c_msg_info         TYPE c VALUE 'I',
            c_lang_default     TYPE sy-langu VALUE 'E',
            c_objvers_active   TYPE c VALUE rs_c_objvers-active,
            c_ip_display_yes   TYPE c VALUE '0',
            c_ip_display_chain TYPE c VALUE '1',
            c_ip_display_node  TYPE c VALUE '2',
            c_ip_display_no    TYPE c VALUE '3'.

* Local Class used to get SHELL ID of a container
CLASS lcl_gui_docking_container DEFINITION INHERITING
      FROM cl_gui_docking_container FINAL.
  PUBLIC SECTION.
    METHODS get_shellid EXPORTING shellid TYPE i.
ENDCLASS.
CLASS lcl_gui_docking_container IMPLEMENTATION.
  METHOD get_shellid.
    shellid = h_control-shellid.
  ENDMETHOD.
ENDCLASS.

SELECTION-SCREEN BEGIN OF BLOCK t01 WITH FRAME TITLE text-t01.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(31) FOR FIELD p_wb.
PARAMETER p_wb TYPE rsrworkbook-workbookid.
SELECTION-SCREEN COMMENT 60(60) p_wb_lbl.
SELECTION-SCREEN END OF LINE.
PARAMETER p_wad TYPE rszwbtmphead-objid.
SELECT-OPTIONS so_query FOR so_decl-query.
SELECT-OPTIONS so_multi FOR so_decl-multi.
SELECT-OPTIONS so_iset FOR so_decl-iset.
SELECT-OPTIONS so_open FOR so_decl-open.
SELECT-OPTIONS so_iobj FOR so_decl-iobj.
SELECT-OPTIONS so_dso FOR so_decl-dso.
SELECT-OPTIONS so_cube FOR so_decl-cube.
SELECT-OPTIONS so_is FOR so_decl-is.
SELECT-OPTIONS so_ds FOR so_decl-ds.
PARAMETERS p_dest TYPE rsds-logsys.
SELECT-OPTIONS so_chain FOR so_decl-chain.
SELECTION-SCREEN END OF BLOCK t01.

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF BLOCK t02 WITH FRAME TITLE text-t02.
PARAMETER p_file TYPE string LOWER CASE OBLIGATORY.
PARAMETER p_skip AS CHECKBOX.
SELECTION-SCREEN END OF BLOCK t02.

SELECTION-SCREEN BEGIN OF BLOCK t03 WITH FRAME TITLE text-t03.
PARAMETER p_flow TYPE string LOWER CASE.
PARAMETER p_main TYPE string.
PARAMETER p_ref(2) TYPE c.
PARAMETER p_split AS CHECKBOX.
PARAMETER p_recurs AS CHECKBOX DEFAULT 'X'.
PARAMETER p_recqry AS CHECKBOX.
PARAMETER p_ipdisp TYPE c  AS LISTBOX VISIBLE LENGTH 40 DEFAULT cs_custo-ip_display.
PARAMETER p_date TYPE dats.
SELECTION-SCREEN END OF BLOCK t03.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_wb.
  PERFORM f4_wb.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_wad.
  PERFORM f4_wad.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR so_cube-low.
  PERFORM f4_cube USING 'SO_CUBE-LOW' c_cube
                  CHANGING so_cube-low.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR so_cube-high.
  PERFORM f4_cube USING 'SO_CUBE-HIGH' c_cube
                  CHANGING so_cube-high.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR so_multi-low.
  PERFORM f4_cube USING 'SO_MULTI-LOW' c_multi
                  CHANGING so_multi-low.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR so_multi-high.
  PERFORM f4_cube USING 'SO_MULTI-HIGH' c_multi
                  CHANGING so_multi-high.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR so_dso-low.
  PERFORM f4_dso USING 'SO_DSO-LOW'
                 CHANGING so_dso-low.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR so_dso-high.
  PERFORM f4_dso USING 'SO_DSO-HIGH'
                 CHANGING so_dso-high.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  PERFORM f4_file.


INITIALIZATION.
* Get logical system
  CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
    IMPORTING
      own_logical_system             = w_logsys
    EXCEPTIONS
      own_logical_system_not_defined = 1
      OTHERS                         = 2.

* Search if server is prod
  SELECT SINGLE mandt INTO sy-mandt
         FROM t000
         WHERE mandt = sy-mandt
         AND cccategory = 'P'.
* Set date range of loads
* - In any non productive environment, take long range of loads
  IF sy-subrc NE 0.
    p_date = sy-datum - 3650.
* - In productive environment, take last year and current year
*   loads as reference
  ELSE.
    p_date(4) = sy-datum(4) - 1.
    p_date+4 = '0101'.
  ENDIF.

* Build value list for ip/dtp display parameter
  s_list-key = c_ip_display_yes.
  s_list-text = 'Display'.
  APPEND s_list TO t_ip_option_list.
  s_list-key = c_ip_display_chain.
  s_list-text = 'Display only if used in process chain'.
  APPEND s_list TO t_ip_option_list.
  s_list-key = c_ip_display_node.
  s_list-text = 'Display only if used in process chain in a node'.
  APPEND s_list TO t_ip_option_list.
  s_list-key = c_ip_display_no.
  s_list-text = 'No display'.
  APPEND s_list TO t_ip_option_list.

* Set default save folder
  p_file = cs_custo-zautodoc_default_path.

AT SELECTION-SCREEN OUTPUT.
  CALL FUNCTION 'VRM_SET_VALUES'
    EXPORTING
      id     = 'P_IPDISP'
      values = t_ip_option_list.

* Workbook label
  IF NOT p_wb IS INITIAL AND p_wb_lbl IS INITIAL.
    SELECT SINGLE title
           FROM rsrwbindext
           INTO p_wb_lbl
           WHERE workbookid = p_wb
           AND langu = c_lang_default
           AND objvers = c_objvers_active.
  ELSEIF p_wb IS INITIAL AND NOT p_wb_lbl IS INITIAL.
    CLEAR p_wb_lbl.
  ENDIF.

START-OF-SELECTION.

* Control on mandatory fields
  IF cs_custo-use_ref NE space AND NOT p_wb IS INITIAL
  AND p_ref IS INITIAL.
    MESSAGE 'For workbook, please enter a reference'(e01)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ENDIF.
  IF cs_custo-use_ref NE space AND NOT p_wad IS INITIAL
  AND p_ref IS INITIAL.
    MESSAGE 'For bex Web Template, please enter a reference'(e10)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ENDIF.
  IF cs_custo-use_ref NE space AND NOT so_multi[] IS INITIAL
  AND p_ref IS INITIAL.
    MESSAGE 'For multiprovider, please enter a reference'(e02)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ENDIF.
  IF cs_custo-use_ref NE space AND NOT so_iset[] IS INITIAL
  AND p_ref IS INITIAL.
    MESSAGE 'For infoset, please enter a reference'(e12)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ENDIF.

* Correct folder if incorrect
  w_len = strlen( p_file ).
  w_len = w_len - 1.
  IF p_file+w_len(1) NE '\'.
    CONCATENATE p_file '\' INTO p_file.
  ENDIF.

* Get list of initial objects to process
  PERFORM fill_objects_to_process.

*  IF sy-uname = '1HERMANN'. "test query*
*    DATA ls_object LIKE LINE OF t_objects_to_process.
*    ls_object-objtype = c_query.
*    "ls_object-object = 'FL1M01_Q00402'.
*    ls_object-object = 'FL1M01_Q006'.
*    APPEND ls_object TO t_objects_to_process.
*  ENDIF.

* Control before create doc
  DESCRIBE TABLE t_objects_to_process LINES w_lines.
  IF w_lines IS INITIAL.
    MESSAGE 'No object match with selection'(e04)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ELSEIF p_split NE space AND NOT p_flow = space.
    MESSAGE 'Flow cannot be used when 1 document is created by object'(e05)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ELSEIF p_split NE space AND NOT p_main = space.
    MESSAGE 'Main object cannot be used when 1 document is created by object'(e09)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ELSEIF w_lines GT 1 AND p_split = space AND p_flow = space
  AND p_main = space.
    MESSAGE 'Flow or main object is mandatory in case of many objects and no split'(e06)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ELSEIF p_wb NE space AND w_lines > 1.
    MESSAGE 'When you enter a workbook, please do not choose other selections'(e07)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ELSEIF p_wad NE space AND w_lines > 1.
    MESSAGE 'When you enter a Bex Web Template, please do not choose other selections'(e11)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ENDIF.

  IF p_main NE space.
    READ TABLE t_objects_to_process WITH KEY object = p_main
               INTO s_object_main.
    IF sy-subrc NE 0.
      MESSAGE 'Main object must be specified in the object list (infoprovider, datasource...)'(e08)
              TYPE c_msg_success DISPLAY LIKE c_msg_error.
      RETURN.
    ENDIF.
  ENDIF.

* Begin of processing objects
  WHILE NOT t_objects_to_process IS INITIAL.

* Read next object to process
    READ TABLE t_objects_to_process INTO s_object INDEX 1.
    IF sy-subrc NE 0.
      EXIT. "exit while
    ENDIF.

* Add object to the processed buffer
    APPEND s_object TO t_objects_processed.

* Remove object from the buffer
    DELETE t_objects_to_process INDEX 1.

    PERFORM object_progress_bar USING s_object-object
                                      s_object-objtype
                                      'Check'(m01).

    IF o_doc IS INITIAL.
      CLEAR w_skip.
      IF NOT s_object_main IS INITIAL.
        PERFORM get_doc_title USING s_object_main-objtype
                                    s_object_main-object
                                    s_object_main-subobject
                              CHANGING w_doc_title.
      ELSE.
        PERFORM get_doc_title USING s_object-objtype
                                    s_object-object
                                    s_object-subobject
                              CHANGING w_doc_title.
      ENDIF.
      w_doc_filename = w_doc_title.
      TRANSLATE w_doc_filename USING '._(_)_/_\_:_'.
      CONCATENATE p_file w_doc_filename cs_custo-doc_extension
                  INTO w_doc_filename.
      IF p_skip NE space.
        w_skip = cl_gui_frontend_services=>file_exist( w_doc_filename ).
      ENDIF.
    ENDIF.

* Initialize a new word object if necessary
    IF w_skip = space AND o_doc IS INITIAL.
      IF s_object_main IS INITIAL.
        PERFORM init_document USING s_object.
      ELSE.
        PERFORM init_document USING s_object_main.
      ENDIF.
    ENDIF.

    CASE s_object-objtype.
      WHEN c_cube.
        PERFORM cube USING s_object-object c_cube.
      WHEN c_dso.
        PERFORM dso USING s_object-object.
      WHEN c_iobj.
        PERFORM iobj USING s_object-object.
      WHEN c_is3.
        PERFORM isource USING s_object-object s_object-subobject.
      WHEN c_is7.
        PERFORM isource7 USING s_object-object.
      WHEN c_ds.
        PERFORM datasource USING s_object-subobject s_object-object.
      WHEN c_multi.
        PERFORM multi USING s_object-object.
      WHEN c_wb.
        PERFORM wb USING s_object-object.
      WHEN c_wad.
        PERFORM wad USING s_object-object.
      WHEN c_query.
        PERFORM query USING s_object-object.
      WHEN c_chain.
        APPEND s_object-object TO t_used_pc.
      WHEN c_iset.
        PERFORM infoset USING s_object-object.
      WHEN c_oh.
        PERFORM openhub USING s_object-object.
    ENDCASE.

* End of document : Save the doc
    IF w_skip = space AND p_split NE space.
      PERFORM finalize_doc USING s_object.
      FREE o_doc.
    ENDIF. "if p_split ne space
  ENDWHILE.

  IF NOT o_doc IS INITIAL.
    CLEAR s_object.
    s_object-object = p_flow.
    PERFORM finalize_doc USING s_object.
  ENDIF.

  PERFORM object_progress_bar_close.


*&---------------------------------------------------------------------*
*&      Form  init_document
*&---------------------------------------------------------------------*
*       Initialize word document
*----------------------------------------------------------------------*
*      -->FS_OBJECT  Object to initialize
*----------------------------------------------------------------------*
FORM init_document USING fs_object LIKE s_object.
  DATA : BEGIN OF ls_suivi1,
           f1(80) TYPE c,
         END OF ls_suivi1,
         lt_suivi1 LIKE TABLE OF ls_suivi1,
         BEGIN OF ls_suivi2,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
         END OF ls_suivi2,
         lt_suivi2 LIKE TABLE OF ls_suivi2,
         lw_author TYPE string,
         lw_texte  TYPE string,
         lw_imgurl TYPE string,
         ls_style  TYPE cl_word=>ty_character_style_effect.

  PERFORM object_progress_bar
          USING fs_object-object fs_object-objtype
                'Initialization of the document...'(m02).

* Create a new empty document based on template
  CREATE OBJECT o_doc
    EXPORTING
      tpl = cs_custo-doc_template.

* Use header/footer defined in tpl
  IF NOT cs_custo-doc_template IS INITIAL.
    CALL METHOD o_doc->header_footer_direct_assign
      EXPORTING
        header       = cs_custo-header
        header_first = cs_custo-header_first
        footer       = cs_custo-footer
        footer_first = cs_custo-footer_first.
  ENDIF.

* Cover page
  CALL METHOD o_doc->write_text
    EXPORTING
      textline = 'BW TECHNICAL SPECIFICATION'.
  CALL METHOD o_doc->write_break.

  CALL METHOD o_doc->set_title( w_doc_title ).

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = w_doc_title
      line_style = cs_custo-style_title.

* Add author as subtitle
  SELECT SINGLE name_textc INTO lw_author
         FROM user_addr
         WHERE bname = sy-uname.
  CONCATENATE 'By' lw_author INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_author.

  IF NOT cs_custo-cover_image IS INITIAL.
    o_doc->insert_image( url = cs_custo-cover_image ).
  ENDIF.

  IF NOT cs_custo-table_following_head IS INITIAL.
    ls_suivi1-f1 = 'Update following'.
    APPEND ls_suivi1 TO lt_suivi1.
    CALL METHOD o_doc->write_table
      EXPORTING
        content  = lt_suivi1
        style    = cs_custo-table_following_head
        tblwidth = 9300.
  ENDIF.

  IF NOT cs_custo-table_following_body IS INITIAL.
    ls_suivi2-f1 = 'Version - Date'.
    ls_suivi2-f2 = 'Chapter'.
    ls_suivi2-f3 = 'Author / Description of the modification'.
    APPEND ls_suivi2 TO lt_suivi2.

    CONCATENATE 'v1.0 - ' sy-datum+6(2) '.' sy-datum+4(2) '.' sy-datum(4)
                INTO ls_suivi2-f1 RESPECTING BLANKS.
    ls_suivi2-f2 = ''.
    CONCATENATE lw_author '/ Initial release'
                INTO ls_suivi2-f3 SEPARATED BY space.
    APPEND ls_suivi2 TO lt_suivi2.

    CLEAR ls_suivi2.
    DO cs_custo-table_following_empty TIMES.
      APPEND ls_suivi2 TO lt_suivi2.
    ENDDO.
    CALL METHOD o_doc->write_table
      EXPORTING
        content  = lt_suivi2
        style    = cs_custo-table_following_body
        tblwidth = 9300.
  ENDIF.

  IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
    CALL METHOD o_doc->write_newpage.
  ENDIF.

* Sommaire
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Table of content'
      line_style = cs_custo-style_title1.

  CALL METHOD o_doc->write_toc.

  IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
    CALL METHOD o_doc->write_newpage.
  ENDIF.

* Introduction
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Introduction'
      line_style = cs_custo-style_title1.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Object of the document'
      line_style = cs_custo-style_title2.

  IF p_flow IS INITIAL.
    CONCATENATE 'The present document describe the object named'
                 w_doc_title
                INTO lw_texte SEPARATED BY space.
    IF p_recurs NE space.
      CONCATENATE lw_texte 'and all his subsequent flow'
                  INTO lw_texte SEPARATED BY space.
    ENDIF.
  ELSE.
    CONCATENATE 'The present document describe the flow named'
                w_doc_title
                INTO lw_texte SEPARATED BY space.
  ENDIF.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline = lw_texte.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = '. All the technical settings required to create object and loading flow are detailed.'
      line_style = cl_word=>c_style_normal.

  IF NOT p_ref IS INITIAL.
    CONCATENATE 'Reference' cs_custo-ref_object_name
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title2.
    CONCATENATE 'This flow is generic. Each'
                cs_custo-ref_object_name
                'have the same flow, duplicated.'
                'To create this document, 1'
                cs_custo-ref_object_name
                'is taken as reference, this is the'
                cs_custo-ref_object_name
                p_ref
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline = lw_texte.

    CONCATENATE '. Each time you find a reference to a bw object specific for this'
                cs_custo-ref_object_name
                'you can translate it to any other'
                cs_custo-ref_object_name
                'as the flow is duplicated for all of them.'
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.
  ENDIF.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Loads information'
      line_style = cs_custo-style_title2.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline = 'Following objects are loaded using process chains: '.
  CALL METHOD o_doc->write_line
    EXPORTING
      style = cl_word=>c_style_normal.

  CALL METHOD o_doc->insert_virtual_field
    EXPORTING
      field              = 'process_chain'
      field_as_paragraph = cl_word=>c_true.

* Add flowmap only for infoproviders (iobj/dso/cube/multi)
  IF fs_object-objtype = c_iobj
  OR fs_object-objtype = c_multi
  OR fs_object-objtype = c_dso
  OR fs_object-objtype = c_cube
  OR fs_object-objtype = c_iset
  OR fs_object-objtype = c_oh.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Data flow'
        line_style = cs_custo-style_title2.
    IF p_split = space AND NOT t_objects_to_process IS INITIAL
    AND p_main IS INITIAL.
      CLEAR ls_style.
      ls_style-italic = cl_word=>c_true.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline     = 'Complex flow, please generate manually the flowmap'
          style_effect = ls_style
          line_style   = cl_word=>c_style_normal.
    ELSE.
      PERFORM get_dataflow USING fs_object-object fs_object-objtype
                           CHANGING lw_imgurl.

      CALL METHOD o_doc->insert_image
        EXPORTING
          url = lw_imgurl.
    ENDIF.
  ENDIF. "flowmap

ENDFORM.                    "init_document

*&---------------------------------------------------------------------*
*&      Form  multi
*&---------------------------------------------------------------------*
*       Display documentation for a Multiprovider
*----------------------------------------------------------------------*
*      -->FW_MULTI   Multiprovider
*----------------------------------------------------------------------*
FORM multi USING fw_multi TYPE string.
  DATA : lw_multi TYPE rsdcube-infocube,
         BEGIN OF ls_map,
           iobjnm   TYPE rsdicmultiiobj-iobjnm,
           partcube TYPE rsdicmultiiobj-partcube,
           partiobj TYPE rsdicmultiiobj-partiobj,
         END OF ls_map,
         lt_map LIKE TABLE OF ls_map,
         BEGIN OF ls_iprov,
           iprov TYPE rsdcube-infocube,
           tpl   TYPE rsdcube-infocube,
           type  TYPE rstlogo,
           ref   LIKE p_ref,
           rules TYPE i,
         END OF ls_iprov,
         lt_iprov     LIKE TABLE OF ls_iprov,
         lr_partcubes LIKE RANGE OF ls_map-partcube,
         ls_partcubes LIKE LINE OF lr_partcubes,
         ls_object    LIKE s_object.
  DATA : BEGIN OF ls_tab,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
         END OF ls_tab,
         lt_tab   LIKE TABLE OF ls_tab,
         lt_cubes LIKE TABLE OF ls_iprov-iprov,
         lt_dso   LIKE TABLE OF ls_iprov-iprov,
         lt_iobj  LIKE TABLE OF ls_iprov-iprov.

  lw_multi = fw_multi.

  IF w_skip = space.
    PERFORM object_progress_bar USING fw_multi c_multi
                                      'Writing multiprovider info...'(m03).
  ENDIF.

* A multicube is a cube in BW. Display cube infos...
  PERFORM cube USING fw_multi c_multi.

* Get mapping
  SELECT iobjnm partcube partiobj FROM rsdicmultiiobj
         INTO TABLE lt_map
         WHERE infocube = lw_multi
         AND objvers = c_objvers_active.

* Build list of infoproviders
  LOOP AT lt_map INTO ls_map.
    ls_iprov-iprov = ls_map-partcube.
    ls_iprov-rules = 1.
    COLLECT ls_iprov INTO lt_iprov.
  ENDLOOP.
  SORT lt_iprov.
  DELETE ADJACENT DUPLICATES FROM lt_iprov.

  LOOP AT lt_iprov INTO ls_iprov.
    IF NOT p_ref IS INITIAL.
      PERFORM get_reference USING    ls_iprov-iprov
                            CHANGING ls_iprov-tpl
                                     ls_iprov-ref.
* Keep only cubes from reference & non referrables cubes
      IF ls_iprov-tpl NE space AND NOT ls_iprov-ref IS INITIAL
      AND ls_iprov-ref NE p_ref.
        DELETE lt_iprov.
        CONTINUE.
      ELSE.
        MODIFY lt_iprov FROM ls_iprov.
      ENDIF.
    ENDIF.
    ls_partcubes = 'IEQ'.
    ls_partcubes-low = ls_iprov-iprov.
    APPEND ls_partcubes TO lr_partcubes.
  ENDLOOP.

* Get cubes from infoprov used in multi
  SELECT infocube INTO TABLE lt_cubes
         FROM rsdcube
         FOR ALL ENTRIES IN lt_iprov
         WHERE infocube = lt_iprov-iprov
         AND objvers = c_objvers_active.

* Get DSO from infoprov used in multi
  SELECT odsobject INTO TABLE lt_dso
         FROM rsdodso
         FOR ALL ENTRIES IN lt_iprov
         WHERE odsobject = lt_iprov-iprov
         AND objvers = c_objvers_active.

* Get MD from infoprov used in multi
  SELECT iobjnm INTO TABLE lt_iobj
         FROM rsdiobj
         FOR ALL ENTRIES IN lt_iprov
         WHERE iobjnm = lt_iprov-iprov
         AND objvers = c_objvers_active.

  IF w_skip = space.
* Remove all mapping that is not in list of kept cubes
    DELETE lt_map WHERE NOT partcube IN lr_partcubes.

* Replace duplicated objects by xx in mapping
    LOOP AT lt_iprov INTO ls_iprov WHERE NOT tpl = space.
      IF NOT ls_iprov-tpl IS INITIAL.
        REPLACE ALL OCCURRENCES OF ls_iprov-iprov
                IN TABLE lt_map WITH ls_iprov-tpl
                RESPECTING CASE.
      ENDIF.
    ENDLOOP.

* Write list of used cubes
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Linked InfoProviders'
        line_style = cs_custo-style_title2.
    REFRESH lt_tab.
    CLEAR ls_tab.
    ls_tab-f1 = 'Type'.
    IF NOT p_ref IS INITIAL.
      ls_tab-f2 = 'Infoprovider template'.
    ELSE.
      ls_tab-f2 = 'Infoprovider'.
    ENDIF.
    ls_tab-f3 = 'Associated rules'.
    APPEND ls_tab TO lt_tab.
    LOOP AT lt_iprov INTO ls_iprov.
      CLEAR ls_tab.
      READ TABLE lt_cubes WITH KEY = ls_iprov-iprov
                 TRANSPORTING NO FIELDS.
      IF sy-subrc = 0.
        ls_tab-f1 = 'CUBE'.
        ls_iprov-type = c_cube.
      ENDIF.
      IF sy-subrc NE 0.
        READ TABLE lt_dso WITH KEY = ls_iprov-iprov
                   TRANSPORTING NO FIELDS.
        IF sy-subrc = 0.
          ls_tab-f1 = 'DSO'.
          ls_iprov-type = c_dso.
        ENDIF.
      ENDIF.
      IF sy-subrc NE 0.
        READ TABLE lt_iobj WITH KEY = ls_iprov-iprov
                   TRANSPORTING NO FIELDS.
        IF sy-subrc = 0.
          ls_tab-f1 = 'IOBJ'.
          ls_iprov-type = c_iobj.
        ENDIF.
      ENDIF.
      IF NOT ls_iprov-tpl IS INITIAL.
        ls_tab-f2 = ls_iprov-tpl.
      ELSE.
        ls_tab-f2 = ls_iprov-iprov.
      ENDIF.
      ls_tab-f3 = ls_iprov-rules.
      CONDENSE ls_tab-f3 NO-GAPS.
      APPEND ls_tab TO lt_tab.
      MODIFY lt_iprov FROM ls_iprov.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_tab
        style   = cs_custo-table_with_head.

* Write mapping
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Detailed Mapping'
        line_style = cs_custo-style_title2.
    REFRESH lt_tab.
    CLEAR ls_tab.
    ls_tab-f1 = 'InfoObject'.
    ls_tab-f2 = 'Linked Provider'.
    ls_tab-f3 = 'Linked InfoObject'.
    APPEND ls_tab TO lt_tab.
    LOOP AT lt_map INTO ls_map.
      CLEAR ls_tab.
      ls_tab-f1 = ls_map-iobjnm.
      ls_tab-f2 = ls_map-partcube.
      ls_tab-f3 = ls_map-partiobj.
      APPEND ls_tab TO lt_tab.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_tab
        style   = cs_custo-table_with_head.
  ENDIF.

* Finally add objects to process list, if recursive mode activated
  IF p_recurs NE space.
    LOOP AT lt_iprov INTO ls_iprov WHERE NOT type IS INITIAL.
      CLEAR ls_object.
      ls_object-object = ls_iprov-iprov.
      ls_object-objtype = ls_iprov-type.
      PERFORM add_object_to_queue USING ls_object.
    ENDLOOP.
  ENDIF.
ENDFORM.                    "multi

*&---------------------------------------------------------------------*
*&      Form  cube
*&---------------------------------------------------------------------*
*       Display documentation for an InfoCube
*----------------------------------------------------------------------*
*      -->FW_CUBE    InfoProvider
*      -->FW_TYPE    Type of provider : Cube or Multiprovider
*----------------------------------------------------------------------*
FORM cube USING fw_cube TYPE string
                fw_type TYPE rstlogo.
  DATA : ls_cube_detail  TYPE  rsd_s_cube,
         lt_cube_dime    TYPE  rsd_t_dime,
         ls_cube_dime    LIKE LINE OF lt_cube_dime,
         lt_cube_dimiobj TYPE rsd_t_dime_iobj,
         ls_cube_dimiobj LIKE LINE OF lt_cube_dimiobj,
         lt_cube_ikyf    TYPE rsd_t_cube_iobj,
         ls_cube_ikyf    LIKE LINE OF lt_cube_ikyf,
         lw_texte        TYPE string,
         lw_dummy        TYPE c.
  DATA : BEGIN OF ls_carac,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
         END OF ls_carac,
         lt_carac LIKE TABLE OF ls_carac.
  DATA : BEGIN OF ls_tab1,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
           f5(80) TYPE c,
         END OF ls_tab1,
         lt_tab1 LIKE TABLE OF ls_tab1.
  DATA : BEGIN OF ls_ratio,
           f1(80) TYPE c,
           f2(80) TYPE c,
         END OF ls_ratio,
         lt_ratio LIKE TABLE OF ls_ratio,
         BEGIN OF ls_iobj_atr_txt,
           iobjnm TYPE rsdiobjt-iobjnm,
           txtlg  TYPE rsdiobjt-txtlg,
         END OF ls_iobj_atr_txt,
         lt_iobj_atr_txt LIKE TABLE OF ls_iobj_atr_txt.

  ls_cube_detail-infocube = fw_cube.

  IF w_skip = space.
    IF fw_type = c_cube.
      PERFORM object_progress_bar USING fw_cube c_cube
                                        'Writing cube info...'(m04).
    ENDIF.

* Get cube informations
    CALL FUNCTION 'RSD_CUBE_GET'
      EXPORTING
        i_infocube         = ls_cube_detail-infocube
        i_objvers          = c_objvers_active
        i_with_atr_nav     = 'X'
      IMPORTING
        e_s_cube           = ls_cube_detail
        e_t_dime           = lt_cube_dime
        e_t_dime_iobj      = lt_cube_dimiobj
        e_t_cube_iobj      = lt_cube_ikyf
      EXCEPTIONS
        infocube_not_found = 1.
    IF sy-subrc NE 0.
      RETURN.
    ENDIF.

* Get infoobject label
    IF NOT lt_cube_dimiobj IS INITIAL.
      LOOP AT lt_cube_dimiobj INTO ls_cube_dimiobj.
        IF ls_cube_dimiobj-atrnavfl = space.
          ls_iobj_atr_txt-iobjnm = ls_cube_dimiobj-iobjnm.
        ELSE.
          SPLIT ls_cube_dimiobj-iobjnm AT '__' INTO lw_dummy ls_iobj_atr_txt-iobjnm.
        ENDIF.
        APPEND ls_iobj_atr_txt TO lt_iobj_atr_txt.
      ENDLOOP.
      SELECT iobjnm txtlg INTO TABLE lt_iobj_atr_txt
             FROM rsdiobjt
             FOR ALL ENTRIES IN lt_iobj_atr_txt
             WHERE langu = c_lang_default
             AND   iobjnm = lt_iobj_atr_txt-iobjnm
             AND   objvers = c_objvers_active.
      SORT lt_iobj_atr_txt BY iobjnm.
    ENDIF.
* Get key figure label
    IF NOT lt_cube_ikyf IS INITIAL.
      DELETE lt_cube_ikyf WHERE iobjtp NE 'KYF'.
    ENDIF.
    IF NOT lt_cube_ikyf IS INITIAL.
      SELECT iobjnm txtlg APPENDING TABLE lt_iobj_atr_txt
             FROM rsdiobjt
             FOR ALL ENTRIES IN lt_cube_ikyf
             WHERE langu = c_lang_default
             AND   iobjnm = lt_cube_ikyf-iobjnm
             AND   objvers = c_objvers_active.
      SORT lt_iobj_atr_txt BY iobjnm.
    ENDIF.

    IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
      CALL METHOD o_doc->write_newpage.
    ENDIF.

* Infocube title
    IF fw_type = c_cube.
      CONCATENATE 'InfoCube' ls_cube_detail-infocube INTO lw_texte
                  SEPARATED BY space.
    ELSE.
      CONCATENATE 'Multiprovider' ls_cube_detail-infocube INTO lw_texte
                  SEPARATED BY space.
    ENDIF.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title1.

* Infocube description
    CONCATENATE 'Description:' ls_cube_detail-txtlg INTO lw_texte
                SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.

* Insert embbeded documents
    PERFORM special_note USING fw_type fw_cube
                               cs_custo-style_title2.

* Characteristics table
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Characteristics'
        line_style = cs_custo-style_title2.
    REFRESH lt_tab1.
    CLEAR ls_tab1.
    ls_tab1-f1 = 'Characteristic'.
    ls_tab1-f2 = 'Description'.
    ls_tab1-f3 = 'Dimension'.
    ls_tab1-f4 = 'Dimension description'.
    ls_tab1-f5 = 'Dimension options'.
    APPEND ls_tab1 TO lt_tab1.
    LOOP AT lt_cube_dimiobj INTO ls_cube_dimiobj WHERE atrnavfl = space.
      IF ls_cube_dimiobj-dimension NE ls_cube_dime-dimension.
        CLEAR ls_cube_dime.
        READ TABLE lt_cube_dime INTO ls_cube_dime
                   WITH KEY dimension = ls_cube_dimiobj-dimension.
      ENDIF.
      CHECK ls_cube_dime-iobjtp NE 'DPA'
            AND ls_cube_dime-iobjtp NE 'TIM'
            AND ls_cube_dime-iobjtp NE 'UNI'.

      CLEAR ls_iobj_atr_txt.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_cube_dimiobj-iobjnm
                 BINARY SEARCH.
      CLEAR ls_tab1.
      ls_tab1-f1 = ls_cube_dimiobj-iobjnm.
      ls_tab1-f2 = ls_iobj_atr_txt-txtlg.
      ls_tab1-f3 = ls_cube_dimiobj-dimension.
      ls_tab1-f4 = ls_cube_dime-txtlg.
      IF NOT ls_cube_dime-linitfl IS INITIAL.
        ls_tab1-f5 = 'Line item'.
      ELSEIF NOT ls_cube_dime-highcard IS INITIAL.
        ls_tab1-f5 = 'High cardinality'.
      ENDIF.
      APPEND ls_tab1 TO lt_tab1.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_tab1
        style   = cs_custo-table_with_head.

* Time char. table
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Time characteristics'
        line_style = cs_custo-style_title2.
    REFRESH lt_carac.
    CLEAR ls_carac.
    ls_carac-f1 = 'Characteristic'.
    ls_carac-f2 = 'Description'.
    ls_carac-f3 = 'Dimension'.
    ls_carac-f4 = 'Dimension description'.
    APPEND ls_carac TO lt_carac.
    LOOP AT lt_cube_dimiobj INTO ls_cube_dimiobj WHERE atrnavfl = space.
      CLEAR ls_cube_dime.
      READ TABLE lt_cube_dime INTO ls_cube_dime
                 WITH KEY dimension = ls_cube_dimiobj-dimension.
      CHECK ls_cube_dime-iobjtp = 'TIM'.
      CLEAR ls_iobj_atr_txt.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_cube_dimiobj-iobjnm
                 BINARY SEARCH.
      CLEAR ls_carac.
      ls_carac-f1 = ls_cube_dimiobj-iobjnm.
      ls_carac-f2 = ls_iobj_atr_txt-txtlg.
      ls_carac-f3 = ls_cube_dimiobj-dimension.
      ls_carac-f4 = ls_cube_dime-txtlg.
      APPEND ls_carac TO lt_carac.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_carac
        style   = cs_custo-table_with_head.

* Nav attr table
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Navigation attributes'
        line_style = cs_custo-style_title2.
    REFRESH lt_carac.
    CLEAR ls_carac.
    ls_carac-f1 = 'Characteristic'.
    ls_carac-f2 = 'Description'.
    ls_carac-f3 = 'Dimension'.
    ls_carac-f4 = 'Dimension description'.
    APPEND ls_carac TO lt_carac.
    LOOP AT lt_cube_dimiobj INTO ls_cube_dimiobj WHERE atrnavfl = 'X'.
      CLEAR ls_cube_dime.
      READ TABLE lt_cube_dime INTO ls_cube_dime
                 WITH KEY dimension = ls_cube_dimiobj-dimension.
      CLEAR ls_iobj_atr_txt.
      SPLIT ls_cube_dimiobj-iobjnm AT '__'
            INTO lw_dummy ls_iobj_atr_txt-iobjnm.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_iobj_atr_txt-iobjnm
                 BINARY SEARCH.
      CLEAR ls_carac.
      ls_carac-f1 = ls_cube_dimiobj-iobjnm.
      ls_carac-f2 = ls_iobj_atr_txt-txtlg.
      ls_carac-f3 = ls_cube_dimiobj-dimension.
      ls_carac-f4 = ls_cube_dime-txtlg.
      APPEND ls_carac TO lt_carac.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_carac
        style   = cs_custo-table_with_head.

* Key figure table
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Key figures'
        line_style = cs_custo-style_title2.
    REFRESH lt_ratio.
    CLEAR ls_ratio.
    ls_ratio-f1 = 'Key figure'.
    ls_ratio-f2 = 'Description'.
    APPEND ls_ratio TO lt_ratio.
    LOOP AT lt_cube_ikyf INTO ls_cube_ikyf.
      CLEAR ls_iobj_atr_txt.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_cube_ikyf-iobjnm
                 BINARY SEARCH.
      CLEAR ls_ratio.
      ls_ratio-f1 = ls_cube_ikyf-iobjnm.
      ls_ratio-f2 = ls_iobj_atr_txt-txtlg.
      APPEND ls_ratio TO lt_ratio.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_ratio
        style   = cs_custo-table_with_head.

* Units table
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Units'
        line_style = cs_custo-style_title2.
    REFRESH lt_ratio.
    CLEAR ls_ratio.
    ls_ratio-f1 = 'Unit'.
    ls_ratio-f2 = 'Description'.
    APPEND ls_ratio TO lt_ratio.
    LOOP AT lt_cube_dimiobj INTO ls_cube_dimiobj WHERE atrnavfl = space.
      CLEAR ls_cube_dime.
      READ TABLE lt_cube_dime INTO ls_cube_dime
                 WITH KEY dimension = ls_cube_dimiobj-dimension.
      CHECK ls_cube_dime-iobjtp = 'UNI'.
      CLEAR ls_iobj_atr_txt.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_cube_dimiobj-iobjnm
                 BINARY SEARCH.
      CLEAR ls_ratio.
      ls_ratio-f1 = ls_cube_dimiobj-iobjnm.
      ls_ratio-f2 = ls_iobj_atr_txt-txtlg.
      APPEND ls_ratio TO lt_ratio.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_ratio
        style   = cs_custo-table_with_head.
  ENDIF.

  IF fw_type = c_cube.
* Update rules 3x
    PERFORM updr_list USING ls_cube_detail-infocube
                            c_cube.

* transformation 7x
    PERFORM trsf_list USING ls_cube_detail-infocube c_cube.

    IF w_skip = space.
      PERFORM get_used_pc USING ls_cube_detail-infocube c_cube.
    ENDIF.
  ENDIF.
ENDFORM.                    " cube

*&---------------------------------------------------------------------*
*&      Form  dso
*&---------------------------------------------------------------------*
*       Display documentation for a DSO
*----------------------------------------------------------------------*
*  -->  fw_dso    DSO
*----------------------------------------------------------------------*
FORM dso USING fw_dso TYPE string.
  DATA : BEGIN OF ls_carac,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
           f5(80) TYPE c,
         END OF ls_carac,
         lt_carac LIKE TABLE OF ls_carac,
         BEGIN OF ls_idx,
           f1(80) TYPE c,
           f2(80) TYPE c,
         END OF ls_idx,
         lt_idx LIKE TABLE OF ls_idx,
         BEGIN OF ls_prop,
           name  TYPE cl_word=>ty_table_style_field,
           value TYPE cl_word=>ty_table_style_field,
         END OF ls_prop,
         lt_prop   LIKE TABLE OF ls_prop,
         lw_texte  TYPE string,
         lw_domval TYPE val_text.
  DATA: lo_dso TYPE REF TO cl_rsd_odso.
  DATA: ls_dso_detail TYPE rsd_s_odso,
        lt_dso_iobj   TYPE rsdo_t_odso_iobj,
        ls_dso_iobj   LIKE LINE OF lt_dso_iobj,
        lt_dso_nav    TYPE rsdo_t_odso_atr_nav,
        ls_dso_nav    LIKE LINE OF lt_dso_nav,
        lt_index      TYPE rsd_t_odso_indx,
        ls_index      LIKE LINE OF lt_index,
        lt_index_iobj TYPE rsd_t_odso_indx_iobj,
        ls_index_iobj LIKE LINE OF lt_index_iobj,
        lt_dso_pro    TYPE rsd_t_odso_pro,
        ls_dso_pro    LIKE LINE OF lt_dso_pro.

  ls_dso_detail-odsobject = fw_dso.

  IF w_skip = space.
    PERFORM object_progress_bar USING fw_dso c_dso
                                      'Writing DSO info...'(m05).

    CALL METHOD cl_rsd_odso=>factory
      EXPORTING
        i_odsobject = ls_dso_detail-odsobject
      RECEIVING
        r_r_odso    = lo_dso.
    IF lo_dso IS INITIAL.
      RETURN.
    ENDIF.

    CALL METHOD lo_dso->get_info
      EXPORTING
        i_objvers        = 'A'
        i_with_atr_nav   = abap_true
      IMPORTING
        e_s_odso         = ls_dso_detail
        e_t_odso_iobj    = lt_dso_iobj
        e_t_odso_atr_nav = lt_dso_nav
        e_t_odso_pro     = lt_dso_pro
        e_t_odso_indx    = lt_index
        e_t_indx_iobj    = lt_index_iobj
      EXCEPTIONS
        iobj_not_found   = 1
        not_found        = 2
        OTHERS           = 3.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

    DELETE lt_dso_nav WHERE atrnavfl = space.
    SORT lt_dso_pro BY iobjnm.

    IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
      CALL METHOD o_doc->write_newpage.
    ENDIF.

* DSO Title
    CONCATENATE 'DSO' ls_dso_detail-odsobject INTO lw_texte
                SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title1.

* DSO Description
    CONCATENATE 'Description:' ls_dso_detail-txtlg INTO lw_texte
                SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.

    PERFORM get_domain_value USING 'RSDODSOTYPE'
                                   ls_dso_detail-odsotype
                             CHANGING lw_domval.

    CONCATENATE 'DSO type:' lw_domval INTO lw_texte
                SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.

* Insert embbeded documents
    PERFORM special_note USING c_dso fw_dso
                               cs_custo-style_title2.

* DSO Options
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Settings'
        line_style = cs_custo-style_title2.
    REFRESH lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Reporting Bex'.
    IF ls_dso_detail-bexfl = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Unique data records'.
    IF ls_dso_detail-insertonly = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Set Quality Status to ''OK'' Automatically'.
    IF ls_dso_detail-autoqualokfl = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Activate Data Automatically'.
    IF ls_dso_detail-autoactivatefl = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Update Data Automatically'.
    IF ls_dso_detail-autoprocessfl = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_without_head.

* Key fields
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Key fields'
        line_style = cs_custo-style_title2.

    REFRESH lt_carac.
    CLEAR ls_carac.
    ls_carac-f1 = 'InfoObject'.
    ls_carac-f2 = 'Description'.
    ls_carac-f3 = 'Type'.
    ls_carac-f4 = 'Length'.
    ls_carac-f5 = 'Decimals'.
    APPEND ls_carac TO lt_carac.

    LOOP AT lt_dso_iobj INTO ls_dso_iobj WHERE keyflag = 'X'.
      CLEAR ls_dso_pro.
      READ TABLE lt_dso_pro INTO ls_dso_pro
                 WITH KEY iobjnm = ls_dso_iobj-iobjnm
                 BINARY SEARCH.
      CLEAR ls_carac.
      ls_carac-f1 = ls_dso_iobj-iobjnm.
      ls_carac-f2 = ls_dso_pro-txtlg.
      ls_carac-f3 = ls_dso_pro-datatp.
      ls_carac-f4 = ls_dso_pro-intlen.
      ls_carac-f5 = ls_dso_pro-decimals.
      APPEND ls_carac TO lt_carac.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_carac
        style   = cs_custo-table_with_head.

* Data fields
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Data fields'
        line_style = cs_custo-style_title2.

    REFRESH lt_carac.
    CLEAR ls_carac.
    ls_carac-f1 = 'InfoObject'.
    ls_carac-f2 = 'Description'.
    ls_carac-f3 = 'Type'.
    ls_carac-f4 = 'Length'.
    ls_carac-f5 = 'Decimals'.
    APPEND ls_carac TO lt_carac.
    LOOP AT lt_dso_iobj INTO ls_dso_iobj WHERE keyflag = space.
      CLEAR ls_dso_pro.
      READ TABLE lt_dso_pro INTO ls_dso_pro
                 WITH KEY iobjnm = ls_dso_iobj-iobjnm
                 BINARY SEARCH.
      CLEAR ls_carac.
      ls_carac-f1 = ls_dso_iobj-iobjnm.
      ls_carac-f2 = ls_dso_pro-txtlg.
      ls_carac-f3 = ls_dso_pro-datatp.
      ls_carac-f4 = ls_dso_pro-intlen.
      ls_carac-f5 = ls_dso_pro-decimals.
      APPEND ls_carac TO lt_carac.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_carac
        style   = cs_custo-table_with_head.

* Navigation attributes
    IF NOT lt_dso_nav[] IS INITIAL.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Navigation attributes'
          line_style = cs_custo-style_title2.

      REFRESH lt_carac.
      CLEAR ls_carac.
      ls_carac-f1 = 'InfoObject'.
      ls_carac-f2 = 'Description'.
      ls_carac-f3 = 'Type'.
      ls_carac-f4 = 'Length'.
      ls_carac-f5 = 'Decimals'.
      APPEND ls_carac TO lt_carac.
      LOOP AT lt_dso_nav INTO ls_dso_nav.
        CLEAR ls_dso_pro.
        READ TABLE lt_dso_pro INTO ls_dso_pro
                   WITH KEY iobjnm = ls_dso_nav-atrnavnm
                   BINARY SEARCH.
        CLEAR ls_carac.
        ls_carac-f1 = ls_dso_nav-atrnavnm.
        ls_carac-f2 = ls_dso_pro-txtlg.
        ls_carac-f3 = ls_dso_pro-datatp.
        ls_carac-f4 = ls_dso_pro-intlen.
        ls_carac-f5 = ls_dso_pro-decimals.
        APPEND ls_carac TO lt_carac.
      ENDLOOP.
      CALL METHOD o_doc->write_table
        EXPORTING
          content = lt_carac
          style   = cs_custo-table_with_head.
    ENDIF.

* Indexes
    IF NOT lt_index IS INITIAL.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Indexs'
          line_style = cs_custo-style_title2.
      LOOP AT lt_index INTO ls_index.
        CONCATENATE 'Index' ls_index-indexid
                    INTO lw_texte SEPARATED BY space.

        CALL METHOD o_doc->write_text
          EXPORTING
            textline   = lw_texte
            line_style = cs_custo-style_title3.

        CALL METHOD o_doc->write_text
          EXPORTING
            textline = 'Unique:'.
        IF ls_index-uniqueflag = space.
          CALL METHOD o_doc->write_symbol
            EXPORTING
              symbol = cl_word=>c_symbol_checkbox.
        ELSE.
          CALL METHOD o_doc->write_symbol
            EXPORTING
              symbol = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        CALL METHOD o_doc->write_line
          EXPORTING
            style = cl_word=>c_style_normal.

        REFRESH lt_idx.
        CLEAR ls_idx.
        ls_idx-f1 = 'Position'.
        ls_idx-f2 = 'Field'.
        APPEND ls_idx TO lt_idx.
        LOOP AT lt_index_iobj INTO ls_index_iobj WHERE indexid = ls_index-indexid.
          CLEAR ls_idx.
          ls_idx-f1 = ls_index_iobj-posit.
          ls_idx-f2 = ls_index_iobj-iobjnm.
          APPEND ls_idx TO lt_idx.
        ENDLOOP.
        CALL METHOD o_doc->write_table
          EXPORTING
            content = lt_idx
            style   = cs_custo-table_with_head.
      ENDLOOP.
    ENDIF.
  ENDIF.

* Update rules 3x
  PERFORM updr_list USING ls_dso_detail-odsobject
                          c_dso.

* transformation 7x
  PERFORM trsf_list USING ls_dso_detail-odsobject c_dso.

  IF w_skip = space.
    PERFORM get_used_pc USING ls_dso_detail-odsobject c_dso.
  ENDIF.
ENDFORM.                    " dso

*&--------------------------------------------------------------------*
*&      Form  updr_list
*&--------------------------------------------------------------------*
*       Get list of update rules for a given target
*---------------------------------------------------------------------*
*      -->FW_TARGET  DSO/Cube/InfoObject target of update rules
*      -->FW_TYPE    Type of the target
*---------------------------------------------------------------------*
FORM updr_list USING fw_target TYPE rsupdinfo-infocube
                     fw_type TYPE rstlogo.
  DATA : BEGIN OF ls_upd_list,
           updid   TYPE rsupdid,
           dta     TYPE rsddatatarget,
           isource TYPE rsisource,
         END OF ls_upd_list,
         lt_upd_list LIKE TABLE OF ls_upd_list,
         lw_mdtext   TYPE rsupdinfo-infocube,
         ls_object   LIKE s_object,
         lw_tpl(30)  TYPE c,
         lw_ref      LIKE p_ref.

* regles mise a jour
  REFRESH lt_upd_list.
  SELECT updid infocube isource
         INTO TABLE lt_upd_list
         FROM rsupdinfo
         WHERE objvers = c_objvers_active
         AND infocube = fw_target.

  IF fw_type = c_iobj.
    CONCATENATE fw_target '___T' INTO lw_mdtext.
    SELECT updid infocube isource
           APPENDING TABLE lt_upd_list
           FROM rsupdinfo
           WHERE objvers = c_objvers_active
           AND infocube = lw_mdtext.
  ENDIF.

* Display doc for each update rule
  LOOP AT lt_upd_list INTO ls_upd_list.
* Filter duplicated object when reference object is given
    IF NOT p_ref IS INITIAL AND ls_upd_list-isource(1) = '8'.

      PERFORM get_reference USING    ls_upd_list-isource+1(29)
                            CHANGING lw_tpl lw_ref.

* Keep only cubes from reference object & non duplicated cubes
      IF lw_tpl NE space AND NOT lw_ref IS INITIAL
      AND lw_ref NE p_ref.
        CONTINUE.
      ENDIF.
    ENDIF.

    IF w_skip = space.
      PERFORM upd USING ls_upd_list-updid
                        ls_upd_list-dta
                        ls_upd_list-isource
                        fw_type.
    ENDIF.

* Display doc for each infosource
    CLEAR ls_object.
    ls_object-objtype = c_is3.
    ls_object-object = ls_upd_list-isource.
    PERFORM add_object_to_queue USING ls_object.
  ENDLOOP.

* Display doc for direct infosource (in case of infoObject)
  IF fw_type = c_iobj.
    CLEAR ls_object.
    ls_object-objtype = c_is3.
    ls_object-object = fw_target.
    ls_object-subobject = 'X'.
    PERFORM add_object_to_queue USING ls_object.
  ENDIF.
ENDFORM.                    "updr_list

*&--------------------------------------------------------------------*
*&      Form  upd
*&--------------------------------------------------------------------*
*       Display documentation for an update rule
*---------------------------------------------------------------------*
*      -->FW_UPDID   Update rule ID
*      -->FW_DTA     Target of the update rule
*      -->FW_ISOURCE Source of the update rule
*      -->FW_DTATYPE Type of the target
*---------------------------------------------------------------------*
FORM upd USING fw_updid TYPE rsupdid
               fw_dta TYPE rsddatatarget
               fw_isource TYPE rsisource
               fw_dtatype TYPE rstlogo.

  DATA lo_updr TYPE REF TO cl_rsau_updr.
  DATA : ls_updr    TYPE rsau_s_updr,
         ls_updrout LIKE LINE OF ls_updr-t_updrout,
         ls_updform LIKE LINE OF ls_updr-t_updform,
         ls_abap    LIKE LINE OF ls_updr-t_aabap,
         ls_key     LIKE LINE OF ls_updr-t_key,
         ls_dat     LIKE LINE OF ls_updr-t_dat,
         ls_aroutt  LIKE LINE OF ls_updr-t_aroutt,
         BEGIN OF ls_upd_form,
           formid TYPE rsfobuev001-formid,
           line   TYPE rsfobuev001-line,
           fsym   TYPE rsfobuev001-fsym,
         END OF ls_upd_form,
         lt_upd_form LIKE TABLE OF ls_upd_form,
         lw_texte    TYPE string,
         BEGIN OF ls_cle,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
         END OF ls_cle,
         lt_cle LIKE TABLE OF ls_cle,
         BEGIN OF ls_carac,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
         END OF ls_carac,
         lt_carac  LIKE TABLE OF ls_carac,
         lt_code   TYPE ty_code_table,
         lw_domval TYPE val_text.

  CONCATENATE 'Writing update rules'(m06) fw_isource '=>' fw_dta
              INTO lw_texte SEPARATED BY space.
  PERFORM object_progress_bar USING fw_dta fw_dtatype
                                    lw_texte.

  CALL METHOD cl_rsau_updr=>factory
    EXPORTING
      i_updid       = fw_updid
      i_dta         = fw_dta
      i_isource     = fw_isource
    RECEIVING
      r_r_updr      = lo_updr
    EXCEPTIONS
      input_invalid = 1.

  CALL METHOD lo_updr->read
    EXPORTING
      i_objvers         = c_objvers_active
    IMPORTING
      e_s_updr          = ls_updr
    EXCEPTIONS
      version_not_found = 1
      invalid_input     = 2
      read_error        = 3
      unauthorized      = 4.
  IF sy-subrc NE 0.
    RETURN.
  ENDIF.

  SELECT formid line fsym
         INTO TABLE lt_upd_form
         FROM rsfobuev001
         FOR ALL ENTRIES IN ls_updr-t_updform
         WHERE formid = ls_updr-t_updform-formula_id
         AND objvers = c_objvers_active.

* Update rule title
  CONCATENATE 'Update rule' fw_isource '=>' fw_dta
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title2.

* Update rule description
  CASE fw_dtatype.
    WHEN c_cube.
      lw_texte = 'Infocube:'.
    WHEN c_dso.
      lw_texte = 'DSO:'.
    WHEN OTHERS.
      lw_texte = 'InfoObject:'.
  ENDCASE.
  CONCATENATE lw_texte fw_dta
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.
  CONCATENATE 'Infosource:' fw_isource
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.

* Start routine display
  lw_texte = 'Start routine:'.
  READ TABLE ls_updr-t_updrout INTO ls_updrout
             WITH KEY routine = '9998'.
  IF sy-subrc NE 0.
    CONCATENATE lw_texte 'No'
                INTO lw_texte SEPARATED BY space.
  ELSE.
    CONCATENATE lw_texte 'Yes'
                INTO lw_texte SEPARATED BY space.
  ENDIF.

* Insert embbeded documents
  PERFORM special_note USING 'UPDR' fw_updid
                             cs_custo-style_title3.

  READ TABLE ls_updr-t_updrout INTO ls_updrout
             WITH KEY routine = '9999'.
  IF sy-subrc = 0.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Global data declaration routine'
        line_style = cs_custo-style_title3.
    REFRESH lt_code.
    LOOP AT ls_updr-t_aabap INTO ls_abap
            WHERE codeid = ls_updrout-codeid
            AND objvers = c_objvers_active.
      APPEND ls_abap-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDIF.

  READ TABLE ls_updr-t_updrout INTO ls_updrout
             WITH KEY routine = '9998'.
  IF sy-subrc = 0.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Start routine'
        line_style = cs_custo-style_title3.

    REFRESH lt_code.
    LOOP AT ls_updr-t_aabap INTO ls_abap
            WHERE codeid = ls_updrout-codeid
            AND objvers = c_objvers_active.
      APPEND ls_abap-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDIF.

* Key fields mapping
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Key fields'
      line_style = cs_custo-style_title3.

  REFRESH lt_cle.
  CLEAR ls_cle.
  ls_cle-f1-textline = 'Key field'.
  ls_cle-f2-textline = 'Method'.
  ls_cle-f3-textline = 'Source field'.
  ls_cle-f4-textline = 'Automatic Time Conversion'.
  APPEND ls_cle TO lt_cle.
  LOOP AT ls_updr-t_key INTO ls_key
          WHERE objvers = c_objvers_active
          AND   ruleno = '0001'.

    CLEAR ls_cle.
    ls_cle-f1-textline = ls_key-iciobjnm.

    PERFORM get_domain_value USING 'RSCALCTPKEY'
                                   ls_key-calctpkey
                             CHANGING lw_domval.
    ls_cle-f2-textline = lw_domval.
    CASE ls_key-calctpkey.
      WHEN '1'.
        ls_cle-f3-textline = ls_key-csiobjnm.
      WHEN '4'.
        ls_cle-f3-textline = ls_key-constant.
      WHEN '5'.
        ls_cle-f3-textline = ls_key-cmiobjnm.
    ENDCASE.
    IF ls_key-dateconv = space.
      ls_cle-f4-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_cle-f4-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_cle-f4-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_cle TO lt_cle.
  ENDLOOP.
  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_cle
      style   = cs_custo-table_with_head.

* Data fields mapping
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Data fields'
      line_style = cs_custo-style_title3.

  REFRESH lt_carac.
  CLEAR ls_carac.
  ls_carac-f1 = 'Data field'.
  ls_carac-f2 = 'Update type'.
  ls_carac-f3 = 'Method'.
  ls_carac-f4 = 'Source field'.
  APPEND ls_carac TO lt_carac.

  LOOP AT ls_updr-t_dat INTO ls_dat
          WHERE objvers = c_objvers_active.
    CLEAR ls_carac.
    ls_carac-f1 = ls_dat-iciobjnm.
    ls_carac-f2 = ls_dat-updtype.
    IF NOT ls_dat-updtype = 'NOP'.
      PERFORM get_domain_value USING 'RSCALCTPKEY'
                                     ls_dat-calctpdat
                               CHANGING lw_domval.
      ls_carac-f3 = lw_domval.
    ENDIF.
    IF NOT ls_dat-updtype = 'NOP'.
      CASE ls_dat-calctpdat.
        WHEN '4'.
          ls_carac-f4 = ls_dat-constant.
        WHEN '1'.
          ls_carac-f4 = ls_dat-csiobjnm.
        WHEN '5'.
          ls_carac-f4 = ls_dat-cmiobjnm.
        WHEN OTHERS.
          ls_carac-f4 = '-'.
      ENDCASE.
    ENDIF.
    APPEND ls_carac TO lt_carac.
  ENDLOOP.
  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_carac
      style   = cs_custo-table_with_head.

* Mapping individual ABAP routine display
  LOOP AT ls_updr-t_updrout INTO ls_updrout WHERE routine LT '9998'.
    CLEAR : ls_dat, ls_key.
    READ TABLE ls_updr-t_dat INTO ls_dat
               WITH KEY objvers = c_objvers_active
                        routine = ls_updrout-routine.
    CHECK ls_dat-updtype NE 'NOP'.
    IF sy-subrc NE 0.
      READ TABLE ls_updr-t_key INTO ls_key
                 WITH KEY objvers = c_objvers_active
                          routine = ls_updrout-routine.
      CHECK sy-subrc = 0.
    ENDIF.

    CLEAR ls_aroutt.
    READ TABLE ls_updr-t_aroutt INTO ls_aroutt
               WITH KEY langu = c_lang_default
                        codeid = ls_updrout-codeid
                        objvers = c_objvers_active.
    CONCATENATE 'Routine:' ls_updrout-iciobjnm '-' ls_aroutt-txtlg
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title3.

    REFRESH lt_code.
    LOOP AT ls_updr-t_aabap INTO ls_abap
            WHERE codeid = ls_updrout-codeid
            AND objvers = c_objvers_active.
      APPEND ls_abap-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDLOOP.

* Mapping individual Formulas display
  LOOP AT ls_updr-t_updform INTO ls_updform.
    CONCATENATE 'Formula:' ls_updform-iciobjnm '-' ls_updform-formulatxt
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title3.

    LOOP AT lt_upd_form INTO ls_upd_form
            WHERE formid = ls_updform-formula_id.
      lw_texte = ls_upd_form-fsym.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_texte.
    ENDLOOP.
    CALL METHOD o_doc->write_line
      EXPORTING
        style = cs_custo-style_code.
  ENDLOOP.
ENDFORM.                    "upd

*&--------------------------------------------------------------------*
*&      Form  isource
*&--------------------------------------------------------------------*
*       Display documentation for an infosource 3x
*---------------------------------------------------------------------*
*      -->FW_ISOURCE Infosource
*      -->FW_MD      Infosource directe (target is masterdata)
*---------------------------------------------------------------------*
FORM isource USING fw_isource TYPE string
                   fw_md TYPE string.
  DATA : lt_isource        TYPE rsarc_t_rssksfield,
         ls_isource        LIKE LINE OF lt_isource,
         ls_isource_detail TYPE rsist,
         lt_osource_list   TYPE rsaos_t_isosmap,
         ls_osource_list   LIKE LINE OF lt_osource_list,
         lt_osource_text   TYPE rsaos_t_oltpsourcet,
         ls_osource_text   LIKE LINE OF lt_osource_text,
         lt_osource        TYPE rsarc_t_rsrulmulti,
         ls_osource        LIKE LINE OF lt_osource,
         ls_osource_tab    LIKE LINE OF ls_osource-tab,
         lt_osource_abap   TYPE rsaa_t_aabap,
         ls_osource_abap   LIKE LINE OF lt_osource_abap,
         lt_osource_codeid TYPE rsaa_t_codeid,
         ls_osource_codeid LIKE LINE OF lt_osource_codeid,
         lt_osource_sr     TYPE rsarc_t_rstsmulti,
         ls_osource_sr     LIKE LINE OF lt_osource_sr,
         lw_isostype       TYPE rsisostype,
         lw_istype         TYPE rsrequtype,
         lw_modus          TYPE rs_modus,
         lw_texte          TYPE string,
         ls_style          TYPE cl_word=>ty_character_style_effect,
         ls_linestyle      TYPE cl_word=>ty_paragraph_style_effect,
         lw_md(1)          TYPE c,
         ls_object         LIKE s_object.

  DATA : BEGIN OF ls_osource_formule,
           line TYPE rsfobuev001-line,
           fsym TYPE rsfobuev001-fsym,
         END OF ls_osource_formule,
         lt_osource_formule LIKE TABLE OF ls_osource_formule.

  DATA : BEGIN OF ls_com,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
           f5 TYPE cl_word=>ty_table_style_field,
           f6 TYPE cl_word=>ty_table_style_field,
           f7 TYPE cl_word=>ty_table_style_field,
         END OF ls_com,
         lt_com LIKE TABLE OF ls_com,
         BEGIN OF ls_trsf,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
           f5(80) TYPE c,
         END OF ls_trsf,
         lt_trsf LIKE TABLE OF ls_trsf,
         lt_code TYPE ty_code_table,
         BEGIN OF ls_prop,
           name(80)  TYPE c,
           VALUE(80) TYPE c,
         END OF ls_prop,
         lt_prop LIKE TABLE OF ls_prop.

  ls_isource_detail-isource = fw_isource.
  IF w_skip = space.
    PERFORM object_progress_bar USING fw_isource c_is3
                                      'Writing infosource info...'(m07).
  ENDIF.
  lw_md = fw_md.
  CALL FUNCTION 'RSAR_INFOSOURCE_PREPARE' "TODO : poor perf, to replace
    EXPORTING
      i_isource       = ls_isource_detail-isource
    IMPORTING
      e_s_txt         = ls_isource_detail
      e_t_csoltpfield = lt_isource
      e_t_isosmap     = lt_osource_list
      e_t_oltpsourcet = lt_osource_text
    CHANGING
      c_isostype      = lw_isostype
      c_istype        = lw_istype
      c_modus         = lw_modus
    EXCEPTIONS
      prep_fail       = 8.
  IF sy-subrc NE 0.
    RETURN.
  ENDIF.
  IF lw_md NE space AND lt_osource_list IS INITIAL.
    RETURN.
  ENDIF.

  IF w_skip = space.
    IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
      CALL METHOD o_doc->write_newpage.
    ENDIF.

* Infosource Title
    CONCATENATE 'Infosource' ls_isource_detail-isource
    INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title1.

* Infosource description
    CONCATENATE 'Description:' ls_isource_detail-txtlg
    INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.

    IF lw_md NE space.
      CLEAR ls_style.
      ls_style-italic = cl_word=>c_true.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline     = 'Direct infosource'
          style_effect = ls_style.
      CLEAR ls_linestyle.
      ls_linestyle-alignment = cl_word=>c_align_center.
      CALL METHOD o_doc->write_line
        EXPORTING
          style_effect = ls_linestyle.
    ENDIF.

* Insert embbeded documents
    PERFORM special_note USING c_is3 fw_isource
                               cs_custo-style_title2.

* Communication structure
* Do not display comm structure for direct infosource
    IF lw_md = space.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Communication structure'
          line_style = cs_custo-style_title2.

      REFRESH lt_com.
      CLEAR ls_com.
      ls_com-f1-textline = 'InfoObject'.
      ls_com-f2-textline = 'Description'.
      ls_com-f3-textline = 'ref integrity'.
      ls_com-f4-textline = 'Check object'.
      ls_com-f5-textline = 'Unit'.
      ls_com-f6-textline = 'Conversion exit'.
      ls_com-f7-textline = 'Position'.
      APPEND ls_com TO lt_com.

      SORT lt_isource BY posit.

      LOOP AT lt_isource INTO ls_isource.
        CLEAR ls_com.
        ls_com-f1-textline = ls_isource-iobjnm.
        ls_com-f2-textline = ls_isource-txtlg.
        IF ls_isource-integrity = space.
          ls_com-f3-textline = cl_word=>c_symbol_checkbox.
        ELSE.
          ls_com-f3-textline = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        ls_com-f3-style_effect-font = cl_word=>c_font_symbol.
        IF ls_isource-integritymaint NE space.
          ls_com-f4-textline = ls_isource-iobjnm.
        ENDIF.
        ls_com-f5-textline = ls_isource-unifieldnm.
        ls_com-f6-textline = ls_isource-convexit.
        ls_com-f7-textline = ls_isource-posit.
        APPEND ls_com TO lt_com.
      ENDLOOP.
    ENDIF.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_com
        style   = cs_custo-table_with_head.

* Transfer rules
    LOOP AT lt_osource_list INTO ls_osource_list.
      CONCATENATE 'Transfer rule' ls_isource_detail-isource '-'
                  ls_osource_list-logsys '-' ls_osource_list-oltpsource
                  INTO lw_texte SEPARATED BY space.
      PERFORM object_progress_bar USING fw_isource c_is3
                                        lw_texte.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = lw_texte
          line_style = cs_custo-style_title2.

      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'General informations'
          line_style = cs_custo-style_title3.
      REFRESH lt_prop.

      CLEAR ls_prop.
      ls_prop-name = 'Infosource'.
      ls_prop-value = ls_isource_detail-isource.
      APPEND ls_prop TO lt_prop.

      CLEAR ls_prop.
      ls_prop-name = 'Source system'.
      ls_prop-value = ls_osource_list-logsys.
      APPEND ls_prop TO lt_prop.

      CLEAR ls_prop.
      ls_prop-name = 'Datasource'.
      ls_prop-value = ls_osource_list-oltpsource.
      APPEND ls_prop TO lt_prop.

      CLEAR ls_prop.
      ls_prop-name = 'Description'.
      CLEAR ls_osource_text.
      READ TABLE lt_osource_text INTO ls_osource_text
                 WITH KEY oltpsource = ls_osource_list-oltpsource
                          logsys = ls_osource_list-logsys.
      ls_prop-value = ls_osource_text-txtlg.
      APPEND ls_prop TO lt_prop.
      CALL METHOD o_doc->write_table
        EXPORTING
          content = lt_prop
          style   = cs_custo-table_without_head.

* Mapping transfer structure - com structure
* Do not display mapping for hierarchy
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Comm structure / Transfer rules'
          line_style = cs_custo-style_title3.

      IF ls_osource_list-istype = 'H'.
        CLEAR ls_style.
        ls_style-italic = cl_word=>c_true.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline     = 'Hierarchy'
            style_effect = ls_style.
        CLEAR ls_linestyle.
        ls_linestyle-alignment = cl_word=>c_align_center.
        CALL METHOD o_doc->write_line
          EXPORTING
            style_effect = ls_linestyle.
      ELSE.

        REFRESH lt_trsf.
        CLEAR ls_trsf.
        ls_trsf-f1 = 'InfoObject'.
        ls_trsf-f2 = 'Description'.
        ls_trsf-f3 = 'Type'.
        ls_trsf-f4 = 'Rule'.
        ls_trsf-f5 = 'Source field'.
        APPEND ls_trsf TO lt_trsf.

        CALL FUNCTION 'RSAR_INFOSOURCE_PREPARE' "TODO : poor perf, to replace
          EXPORTING
            i_isource    = ls_isource_detail-isource
            i_logsys     = ls_osource_list-logsys
            i_transtru   = ls_osource_list-transtru
            i_oltpsource = ls_osource_list-oltpsource
          IMPORTING
            e_t_rulmulti = lt_osource
            e_t_tsmulti  = lt_osource_sr
          CHANGING
            c_isostype   = lw_isostype
            c_istype     = lw_istype
            c_modus      = lw_modus.

        READ TABLE lt_osource INTO ls_osource
                   WITH KEY transtru = ls_osource_list-transtru
                            logsys = ls_osource_list-logsys
                            oltpsource = ls_osource_list-oltpsource.
        LOOP AT ls_osource-tab INTO ls_osource_tab.
          CLEAR ls_trsf.
          ls_trsf-f1 = ls_osource_tab-iobjnm.
          IF ls_osource_tab-ttxtlg IS INITIAL.
            CLEAR ls_isource.
            READ TABLE lt_isource INTO ls_isource
                       WITH KEY iobjnm = ls_osource_tab-iobjnm.
            ls_trsf-f2 = ls_isource-txtlg.
          ELSE.
            ls_trsf-f2 = ls_osource_tab-ttxtlg.
          ENDIF.
          CASE ls_osource_tab-transrultyp.
            WHEN '@6O@'.
              ls_trsf-f3 = 'InfoObject'.
            WHEN '@7L@'.
              ls_trsf-f3 = 'Constant'.
            WHEN '@9V@'.
              ls_trsf-f3 = 'Routine'.
            WHEN '@6R@'.
              ls_trsf-f3 = 'Formula'.
            WHEN ''.
              ls_trsf-f3 = 'No transfert'.
          ENDCASE.
          ls_trsf-f4 = ls_osource_tab-transrule.
          ls_trsf-f5 = ls_osource_tab-tfieldname.
          APPEND ls_trsf TO lt_trsf.
        ENDLOOP.
        CALL METHOD o_doc->write_table
          EXPORTING
            content = lt_trsf
            style   = cs_custo-table_with_head.

        READ TABLE lt_osource_sr INTO ls_osource_sr INDEX 1.
        IF ls_osource_sr-ts-startroutine NE space.
          REFRESH lt_osource_codeid.
          ls_osource_codeid = 'IEQ'.
          ls_osource_codeid-low = ls_osource_sr-ts-glbcode.
          APPEND ls_osource_codeid TO lt_osource_codeid.
          CALL FUNCTION 'RSAA_ROUTINE_MULTI_GET'
            EXPORTING
              i_objvers  = c_objvers_active
              i_t_codeid = lt_osource_codeid
            IMPORTING
              e_t_aabap  = lt_osource_abap.

          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = 'Global declaration routine'
              line_style = cs_custo-style_title3.
          REFRESH lt_code.
          LOOP AT lt_osource_abap INTO ls_osource_abap.
            APPEND ls_osource_abap-line TO lt_code.
          ENDLOOP.
          PERFORM code_display USING lt_code.
        ENDIF.

        IF ls_osource_sr-ts-startroutine NE space.
          REFRESH lt_osource_codeid.
          ls_osource_codeid = 'IEQ'.
          ls_osource_codeid-low = ls_osource_sr-ts-startroutine.
          APPEND ls_osource_codeid TO lt_osource_codeid.
          CALL FUNCTION 'RSAA_ROUTINE_MULTI_GET'
            EXPORTING
              i_objvers  = c_objvers_active
              i_t_codeid = lt_osource_codeid
            IMPORTING
              e_t_aabap  = lt_osource_abap.

          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = 'Start routine'
              line_style = cs_custo-style_title3.
          REFRESH lt_code.
          LOOP AT lt_osource_abap INTO ls_osource_abap.
            APPEND ls_osource_abap-line TO lt_code.
          ENDLOOP.
          PERFORM code_display USING lt_code.
        ENDIF.

        LOOP AT ls_osource-tab INTO ls_osource_tab
                WHERE transrultyp = '@9V@'.
          REFRESH lt_osource_codeid.
          ls_osource_codeid = 'IEQ'.
          ls_osource_codeid-low = ls_osource_tab-convrout_l.
          APPEND ls_osource_codeid TO lt_osource_codeid.
          CALL FUNCTION 'RSAA_ROUTINE_MULTI_GET'
            EXPORTING
              i_objvers  = c_objvers_active
              i_t_codeid = lt_osource_codeid
            IMPORTING
              e_t_aabap  = lt_osource_abap.

          CONCATENATE 'Routine:' ls_osource_tab-iobjnm '-' ls_osource_tab-transrule
                      INTO lw_texte SEPARATED BY space.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = lw_texte
              line_style = cs_custo-style_title3.

          REFRESH lt_code.
          LOOP AT lt_osource_abap INTO ls_osource_abap.
            APPEND ls_osource_abap-line TO lt_code.
          ENDLOOP.
          PERFORM code_display USING lt_code.
        ENDLOOP.

        LOOP AT ls_osource-tab INTO ls_osource_tab
                WHERE transrultyp = '@6R@'.
          CONCATENATE 'Formula:' ls_osource_tab-iobjnm '-' ls_osource_tab-formula_text
                      INTO lw_texte SEPARATED BY space.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = lw_texte
              line_style = cs_custo-style_title3.

          SELECT line fsym INTO TABLE lt_osource_formule
                 FROM rsfobuev001
                 WHERE formid = ls_osource_tab-formula_id
                 AND   objvers = c_objvers_active.
          SORT lt_osource_formule BY line.

          LOOP AT lt_osource_formule INTO ls_osource_formule.
            lw_texte = ls_osource_formule-fsym.
            CALL METHOD o_doc->write_text
              EXPORTING
                textline = lw_texte.
          ENDLOOP.
          CALL METHOD o_doc->write_line
            EXPORTING
              style = cs_custo-style_code.
        ENDLOOP.
      ENDIF.
* Display infopackages now
      PERFORM ip_list USING fw_isource c_is3
                            ls_osource_list-logsys
                            ls_osource_list-oltpsource.
    ENDLOOP.
  ENDIF.

  LOOP AT lt_osource_list INTO ls_osource_list.
* Add infoprovider source if recursive mode activated
    IF p_recurs NE space AND ls_isource_detail-isource(1) = '8'
    AND ls_osource_list-logsys = w_logsys.
      CLEAR ls_object.
      ls_object-object = ls_osource_list-oltpsource+1.
      SELECT SINGLE odsobject INTO ls_object-object
             FROM rsdodso
             WHERE odsobject = ls_object-object
             AND objvers = c_objvers_active.
      IF sy-subrc = 0.
        ls_object-objtype = c_dso.
      ELSE.
        SELECT SINGLE infocube INTO ls_object-object
               FROM rsdcube
               WHERE infocube = ls_object-object
               AND objvers = c_objvers_active.
        IF sy-subrc = 0.
          ls_object-objtype = c_cube.
        ELSE.
          SELECT SINGLE iobjnm INTO ls_object-object
                 FROM rsdiobj
                 WHERE iobjnm = ls_object-object
                 AND objvers = c_objvers_active.

          IF sy-subrc = 0.
            ls_object-objtype = c_iobj.
          ELSE.
            CONTINUE. "Source not identified, bypass
          ENDIF.
        ENDIF.
      ENDIF.
      PERFORM add_object_to_queue USING ls_object.

* Dislay doc for external datasource
    ELSEIF ls_osource_list-logsys NE w_logsys .
      CLEAR ls_object.
      ls_object-objtype = c_ds.
      ls_object-object = ls_osource_list-oltpsource.
      ls_object-subobject = ls_osource_list-logsys.
      PERFORM add_object_to_queue USING ls_object.
    ENDIF.
  ENDLOOP.

ENDFORM.                    "isource

*&---------------------------------------------------------------------*
*&      Form  datasource
*&---------------------------------------------------------------------*
*       Display documentation for a datasource
*----------------------------------------------------------------------*
*      -->FW_LOGSYS      RFC destination of the datasource
*      -->FW_OLTPSOURCE  Datasource
*----------------------------------------------------------------------*
FORM datasource USING fw_logsys TYPE string
                      fw_oltpsource TYPE string.

  DATA : lw_error_message(80) TYPE c.
  DATA : lt_where     TYPE TABLE OF rfc_db_opt,
         lt_fields    TYPE TABLE OF rfc_db_fld,
         lt_roosource TYPE TABLE OF tab512,
         BEGIN OF ls_roosource,
           exmethod  TYPE roosource-exmethod,
           extractor TYPE roosource-extractor,
         END OF ls_roosource,
         lt_roosfield TYPE TABLE OF tab512,
         BEGIN OF ls_roosfield,
           field     TYPE roosfield-field,
           selection TYPE roosfield-selection,
           storno    TYPE roosfield-storno,
           notexrel  TYPE roosfield-notexrel,
         END OF ls_roosfield,
         lt_exit      TYPE TABLE OF tab512,
         lt_exit_code TYPE TABLE OF abaptxt255,
         ls_code      LIKE LINE OF lt_exit_code,
         lt_code      TYPE ty_code_table,
         lw_header(1) TYPE c,
         lw_texte     TYPE string.
  DATA : BEGIN OF ls_champ,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
           f5 TYPE cl_word=>ty_table_style_field,
           f6 TYPE cl_word=>ty_table_style_field,
         END OF ls_champ,
         lt_champ LIKE TABLE OF ls_champ,
         BEGIN OF ls_prop,
           name(80)  TYPE c,
           VALUE(80) TYPE c,
         END OF ls_prop,
         lt_prop LIKE TABLE OF ls_prop,
         BEGIN OF ls_prop2,
           name  TYPE cl_word=>ty_table_style_field,
           value TYPE cl_word=>ty_table_style_field,
         END OF ls_prop2,
         lt_prop2      LIKE TABLE OF ls_prop2,
         lw_oltpsource TYPE roosource-oltpsource,
         lw_logsys     TYPE rsslogsys,
         lw_style      TYPE cl_word=>ty_character_style_effect.
  DATA : ls_ds           TYPE rsds,
         lt_dst          TYPE rsds_t_rsdst,
         ls_dst          LIKE LINE OF lt_dst,
         lt_dsfields     TYPE rsds_t_rsdssegfd,
         ls_dsfields     LIKE LINE OF lt_dsfields,
         lt_dsfieldtxt   TYPE rsds_t_rsdssegfdt,
         ls_dsfieldtxt   LIKE LINE OF lt_dsfieldtxt,
         lt_dsaccessattr TYPE rsds_t_accessattr,
         ls_dsaccessattr LIKE LINE OF lt_dsaccessattr,
         lw_domval       TYPE val_text,
         lo_attributes   TYPE REF TO object,
         lo_db           TYPE REF TO cl_rsds_store_db_attributes,
         lo_file         TYPE REF TO cl_rsds_store_file_attributes,
         lo_csv          TYPE REF TO cl_rsds_store_csv_attributes,
         lw_schema       TYPE rsds_dbc_objschema,
         lw_objname      TYPE rsds_dbc_objname, "or dbobject_d , depend of the bw system
         lw_filename     TYPE  rsfilenm,
         lw_lines        TYPE rsignorelines,
         lw_sep          TYPE rssep,
         lw_esc          TYPE rsesc,
         lw_ds3          TYPE rsds_old_ds.

  IF w_skip NE space.
    RETURN.
  ENDIF.
  PERFORM object_progress_bar USING fw_oltpsource c_ds
                                    'Writing Datasource info...'(m08).
  lw_oltpsource = fw_oltpsource.
  lw_logsys = fw_logsys.

* Get all datasource info
  CALL FUNCTION 'RSDS_DATASOURCE_SINGLE_GET'
    EXPORTING
      i_datasource     = lw_oltpsource
      i_logsys         = lw_logsys
    IMPORTING
      e_s_ds           = ls_ds
      e_t_dst          = lt_dst
      e_t_dssegfd      = lt_dsfields
      e_t_dssegfdt     = lt_dsfieldtxt
      e_t_dsaccessattr = lt_dsaccessattr
      e_old_ds         = lw_ds3
    EXCEPTIONS
      OTHERS           = 3.
  IF sy-subrc <> 0.
    RETURN. "Datasource not readable, skip
  ENDIF.

* For sap system, get info directly from source
  IF ls_ds-contsrctype = 'R/3'. "ECC, APO, BW
* Check RFC destination
    CALL FUNCTION 'RFC_PING'
      DESTINATION fw_logsys
      EXCEPTIONS
        system_failure        = 1 MESSAGE lw_error_message
        communication_failure = 2 MESSAGE lw_error_message
        OTHERS                = 3.
    IF sy-subrc NE 0.
      MESSAGE lw_error_message TYPE c_msg_success DISPLAY LIKE c_msg_error.
    ELSE.
* Get basic datasource data from ROOSOURCE
      REFRESH lt_fields.
      APPEND 'EXMETHOD' TO lt_fields.
      APPEND 'EXTRACTOR' TO lt_fields.
      REFRESH lt_where.
      APPEND 'OBJVERS = ''A'' and OLTPSOURCE = ' TO lt_where.
      CONCATENATE '''' fw_oltpsource '''' INTO lw_error_message.
      APPEND lw_error_message TO lt_where.
      CALL FUNCTION 'RFC_READ_TABLE' DESTINATION fw_logsys
        EXPORTING
          query_table          = 'ROOSOURCE'
        TABLES
          options              = lt_where
          fields               = lt_fields
          data                 = lt_roosource
        EXCEPTIONS
          table_not_available  = 1
          table_without_data   = 2
          option_not_valid     = 3
          field_not_valid      = 4
          not_authorized       = 5
          data_buffer_exceeded = 6
          OTHERS               = 7.
      IF sy-subrc NE 0.
        REFRESH lt_roosource.
      ELSE.
        READ TABLE lt_roosource INTO ls_roosource INDEX 1.
      ENDIF.

* Get fields attributes from ROOSFIELD
      REFRESH lt_fields.
      APPEND 'FIELD' TO lt_fields.
      APPEND 'SELECTION' TO lt_fields.
      APPEND 'STORNO' TO lt_fields.
      APPEND 'NOTEXREL' TO lt_fields.
      REFRESH lt_where.
      APPEND 'OBJVERS = ''A'' and OLTPSOURCE = ' TO lt_where.
      CONCATENATE '''' fw_oltpsource '''' INTO lw_error_message.
      APPEND lw_error_message TO lt_where.
      CALL FUNCTION 'RFC_READ_TABLE' DESTINATION fw_logsys
        EXPORTING
          query_table          = 'ROOSFIELD'
        TABLES
          options              = lt_where
          fields               = lt_fields
          data                 = lt_roosfield
        EXCEPTIONS
          table_not_available  = 1
          table_without_data   = 2
          option_not_valid     = 3
          field_not_valid      = 4
          not_authorized       = 5
          data_buffer_exceeded = 6
          OTHERS               = 7.
      IF sy-subrc NE 0.
        REFRESH lt_roosfield.
      ELSE.
        SORT lt_fields.
      ENDIF.

* Search if user exit used
      IF NOT cs_custo-r3_exit_tpl IS INITIAL.
        REFRESH lt_fields.
        APPEND 'NAME' TO lt_fields.
        REFRESH lt_where.
        lw_error_message = cs_custo-r3_exit_tpl.
        REPLACE '<ds>' WITH fw_oltpsource INTO lw_error_message.
        CONCATENATE 'NAME = ''' lw_error_message ''''
                    INTO lw_error_message.
        APPEND lw_error_message TO lt_where.
        CALL FUNCTION 'RFC_READ_TABLE' DESTINATION fw_logsys
          EXPORTING
            query_table          = 'TRDIR'
          TABLES
            options              = lt_where
            fields               = lt_fields
            data                 = lt_exit
          EXCEPTIONS
            table_not_available  = 1
            table_without_data   = 2
            option_not_valid     = 3
            field_not_valid      = 4
            not_authorized       = 5
            data_buffer_exceeded = 6
            OTHERS               = 7.
        IF sy-subrc NE 0.
          REFRESH lt_exit.
        ELSE.
* Read user-exit code
          lw_error_message = cs_custo-r3_exit_tpl.
          REPLACE '<ds>' WITH fw_oltpsource INTO lw_error_message.
          CALL FUNCTION 'RPY_PROGRAM_READ'
            DESTINATION fw_logsys
            EXPORTING
              program_name    = lw_error_message
              only_source     = abap_true
            TABLES
              source_extended = lt_exit_code
            EXCEPTIONS
              OTHERS          = 8.
          IF sy-subrc NE 0.
            REFRESH lt_exit_code.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDIF.

  IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
    CALL METHOD o_doc->write_newpage.
  ENDIF.

* Datasource title
  CONCATENATE 'Datasource' fw_oltpsource '(' fw_logsys ')'
  INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Insert embbeded documents
  PERFORM special_note USING c_ds fw_oltpsource
                             cs_custo-style_title2.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title2.

  REFRESH lt_prop2.
* Datasource description
  CLEAR ls_prop2.
  ls_prop2-name-textline = 'Source system'.
  ls_prop2-value-textline = fw_logsys.
  APPEND ls_prop2 TO lt_prop2.

  CLEAR ls_prop2.
  ls_prop2-name-textline = 'Applicative component'.
  ls_prop2-value-textline = ls_ds-applnm.
  APPEND ls_prop2 TO lt_prop2.

* Datasource type
  IF NOT ls_ds-type IS INITIAL.
    CLEAR ls_prop2.
    ls_prop2-name-textline = 'Datasource type'.
    PERFORM get_domain_value USING 'RSDS_REQUTYPE' ls_ds-type
                             CHANGING lw_domval.
    ls_prop2-value-textline = lw_domval.
    APPEND ls_prop2 TO lt_prop2.
  ENDIF.

  CLEAR ls_prop2.
  ls_prop2-name-textline = 'User-Exit'.
  IF lt_exit IS INITIAL.
    ls_prop2-value-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_prop2-value-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_prop2-value-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_prop2 TO lt_prop2.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_prop2
      style   = cs_custo-table_without_head.

* Datasource texts
  IF NOT lt_dst IS INITIAL.
    READ TABLE lt_dst INTO ls_dst INDEX 1.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Texts'
        line_style = cs_custo-style_title2.
    REFRESH lt_prop.
    CLEAR ls_prop.
    ls_prop-name = 'Short description'.
    ls_prop-value = ls_dst-txtsh.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name = 'Medium description'.
    ls_prop-value = ls_dst-txtmd.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name = 'Long description'.
    ls_prop-value = ls_dst-txtlg.
    APPEND ls_prop TO lt_prop.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_without_head.
  ENDIF.

* Extractor informations
  IF ls_roosource-exmethod NE space OR ls_ds-exstructure NE space
  OR NOT lt_dsaccessattr IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Extractor'
        line_style = cs_custo-style_title2.
    REFRESH lt_prop.
    CASE ls_roosource-exmethod.
      WHEN 'V'.
        CLEAR ls_prop.
        ls_prop-name = 'Method'.
        ls_prop-value = 'Extraction from DB View'.
        APPEND ls_prop TO lt_prop.

        CLEAR ls_prop.
        ls_prop-name = 'View/Table'.
        ls_prop-value = ls_roosource-extractor.
        APPEND ls_prop TO lt_prop.

        CLEAR ls_prop.
        ls_prop-name = 'Extraction structure'.
        ls_prop-value = ls_ds-exstructure.
        APPEND ls_prop TO lt_prop.
      WHEN 'Q'.
        CLEAR ls_prop.
        ls_prop-name = 'Method'.
        ls_prop-value = 'Extraction from SAP Query'.
        APPEND ls_prop TO lt_prop.

        CLEAR ls_prop.
        ls_prop-name = 'Infoset'.
        ls_prop-value = ls_roosource-extractor.
        APPEND ls_prop TO lt_prop.

      WHEN 'F2' OR 'F1'.
        CLEAR ls_prop.
        ls_prop-name = 'Method'.
        ls_prop-value = 'Extraction by Function Module'.
        APPEND ls_prop TO lt_prop.

        CLEAR ls_prop.
        ls_prop-name = 'Function Module'.
        ls_prop-value = ls_roosource-extractor.
        APPEND ls_prop TO lt_prop.

        CLEAR ls_prop.
        ls_prop-name = 'Extraction structure'.
        ls_prop-value = ls_ds-exstructure.
        APPEND ls_prop TO lt_prop.

      WHEN OTHERS. "external datasource
        IF NOT lt_dsaccessattr IS INITIAL.
* DB Connect
          READ TABLE lt_dsaccessattr INTO ls_dsaccessattr
                     WITH KEY accessmethod = 'DBEXTRACT'.
          IF sy-subrc = 0.
            CALL TRANSFORMATION id SOURCE XML ls_dsaccessattr-xml
                                   RESULT attrib = lo_attributes.
            lo_db ?= lo_attributes.
            CALL METHOD lo_db->get_objschema
              EXPORTING
                i_segid     = '0001'
              IMPORTING
                e_objschema = lw_schema.
            CALL METHOD lo_db->get_objname
              EXPORTING
                i_segid   = '0001'
              IMPORTING
                e_objname = lw_objname.

            CLEAR ls_prop.
            ls_prop-name = 'Method'.
            ls_prop-value = 'Extraction via DB connect'.
            APPEND ls_prop TO lt_prop.

            CLEAR ls_prop.
            ls_prop-name = 'Schema/table'.
            CONCATENATE lw_schema '/' lw_objname
                        INTO ls_prop-value SEPARATED BY space.
            APPEND ls_prop TO lt_prop.
          ENDIF.

* Flat file
          LOOP AT lt_dsaccessattr INTO ls_dsaccessattr
                  WHERE accessmethod = 'OPEN_DS'
                  OR accessmethod = 'GUI_UPLOAD'
                  OR accessmethod = 'BIN_OPE_EX'
                  OR accessmethod = 'BIN_GUI_EX'.
            CALL TRANSFORMATION id SOURCE XML ls_dsaccessattr-xml
                                   RESULT attrib = lo_attributes.
            lo_file ?= lo_attributes.
            CALL METHOD lo_file->get_filename
              IMPORTING
                e_value = lw_filename.
            IF NOT lw_filename IS INITIAL.
              EXIT. "exit loop
            ENDIF.
          ENDLOOP.
          IF sy-subrc = 0.
            CLEAR ls_prop.
            ls_prop-name = 'Method'.
            ls_prop-value = 'Extraction via Flat file'.
            APPEND ls_prop TO lt_prop.

            CLEAR ls_prop.
            ls_prop-name = 'File'.
            ls_prop-value = lw_filename.
            APPEND ls_prop TO lt_prop.


            CALL METHOD lo_file->get_ignorelines
              IMPORTING
                e_value = lw_lines.

            CLEAR ls_prop.
            ls_prop-name = 'Header rows to be ignored'.
            ls_prop-value = lw_lines.
            CONDENSE ls_prop-value.
            APPEND ls_prop TO lt_prop.

            LOOP AT lt_dsaccessattr INTO ls_dsaccessattr
                    WHERE accessmethod = 'ASCIICONV'
                    OR accessmethod = 'CSVFLCONV'.
              CALL TRANSFORMATION id SOURCE XML ls_dsaccessattr-xml
                                     RESULT attrib = lo_attributes.
              lo_csv ?= lo_attributes.
              CALL METHOD lo_csv->get_filesep
                IMPORTING
                  e_value = lw_sep.
              IF NOT lw_sep IS INITIAL.
                EXIT. "exit loop
              ENDIF.
            ENDLOOP.
            IF sy-subrc = 0 AND NOT lw_sep IS INITIAL.
              lw_texte = cl_abap_conv_in_ce=>uccp( lw_sep ).
              IF lw_texte IS INITIAL.
                lw_texte = lw_sep.
                CONCATENATE '(x' lw_texte ')' INTO lw_texte.
              ENDIF.
              CLEAR ls_prop.
              ls_prop-name = 'Data Separator'.
              ls_prop-value = lw_texte.
              APPEND ls_prop TO lt_prop.

              CALL METHOD lo_csv->get_esc
                IMPORTING
                  e_value = lw_esc.
              lw_texte = cl_abap_conv_in_ce=>uccp( lw_esc ).
              IF lw_texte IS INITIAL.
                lw_texte = lw_esc.
                CONCATENATE '(x' lw_texte ')' INTO lw_texte.
              ENDIF.
              CLEAR ls_prop.
              ls_prop-name = 'Escape Sign'.
              ls_prop-value = lw_texte.
              APPEND ls_prop TO lt_prop.
            ENDIF.
          ENDIF.
        ENDIF.
        IF NOT ls_ds-exstructure IS INITIAL.
          CLEAR ls_prop.
          ls_prop-name = 'Extraction structure'.
          ls_prop-value = ls_ds-exstructure.
          APPEND ls_prop TO lt_prop.
        ENDIF.
    ENDCASE.
    IF NOT lt_prop IS INITIAL.
      CALL METHOD o_doc->write_table
        EXPORTING
          content = lt_prop
          style   = cs_custo-table_without_head.
    ENDIF.
  ENDIF.

* Extractor fields
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Extractor fields'
      line_style = cs_custo-style_title2.

  IF NOT lt_roosfield IS INITIAL. "SAP datasource
    REFRESH lt_champ.
    CLEAR ls_champ.
    ls_champ-f1-textline = 'Field name'.
    ls_champ-f2-textline = 'Short text'.
    ls_champ-f3-textline = 'Selection'.
    ls_champ-f4-textline = 'Hide field'.
    ls_champ-f5-textline = 'Inversion'.
    ls_champ-f6-textline = 'Field only known in Customer Exit'.
    APPEND ls_champ TO lt_champ.

    LOOP AT lt_roosfield INTO ls_roosfield.
      CLEAR ls_champ.
      ls_champ-f1-textline = ls_roosfield-field.
      READ TABLE lt_dsfieldtxt INTO ls_dsfieldtxt WITH KEY fieldnm = ls_roosfield-field.
      IF sy-subrc = 0.
        ls_champ-f2-textline = ls_dsfieldtxt-txtlg.
      ENDIF.

      IF ls_roosfield-selection = '1' OR ls_roosfield-selection = 'X' OR ls_roosfield-selection = 'M'.
        ls_champ-f3-textline = cl_word=>c_symbol_checkbox_checked.
      ELSE.
        ls_champ-f3-textline = cl_word=>c_symbol_checkbox.
      ENDIF.
      ls_champ-f3-style_effect-font = cl_word=>c_font_symbol.

      IF ls_roosfield-selection = '3' OR ls_roosfield-selection = '4'.
        ls_champ-f4-textline = cl_word=>c_symbol_checkbox_checked.
      ELSE.
        ls_champ-f4-textline = cl_word=>c_symbol_checkbox.
      ENDIF.
      ls_champ-f4-style_effect-font = cl_word=>c_font_symbol.

      IF ls_roosfield-storno = 'X'.
        ls_champ-f5-textline = cl_word=>c_symbol_checkbox_checked.
      ELSE.
        ls_champ-f5-textline = cl_word=>c_symbol_checkbox.
      ENDIF.
      ls_champ-f5-style_effect-font = cl_word=>c_font_symbol.

      IF ls_roosfield-notexrel = 'N'.
        ls_champ-f6-textline = cl_word=>c_symbol_checkbox_checked.
      ELSE.
        ls_champ-f6-textline = cl_word=>c_symbol_checkbox.
      ENDIF.
      ls_champ-f6-style_effect-font = cl_word=>c_font_symbol.
      APPEND ls_champ TO lt_champ.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_champ
        style   = cs_custo-table_with_head.
  ELSE.
    REFRESH lt_champ.
    CLEAR ls_champ.
    ls_champ-f1-textline = 'Field name'.
    ls_champ-f2-textline = 'Short text'.
    ls_champ-f3-textline = 'Selection'.
    ls_champ-f4-textline = 'Data element'.
    ls_champ-f5-textline = 'Data type'.
    ls_champ-f6-textline = 'Length'.
    APPEND ls_champ TO lt_champ.
    LOOP AT lt_dsfields INTO ls_dsfields.
      CLEAR ls_champ.
      ls_champ-f1-textline = ls_dsfields-fieldnm.
      READ TABLE lt_dsfieldtxt INTO ls_dsfieldtxt WITH KEY fieldnm = ls_dsfields-fieldnm.
      IF sy-subrc = 0.
        ls_champ-f2-textline = ls_dsfieldtxt-txtlg.
      ENDIF.
      IF ls_dsfields-selection = '1' OR ls_dsfields-selection = 'X' OR ls_dsfields-selection = 'M'.
        ls_champ-f3-textline = cl_word=>c_symbol_checkbox_checked.
      ELSE.
        ls_champ-f3-textline = cl_word=>c_symbol_checkbox.
      ENDIF.
      ls_champ-f3-style_effect-font = cl_word=>c_font_symbol.
      ls_champ-f4-textline = ls_dsfields-dtelnm.
      ls_champ-f5-textline = ls_dsfields-datatype.
      ls_champ-f6-textline = ls_dsfields-leng.
      APPEND ls_champ TO lt_champ.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_champ
        style   = cs_custo-table_with_head.
  ENDIF.

* User-exit code
  IF NOT lt_exit IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'User-Exit'
        line_style = cs_custo-style_title2.
    IF lt_exit_code IS INITIAL.
      CLEAR lw_style.
      lw_style-italic = cl_word=>c_true.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline     = 'Cannot read code of user exit'
          style_effect = lw_style
          line_style   = cl_word=>c_style_normal.
    ELSE.
      REFRESH lt_code.
      lw_header = abap_true.
      LOOP AT lt_exit_code INTO ls_code.
* Remove header comments
        IF lw_header = abap_true AND
        ( ls_code(1) = '*' OR ls_code IS INITIAL ).
          CONTINUE.
        ELSE.
          lw_header = space.
        ENDIF.
        APPEND ls_code TO lt_code.
      ENDLOOP.
      PERFORM code_display USING lt_code.
    ENDIF.
  ENDIF.

* Display infopackage for 7x datasource
* (ip for 3x is displayed in infosource section)
  IF lw_ds3 = space.
    PERFORM ip_list USING fw_oltpsource c_ds fw_logsys fw_oltpsource.
  ENDIF.

ENDFORM.                    " datasource

*&---------------------------------------------------------------------*
*&      Form  iobj
*&---------------------------------------------------------------------*
*       Display documentation for an InfoObject
*----------------------------------------------------------------------*
*      -->FW_IOBJ    InfoObject
*----------------------------------------------------------------------*
FORM iobj USING fw_iobj TYPE string.
  DATA : ls_iobj_detail     TYPE rsd_s_viobj,
         lw_iobj_dtelnm     TYPE rollname,
         lw_iobj_sidtab     TYPE rssidtab,
         lw_iobj_txttab     TYPE rstxttab,
         lw_iobj_chktab     TYPE rsdchkview,
         lw_iobj_chntab     TYPE rschntab,
         lw_iobj_chttab     TYPE rschttab,
         lw_iobj_asitab     TYPE rsasitab,
         lw_iobj_asttab     TYPE rsasttab,
         lw_iobj_hietab     TYPE rshietab,
         lw_iobj_hintab     TYPE rshintab,
         lw_iobj_hsitab     TYPE rshsitab,
         lw_iobj_inctab     TYPE rsinctab,

         lt_iobj_compound   TYPE rsd_t_iobj_cmp,
         ls_iobj_compound   LIKE LINE OF lt_iobj_compound,
         lt_iobj_attributes TYPE rsd_t_atr,
         ls_iobj_attributes LIKE LINE OF lt_iobj_attributes,
         lt_iobj_atr_nav    TYPE rsd_t_atr_nav,
         ls_iobj_atr_nav    LIKE LINE OF lt_iobj_atr_nav,

         BEGIN OF ls_iobj_comp_atr,
           chanm    TYPE rschanm,
           chabasnm TYPE rschabasnm,
           chaconst TYPE rschaconst,
         END OF ls_iobj_comp_atr,
         lt_iobj_comp_atr LIKE TABLE OF ls_iobj_comp_atr,
         BEGIN OF ls_iobj_atr_txt,
           iobjnm TYPE rsdiobjt-iobjnm,
           txtlg  TYPE rsdiobjt-txtlg,
         END OF ls_iobj_atr_txt,
         lt_iobj_atr_txt LIKE TABLE OF ls_iobj_atr_txt,
         lw_texte        TYPE string,
         BEGIN OF ls_data,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_attr,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
           f5 TYPE cl_word=>ty_table_style_field,
           f6 TYPE cl_word=>ty_table_style_field,
           f7 TYPE cl_word=>ty_table_style_field,
           f8 TYPE cl_word=>ty_table_style_field,
           f9 TYPE cl_word=>ty_table_style_field,
         END OF ls_attr,
         lt_attr LIKE TABLE OF ls_attr,
         BEGIN OF ls_comp,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
         END OF ls_comp,
         lt_comp     LIKE TABLE OF ls_comp,
         ls_scr_iobj TYPE rsdgsciobj,
         lw_domtext  TYPE val_text.

  FIELD-SYMBOLS <fs> TYPE any.

  ls_iobj_detail-iobjnm = fw_iobj.
  PERFORM object_progress_bar USING fw_iobj c_iobj
                                    'Writing InfoObject info...'.

  CALL FUNCTION 'RSD_IOBJ_GET'
    EXPORTING
      i_iobjnm       = ls_iobj_detail-iobjnm
    IMPORTING
      e_s_viobj      = ls_iobj_detail
      e_t_iobj_cmp   = lt_iobj_compound
      e_t_atr        = lt_iobj_attributes
      e_t_atr_nav    = lt_iobj_atr_nav
    EXCEPTIONS
      iobj_not_found = 1.
  IF sy-subrc NE 0.
    RETURN.
  ENDIF.

  SORT lt_iobj_atr_nav BY attrinm.

  IF NOT lt_iobj_attributes IS INITIAL.
    SELECT iobjnm txtlg INTO TABLE lt_iobj_atr_txt
           FROM rsdiobjt
           FOR ALL ENTRIES IN lt_iobj_attributes
           WHERE langu = c_lang_default
           AND   iobjnm = lt_iobj_attributes-attrinm
           AND   objvers = c_objvers_active.
    SORT lt_iobj_atr_txt BY iobjnm.
  ENDIF.
  IF NOT ls_iobj_detail-chabasnm IS INITIAL.
    SELECT iobjnm txtlg APPENDING TABLE lt_iobj_atr_txt
           FROM rsdiobjt
           WHERE langu = c_lang_default
           AND   iobjnm = ls_iobj_detail-chabasnm
           AND   objvers = c_objvers_active.
    SORT lt_iobj_atr_txt BY iobjnm.
  ENDIF.
  IF NOT lt_iobj_compound IS INITIAL.
    SELECT iobjnm txtlg APPENDING TABLE lt_iobj_atr_txt
           FROM rsdiobjt
           FOR ALL ENTRIES IN lt_iobj_compound
           WHERE langu = c_lang_default
           AND   iobjnm = lt_iobj_compound-iobjcmp
           AND   objvers = c_objvers_active.
    SORT lt_iobj_atr_txt BY iobjnm.

    SELECT chanm chabasnm chaconst
           INTO TABLE lt_iobj_comp_atr
           FROM rsdcha
           FOR ALL ENTRIES IN lt_iobj_compound
           WHERE chanm = lt_iobj_compound-iobjcmp
           AND   objvers = c_objvers_active.
    SORT lt_iobj_comp_atr BY chanm.
  ENDIF.

* element de donnée
  CALL FUNCTION 'RSD_DTELNM_GET_FOR_IOBJ'
    EXPORTING
      i_iobjnm = ls_iobj_detail-iobjnm
    IMPORTING
      e_dtelnm = lw_iobj_dtelnm.

* table SID
  CALL FUNCTION 'RSD_SIDTAB_GET_FOR_CHA_BAS'
    EXPORTING
      i_chabasnm = ls_iobj_detail-iobjnm
    IMPORTING
      e_sidtab   = lw_iobj_sidtab
    EXCEPTIONS
      name_error = 1.

* Table de texte
  CALL FUNCTION 'RSD_TXTTAB_GET_FOR_CHA_BAS'
    EXPORTING
      i_chabasnm = ls_iobj_detail-iobjnm
    IMPORTING
      e_txttab   = lw_iobj_txttab
    EXCEPTIONS
      name_error = 1.

* Tables de données
  CALL FUNCTION 'RSD_CHKTAB_GET_FOR_CHA_BAS'
    EXPORTING
      i_chabasnm = ls_iobj_detail-iobjnm
      i_s_viobj  = ls_iobj_detail
      i_t_atr    = lt_iobj_attributes
    IMPORTING
      e_chktab   = lw_iobj_chktab
      e_chntab   = lw_iobj_chntab
      e_chttab   = lw_iobj_chttab
      e_asitab   = lw_iobj_asitab
      e_asttab   = lw_iobj_asttab
    EXCEPTIONS
      name_error = 1.

* Table de hierarchie
  CALL FUNCTION 'RSD_HIETAB_GET_FOR_CHA_BAS'
    EXPORTING
      i_chabasnm = ls_iobj_detail-iobjnm
      i_s_viobj  = ls_iobj_detail
    IMPORTING
      e_hietab   = lw_iobj_hietab
      e_hintab   = lw_iobj_hintab
      e_inctab   = lw_iobj_inctab
      e_hsitab   = lw_iobj_hsitab
    EXCEPTIONS
      name_error = 1.

  IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
    CALL METHOD o_doc->write_newpage.
  ENDIF.

* InfoObject title
  CONCATENATE 'InfoObject' ls_iobj_detail-iobjnm INTO lw_texte
              SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Reference
  IF NOT ls_iobj_detail-chabasnm IS INITIAL.
    CLEAR ls_iobj_atr_txt.
    READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
               WITH KEY iobjnm = ls_iobj_detail-chabasnm
               BINARY SEARCH.
    CONCATENATE 'Reference InfoObject:' ls_iobj_detail-chabasnm
                '-' ls_iobj_atr_txt-txtlg
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.
  ENDIF.

* Infoobject type
  PERFORM get_domain_value USING 'RSIOBJTP' ls_iobj_detail-iobjtp
                           CHANGING lw_domtext.
  CONCATENATE 'InfoObject type:' lw_domtext INTO lw_texte
              SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.

* InfoObject description
  CONCATENATE 'Long description:' ls_iobj_detail-txtlg INTO lw_texte
              SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.

  CONCATENATE 'Short description:' ls_iobj_detail-txtsh INTO lw_texte
              SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.

* Insert embbeded documents
  PERFORM special_note USING c_iobj fw_iobj
                             cs_custo-style_title2.

* General settings
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General settings'
      line_style = cs_custo-style_title2.

* Dictionary bloc
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Dictionary'
      line_style = cs_custo-style_title3.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Data element'.
  ls_data-f2-textline = lw_iobj_dtelnm.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Data type'.
  ls_data-f2-textline = ls_iobj_detail-datatp.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Length'.
  ls_data-f2-textline = ls_iobj_detail-intlen.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Lowercase letters'.
  IF ls_iobj_detail-lowercase = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Conversion routine'.
  ls_data-f2-textline = ls_iobj_detail-convexit.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Output length'.
  ls_data-f2-textline = ls_iobj_detail-outputlen.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'SID table'.
  ls_data-f2-textline = lw_iobj_sidtab.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

* Currency / UOM for key figure
  IF ls_iobj_detail-iobjtp = 'KYF'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Currency/Unit of Measure'
        line_style = cs_custo-style_title3.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Fixed currency'.
    ls_data-f2-textline = ls_iobj_detail-fixcuky.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Fixed UOM'.
    ls_data-f2-textline = ls_iobj_detail-fixunit.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Unit/currency'.
    ls_data-f2-textline = ls_iobj_detail-uninm.
    APPEND ls_data TO lt_data.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Bex (units)
  IF ls_iobj_detail-iobjtp = 'UNI'.
* Convert RSCHAPRSNT to readable values
    CALL METHOD cl_rsd_utilities=>convert_to_prsnt_txtki
      EXPORTING
        i_chaprsnt = ls_iobj_detail-chaprsnt
      IMPORTING
        e_prsnt    = ls_scr_iobj-chaprski
        e_txtki    = ls_scr_iobj-chatxtki.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Business Explorer'
        line_style = cs_custo-style_title3.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Display'.
    PERFORM get_domain_value USING 'RSPRSNT' ls_scr_iobj-chaprski
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Text type'.
    PERFORM get_domain_value USING 'RSTXTKI' ls_scr_iobj-chatxtki
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'BEx description'.
    PERFORM get_domain_value USING 'RSTXTDEF' ls_iobj_detail-txtdef
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Other bloc
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Other'
      line_style = cs_custo-style_title3.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Attribute Only'.
  IF ls_iobj_detail-atronlyfl = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Person Responsible'.
  ls_data-f2-textline = ls_iobj_detail-owner.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Content release'.
  ls_data-f2-textline = ls_iobj_detail-contrel.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Characteristic is document property'.
  IF ls_iobj_detail-bdsfl = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Constant'.
  ls_data-f2-textline = ls_iobj_detail-chaconst.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Transfer routine exists'.
  IF ls_iobj_detail-iobjrout = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

* Bex
  IF ls_iobj_detail-iobjtp = 'CHA' OR ls_iobj_detail-iobjtp = 'TIM'
  OR ls_iobj_detail-iobjtp = 'DPA'.
* Convert RSCHAPRSNT to readable values
    CALL METHOD cl_rsd_utilities=>convert_to_prsnt_txtki
      EXPORTING
        i_chaprsnt = ls_iobj_detail-chaprsnt
      IMPORTING
        e_prsnt    = ls_scr_iobj-chaprski
        e_txtki    = ls_scr_iobj-chatxtki.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Business Explorer'
        line_style = cs_custo-style_title2.

* General settings bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'General settings'
        line_style = cs_custo-style_title3.
    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Display'.
    PERFORM get_domain_value USING 'RSPRSNT' ls_scr_iobj-chaprski
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Text type'.
    PERFORM get_domain_value USING 'RSTXTKI' ls_scr_iobj-chatxtki
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'BEx description'.
    PERFORM get_domain_value USING 'RSTXTDEF' ls_iobj_detail-txtdef
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Selection'.
    PERFORM get_domain_value USING 'RSCHASEL' ls_iobj_detail-chasel
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Query Def. Filter Value Selection'.
    PERFORM get_domain_value USING 'RSF4DEFAULT' ls_iobj_detail-f4default
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Query Execution Filter Value Selection'.
    PERFORM get_domain_value USING 'RSF4QUERYEXEC' ls_iobj_detail-f4queryexec
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Filter Value Repr. at Query Execution'.
    PERFORM get_domain_value USING 'RSF4PRSNT' ls_iobj_detail-f4prsnt
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Base Unit of Measure'.
    ls_data-f2-textline = ls_iobj_detail-uomconv.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Unit of Measure for Char.'.
    ls_data-f2-textline = ls_iobj_detail-uomconvods.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Currency attribute'.
    ls_data-f2-textline = ls_iobj_detail-uninm.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Authorization Relevant'.
    IF ls_iobj_detail-authrelfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Authorization Field'.
    ls_data-f2-textline = ls_iobj_detail-authfield.
    APPEND ls_data TO lt_data.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.

* Bex Map bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'BEx Map'
        line_style = cs_custo-style_title3.
    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Geographical type'.
    PERFORM get_domain_value USING 'RSGISTP' ls_iobj_detail-gistp
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Geographical attribute'.
    ls_data-f2-textline = ls_iobj_detail-gisattrinm.
    APPEND ls_data TO lt_data.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Aggregation
  IF ls_iobj_detail-iobjtp = 'KYF'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Aggregation'
        line_style = cs_custo-style_title2.

* Aggregation bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Aggregation'
        line_style = cs_custo-style_title3.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Aggregation'.
    PERFORM get_domain_value USING 'RSDAGGRGEN' ls_iobj_detail-aggrgen
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Exception Aggregation'.
    PERFORM get_domain_value USING 'RSDAGGREXC' ls_iobj_detail-aggrexc
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Reference Characteristic for Exception Aggregation'.
    ls_data-f2-textline = ls_iobj_detail-aggrcha.
    APPEND ls_data TO lt_data.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.

* Cumulative value bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Cumulative/Non-Cumulative Values'
        line_style = cs_custo-style_title3.
    REFRESH lt_data.

    IF ls_iobj_detail-ncumfl = space.
      CLEAR ls_data.
      ls_data-f1-textline = 'Cumulative Value'.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
      ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
      APPEND ls_data TO lt_data.

    ELSEIF ls_iobj_detail-ncumfl = 1.
      CLEAR ls_data.
      ls_data-f1-textline = 'Non-Cumulative Value with Non-Cumulative Value Change'.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
      ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
      APPEND ls_data TO lt_data.
      CLEAR ls_iobj_compound.
      READ TABLE lt_iobj_compound INTO ls_iobj_compound WITH KEY cmptp = 1.
      CLEAR ls_data.
      ls_data-f1-textline = 'Non-Cum. Value Change'.
      ls_data-f2-textline = ls_iobj_compound-iobjcmp.
      APPEND ls_data TO lt_data.

    ELSEIF ls_iobj_detail-ncumfl = 2.
      CLEAR ls_data.
      ls_data-f1-textline = 'Non-Cumulative Value with Inflow/Outflow'.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
      ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
      APPEND ls_data TO lt_data.
      CLEAR ls_iobj_compound.
      READ TABLE lt_iobj_compound INTO ls_iobj_compound WITH KEY cmptp = 1.
      CLEAR ls_data.
      ls_data-f1-textline = 'Inflow'.
      ls_data-f2-textline = ls_iobj_compound-iobjcmp.
      APPEND ls_data TO lt_data.
      CLEAR ls_iobj_compound.
      READ TABLE lt_iobj_compound INTO ls_iobj_compound WITH KEY cmptp = 2.
      CLEAR ls_data.
      ls_data-f1-textline = 'Outflow'.
      ls_data-f2-textline = ls_iobj_compound-iobjcmp.
      APPEND ls_data TO lt_data.
    ENDIF.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Additionnal properties (Key figure)
  IF ls_iobj_detail-iobjtp = 'KYF'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Additional properties'
        line_style = cs_custo-style_title2.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Decimal places'.
    PERFORM get_domain_value USING 'RSKYFDECIM' ls_iobj_detail-kyfdecim
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Display'.
    PERFORM get_domain_value USING 'RSKYFPRSNT' ls_iobj_detail-kyfprsnt
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Bex description'.
    PERFORM get_domain_value USING 'RSTXTDEF' ls_iobj_detail-txtdef
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Key Figure with High Precision'.
    IF ls_iobj_detail-packfl IS INITIAL.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Master data / texts
  IF ls_iobj_detail-iobjtp = 'CHA' OR ls_iobj_detail-iobjtp = 'DPA'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Master data/texts'
        line_style = cs_custo-style_title2.

* Master data bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Master data'
        line_style = cs_custo-style_title3.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline = 'With master data'.
    IF ls_iobj_detail-chktab = space.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox.
    ELSE.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    CALL METHOD o_doc->write_line
      EXPORTING
        style = cl_word=>c_style_normal.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'View of master data table'.
    ls_data-f2-textline = lw_iobj_chktab.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Master data table'.
    ls_data-f2-textline = lw_iobj_chntab.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'SID table attributes'.
    ls_data-f2-textline = lw_iobj_asitab.
    APPEND ls_data TO lt_data.

    IF NOT lw_iobj_chttab IS INITIAL.
      CLEAR ls_data.
      ls_data-f1-textline = 'Master data table (time-dependent)'.
      ls_data-f2-textline = lw_iobj_chttab.
      APPEND ls_data TO lt_data.
    ENDIF.

    IF NOT lw_iobj_asttab IS INITIAL.
      CLEAR ls_data.
      ls_data-f1-textline = 'SID table time-dependent attributes'.
      ls_data-f2-textline = lw_iobj_asttab.
      APPEND ls_data TO lt_data.
    ENDIF.

    CLEAR ls_data.
    ls_data-f1-textline = 'Master data maint. with Auth. Check'.
    IF ls_iobj_detail-mastauthfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'DS Object for check'.
    ls_data-f2-textline = ls_iobj_detail-checkods.
    APPEND ls_data TO lt_data.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.

* Texts bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Texts'
        line_style = cs_custo-style_title3.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline = 'With texts'.
    IF ls_iobj_detail-txttabfl = space.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox.
    ELSE.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    CALL METHOD o_doc->write_line
      EXPORTING
        style = cl_word=>c_style_normal.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Text table'.
    ls_data-f2-textline = lw_iobj_txttab.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Short text exists'.
    IF ls_iobj_detail-txtshfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Medium length text exists'.
    IF ls_iobj_detail-txtmdfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Long text exists'.
    IF ls_iobj_detail-txtlgfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Texts language dependant'.
    IF ls_iobj_detail-nolangu NE space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Texts are time-dependant'.
    IF ls_iobj_detail-txttimfl = '1'.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.

* Infoprovider bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Master Data Infosource / Data Target / InfoProvider / Master data read access'
        line_style = cs_custo-style_title3.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Infosource avec mise à jour directe'.
    IF ls_iobj_detail-applnm = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Application Component'.
    ls_data-f2-textline = ls_iobj_detail-applnm.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Characteristic is InfoProvider'.
    IF ls_iobj_detail-infoarea = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'InfoArea'.
    ls_data-f2-textline = ls_iobj_detail-infoarea.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Characteristic is export data source'.
    IF ls_iobj_detail-expdsourcefl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Master Data Access'.
    PERFORM get_domain_value USING 'RSCHATP' ls_iobj_detail-chatp
                             CHANGING lw_domtext.
    ls_data-f2-textline = lw_domtext.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Name of Master Data Read Class'.
    ls_data-f2-textline = ls_iobj_detail-mdrclnm.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Master Data Read Class Parameters'.
    ls_data-f2-textline = ls_iobj_detail-mdrclpa.
    APPEND ls_data TO lt_data.

    lw_texte = 'LS_IOBJ_DETAIL-RDAFL'.
    ASSIGN (lw_texte) TO <fs>.
    IF sy-subrc = 0.
      CLEAR ls_data.
      ls_data-f1-textline = 'Permitted for Real-Time Data Acquisition'.
      IF <fs> = space. "ls_iobj_detail-rdafl
        ls_data-f2-textline = cl_word=>c_symbol_checkbox.
      ELSE.
        ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
      ENDIF.
      ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
      APPEND ls_data TO lt_data.
    ENDIF.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Hierarchy
  IF ls_iobj_detail-iobjtp = 'CHA' OR ls_iobj_detail-iobjtp = 'UNI'
  OR ls_iobj_detail-iobjtp = 'TIM' OR ls_iobj_detail-iobjtp = 'DPA'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Hierarchy'
        line_style = cs_custo-style_title2.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline = 'With hierarchies'.
    IF ls_iobj_detail-hietabfl = space.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox.
    ELSE.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    CALL METHOD o_doc->write_line
      EXPORTING
        style = cl_word=>c_style_normal.

* Hierarchy properties bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Hierarchy properties'
        line_style = cs_custo-style_title3.

    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Hierarchies, version-dependent'.
    IF ls_iobj_detail-hieverfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Hierarchy not time-dependent'.
    IF ls_iobj_detail-hienmtfl = space AND ls_iobj_detail-hiendtfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Entire hierarchies is time-dependent'.
    IF ls_iobj_detail-hienmtfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Time-dependent Hierarchy structure'.
    IF ls_iobj_detail-hiendtfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Intervals permitted in hierarchy'.
    IF ls_iobj_detail-hieintfl = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.

    CLEAR ls_data.
    ls_data-f1-textline = 'Reverse +/- sign for Node'.
    IF ls_iobj_detail-hiesignch = space.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_data TO lt_data.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.

* Tables for hierarchies bloc
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Tables for Hierarchies'
        line_style = cs_custo-style_title3.
    REFRESH lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Hierarchy table'.
    ls_data-f2-textline = lw_iobj_hietab.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Hierarchy SID table'.
    ls_data-f2-textline = lw_iobj_hsitab.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'SID Hierarchy Structure'.
    ls_data-f2-textline = lw_iobj_inctab.
    APPEND ls_data TO lt_data.
    CLEAR ls_data.
    ls_data-f1-textline = 'Hierarchy intervals table'.
    ls_data-f2-textline = lw_iobj_hintab.
    APPEND ls_data TO lt_data.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.
  ENDIF.

* Attributes
  IF ls_iobj_detail-iobjtp = 'CHA'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Attributes'
        line_style = cs_custo-style_title2.

    REFRESH lt_attr.
    CLEAR ls_attr.
    ls_attr-f1-textline = 'Attribute'.
    ls_attr-f2-textline = 'Long description'.
    ls_attr-f3-textline = 'Type'.
    ls_attr-f4-textline = 'Time-dependent'.
    ls_attr-f5-textline = 'Order for F4 Help'.
    ls_attr-f6-textline = 'Text of Char.'.
    ls_attr-f7-textline = 'Nav. attr. description'.
    ls_attr-f8-textline = 'Nav. attr. short text'.
    ls_attr-f9-textline = 'Nav. attr. name'.
    APPEND ls_attr TO lt_attr.

    LOOP AT lt_iobj_attributes INTO ls_iobj_attributes.

      CLEAR ls_iobj_atr_txt.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_iobj_attributes-attrinm
                 BINARY SEARCH.
      CLEAR ls_attr.
      ls_attr-f1-textline = ls_iobj_attributes-attrinm.
      ls_attr-f2-textline = ls_iobj_atr_txt-txtlg.
      ls_attr-f3-textline = ls_iobj_attributes-attritp.
      IF ls_iobj_attributes-atrtimfl = 1.
        ls_attr-f4-textline = cl_word=>c_symbol_checkbox_checked.
      ELSE.
        ls_attr-f4-textline = cl_word=>c_symbol_checkbox.
      ENDIF.
      ls_attr-f4-style_effect-font = cl_word=>c_font_symbol.
      ls_attr-f5-textline = ls_iobj_attributes-f4order.

      READ TABLE lt_iobj_atr_nav INTO ls_iobj_atr_nav
                 WITH KEY attrinm = ls_iobj_attributes-attrinm
                 BINARY SEARCH.
      IF sy-subrc IS INITIAL.
        IF ls_iobj_atr_nav-txtfromchafl = space.
          ls_attr-f6-textline = cl_word=>c_symbol_checkbox.
        ELSE.
          ls_attr-f6-textline = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        ls_attr-f6-style_effect-font = cl_word=>c_font_symbol.
        ls_attr-f7-textline = ls_iobj_atr_nav-txtlg.
        ls_attr-f8-textline = ls_iobj_atr_nav-txtsh.
        ls_attr-f9-textline = ls_iobj_atr_nav-atrnavnm.
      ELSE.
        ls_attr-f6-textline = cl_word=>c_symbol_checkbox.
        ls_attr-f6-style_effect-font = cl_word=>c_font_symbol.
      ENDIF.
      APPEND ls_attr TO lt_attr.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_attr
        style   = cs_custo-table_with_head.
  ENDIF.

* Compounds
  IF ls_iobj_detail-iobjtp = 'CHA' OR ls_iobj_detail-iobjtp = 'DPA'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Compounding'
        line_style = cs_custo-style_title2.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline = 'Master data locally for source sys.'.
    READ TABLE lt_iobj_compound INTO ls_iobj_compound
               WITH KEY iobjcmp = '0SOURSYSTEM'.
    IF sy-subrc = 0.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox_checked.
    ELSE.
      CALL METHOD o_doc->write_symbol
        EXPORTING
          symbol = cl_word=>c_symbol_checkbox.
    ENDIF.
    CALL METHOD o_doc->write_line
      EXPORTING
        style = cl_word=>c_style_normal.

    REFRESH lt_comp.
    CLEAR ls_comp.
    ls_comp-f1 = 'Superior InfoObject'.
    ls_comp-f2 = 'Long description'.
    ls_comp-f3 = 'Ref. characteristic'.
    ls_comp-f4 = 'Constant'.
    APPEND ls_comp TO lt_comp.
    LOOP AT lt_iobj_compound INTO ls_iobj_compound.
      CLEAR ls_iobj_atr_txt.
      READ TABLE lt_iobj_atr_txt INTO ls_iobj_atr_txt
                 WITH KEY iobjnm = ls_iobj_compound-iobjcmp
                 BINARY SEARCH.

      CLEAR ls_iobj_comp_atr.
      READ TABLE lt_iobj_comp_atr INTO ls_iobj_comp_atr
                 WITH KEY chanm = ls_iobj_compound-iobjcmp
                 BINARY SEARCH.
      CLEAR ls_comp.
      ls_comp-f1 = ls_iobj_compound-iobjcmp.
      ls_comp-f2 = ls_iobj_atr_txt-txtlg.
      ls_comp-f3 = ls_iobj_comp_atr-chabasnm.
      ls_comp-f4 = ls_iobj_comp_atr-chaconst.
      APPEND ls_comp TO lt_comp.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_comp
        style   = cs_custo-table_with_head.
  ENDIF.

* Update rules 3x
  IF lw_iobj_txttab NE space OR ls_iobj_detail-chktab NE space.
    PERFORM updr_list USING ls_iobj_detail-iobjnm
                            c_iobj.
  ENDIF.

* transformation 7x
  PERFORM trsf_list USING ls_iobj_detail-iobjnm c_iobj.

  PERFORM get_used_pc USING ls_iobj_detail-iobjnm c_iobj.
ENDFORM.                    "iobj

*&---------------------------------------------------------------------*
*&      Form  get_domain_value
*&---------------------------------------------------------------------*
*       Get text for given value of a ddic domain
*       Use internal table t_buffer_domvalue as a buffer
*----------------------------------------------------------------------*
*      -->FW_DOMNAME Domain name
*      -->FW_VALUE   Value
*      <--FW_TEXT    Text of the value
*----------------------------------------------------------------------*
FORM get_domain_value USING fw_domname TYPE domname
                            fw_value
                      CHANGING fw_text TYPE val_text.
  CLEAR fw_text.
* Get domain value from buffer
  READ TABLE t_buffer_domvalue
             WITH KEY domname = fw_domname
                      domvalue = fw_value
             BINARY SEARCH.
  IF sy-subrc = 0.
    fw_text = t_buffer_domvalue-ddtext.
    RETURN.
  ENDIF.

* If not found, search if domain already read from database
  READ TABLE t_buffer_domvalue
             WITH KEY domname = fw_domname
             BINARY SEARCH.
  IF sy-subrc = 0.
    fw_text = fw_value.
    RETURN.
  ENDIF.

* For new domain, read values from database
  SELECT domname domvalue_l ddtext
         APPENDING TABLE t_buffer_domvalue
         FROM dd07t
         WHERE domname = fw_domname
         AND ddlanguage = c_lang_default
         AND as4local = c_objvers_active
         AND as4vers = '0000'.
  IF sy-subrc = 0.
    SORT t_buffer_domvalue BY domname domvalue.
    CLEAR t_buffer_domvalue.
    READ TABLE t_buffer_domvalue
               WITH KEY domname = fw_domname
                        domvalue = fw_value
               BINARY SEARCH.
    IF sy-subrc = 0.
      fw_text = t_buffer_domvalue-ddtext.
    ENDIF.
  ENDIF.
  IF sy-subrc NE 0.
    fw_text = fw_value.
  ENDIF.
ENDFORM.                    "get_domain_value

*&---------------------------------------------------------------------*
*&      Form  FILL_OBJECTS_TO_PROCESS
*&---------------------------------------------------------------------*
*       Get list of objects to process from selection-screen
*----------------------------------------------------------------------*
FORM fill_objects_to_process.
  DATA ls_object LIKE s_object.
  DATA : BEGIN OF ls_cubes,
           cube TYPE rsdcube-infocube,
         END OF ls_cubes,
         lt_cubes LIKE TABLE OF ls_cubes,
         BEGIN OF ls_dso,
           dso TYPE rsdodso-odsobject,
         END OF ls_dso,
         lt_dso LIKE TABLE OF ls_dso,
         BEGIN OF ls_iobj,
           iobj TYPE rsdiobj-iobjnm,
         END OF ls_iobj,
         lt_iobj LIKE TABLE OF ls_iobj,
         BEGIN OF ls_is,
           is TYPE rsis-isource,
         END OF ls_is,
         lt_is LIKE TABLE OF ls_is,
         BEGIN OF ls_query,
           compid TYPE rsrrepdir-compid,
         END OF ls_query,
         lt_query LIKE TABLE OF ls_query,
         BEGIN OF ls_iset,
           infoset TYPE rsqinfoset,
         END OF ls_iset,
         lt_isets LIKE TABLE OF ls_iset,
         BEGIN OF ls_oh,
           ohdest TYPE rsohdest,
         END OF ls_oh,
         lt_oh LIKE TABLE OF ls_oh,
         BEGIN OF ls_ds,
           ds     TYPE rsoltpsource-oltpsource,
           logsys TYPE rsoltpsource-logsys,
         END OF ls_ds,
         lt_ds     LIKE TABLE OF ls_ds,
         lr_logsys LIKE RANGE OF p_dest,
         ls_logsys LIKE LINE OF lr_logsys,
         BEGIN OF ls_chain,
           chain_id TYPE rspcchainattr-chain_id,
         END OF ls_chain,
         lt_chain LIKE TABLE OF ls_chain.

  PERFORM object_progress_bar USING space space
                            'Get list of objects to process...'(m09).

* Read Workbook
  IF NOT p_wb IS INITIAL.
    CLEAR ls_object.
    IF NOT cs_custo-workbook_role_template IS INITIAL.
      SELECT SINGLE sap_guid
             FROM agr_hier
             INTO ls_object-object
             WHERE agr_name LIKE cs_custo-workbook_role_template
             AND report EQ 'RRMX'
             AND sap_guid = p_wb.
    ELSE.
      SELECT SINGLE workbookid
             FROM rsrwbindex
             INTO ls_object-object
             WHERE workbookid = p_wb
             AND objvers = c_objvers_active.
    ENDIF.
    IF sy-subrc = 0.
      ls_object-objtype = c_wb.
      APPEND ls_object TO t_objects_to_process.
    ENDIF.
  ENDIF.

* Read Wad
  IF NOT p_wad IS INITIAL.
    CLEAR ls_object.
    SELECT SINGLE objid
           FROM rszwbtmphead
           INTO ls_object-object
           WHERE objid  = p_wad
           AND objvers = c_objvers_active.
    IF sy-subrc = 0.
      ls_object-objtype = c_wad.
      APPEND ls_object TO t_objects_to_process.
    ENDIF.
  ENDIF.

* Read Queries
  IF NOT so_query[] IS INITIAL.
    SELECT compid INTO TABLE lt_query
           FROM rsrrepdir
           WHERE compid IN so_query
           AND objvers = c_objvers_active.
    LOOP AT lt_query INTO ls_query.
      CLEAR ls_object.
      ls_object-objtype = c_query.
      ls_object-object = ls_query-compid.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read cubes
  IF NOT so_cube[] IS INITIAL.
    SELECT infocube INTO TABLE lt_cubes
           FROM rsdcube
           WHERE infocube IN so_cube
           AND objvers = c_objvers_active
           AND cubetype NE 'M'. "exclude multiprov
    LOOP AT lt_cubes INTO ls_cubes.
      CLEAR ls_object.
      ls_object-objtype = c_cube.
      ls_object-object = ls_cubes-cube.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read dso
  IF NOT so_dso[] IS INITIAL.
    SELECT odsobject INTO TABLE lt_dso
           FROM rsdodso
           WHERE odsobject IN so_dso
           AND objvers = c_objvers_active.
    LOOP AT lt_dso INTO ls_dso.
      CLEAR ls_object.
      ls_object-objtype = c_dso.
      ls_object-object = ls_dso-dso.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read iobj
  IF NOT so_iobj[] IS INITIAL.
    SELECT iobjnm INTO TABLE lt_iobj
           FROM rsdiobj
           WHERE iobjnm IN so_iobj
           AND objvers = c_objvers_active.
    LOOP AT lt_iobj INTO ls_iobj.
      CLEAR ls_object.
      ls_object-objtype = c_iobj.
      ls_object-object = ls_iobj-iobj.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read IS
  IF NOT so_is[] IS INITIAL.
* Get IS 3x
    SELECT isource INTO TABLE lt_is
           FROM rsis
           WHERE isource IN so_is
           AND objvers = c_objvers_active.
    LOOP AT lt_is INTO ls_is.
      CLEAR ls_object.
      ls_object-objtype = c_is3.
      ls_object-object = ls_is-is.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
* Get IS 7x
    REFRESH lt_is.
    SELECT isource INTO TABLE lt_is
           FROM rsksnew
           WHERE isource IN so_is
           AND objvers = c_objvers_active.
    LOOP AT lt_is INTO ls_is.
      CLEAR ls_object.
      ls_object-objtype = c_is7.
      ls_object-object = ls_is-is.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read multiprov
  IF NOT so_multi[] IS INITIAL.
    SELECT infocube INTO TABLE lt_cubes
           FROM rsdcube
           WHERE infocube IN so_multi
           AND objvers = c_objvers_active
           AND cubetype = 'M'.
    LOOP AT lt_cubes INTO ls_cubes.
      CLEAR ls_object.
      ls_object-objtype = c_multi.
      ls_object-object = ls_cubes-cube.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read infoset
  IF NOT so_iset[] IS INITIAL.
    SELECT infoset INTO TABLE lt_isets
           FROM rsqiset
           WHERE infoset IN so_iset
           AND objvers = c_objvers_active.
    LOOP AT lt_isets INTO ls_iset.
      CLEAR ls_object.
      ls_object-objtype = c_iset.
      ls_object-object = ls_iset-infoset.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read Open Hub
  IF NOT so_open[] IS INITIAL.
    SELECT ohdest INTO TABLE lt_oh
           FROM rsbohdest
           WHERE ohdest IN so_open
           AND objvers = c_objvers_active.
    LOOP AT lt_oh INTO ls_oh.
      CLEAR ls_object.
      ls_object-objtype = c_oh.
      ls_object-object = ls_oh-ohdest.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF.

* Read DS
  IF NOT so_ds[] IS INITIAL.
    REFRESH lr_logsys.
    IF NOT p_dest IS INITIAL.
      ls_logsys-sign = 'I'.
      ls_logsys-option = 'EQ'.
      ls_logsys-low = p_dest.
      APPEND ls_logsys TO lr_logsys.
    ENDIF.

* Search all replicated datasource 3x
    SELECT oltpsource logsys INTO TABLE lt_ds
           FROM rsoltpsource
           WHERE oltpsource IN so_ds
           AND logsys IN lr_logsys
           AND objvers = c_objvers_active.
* Search all replicated datasource 7x
    SELECT datasource logsys APPENDING TABLE lt_ds
           FROM rsds
           WHERE datasource IN so_ds
           AND logsys IN lr_logsys
           AND objvers = c_objvers_active.
    LOOP AT lt_ds INTO ls_ds.
      CLEAR ls_object.
      ls_object-objtype = c_ds.
      ls_object-object = ls_ds-ds.
      ls_object-subobject = ls_ds-logsys.
      APPEND ls_object TO t_objects_to_process.
    ENDLOOP.
  ENDIF. "IF NOT so_ds IS INITIAL.

* Read Chain
  IF NOT so_chain IS INITIAL.
    SELECT chain_id INTO TABLE lt_chain
           FROM rspcchainattr
           WHERE chain_id IN so_chain
           AND objvers = c_objvers_active.
    IF sy-subrc = 0.
      LOOP AT lt_chain INTO ls_chain.
        CLEAR ls_object.
        ls_object-objtype = c_chain.
        ls_object-object = ls_chain-chain_id.
        APPEND ls_object TO t_objects_to_process.
      ENDLOOP.
    ENDIF.
  ENDIF.

ENDFORM.                    " FILL_OBJECTS_TO_PROCESS

*&---------------------------------------------------------------------*
*&      Form  FINALIZE_DOC
*&---------------------------------------------------------------------*
*       Do process at end of document :
*       - Update process chain list
*       - Save document (if required)
*----------------------------------------------------------------------*
*      -->FS_OBJECT  Object to initialize
*----------------------------------------------------------------------*
FORM finalize_doc USING fs_object LIKE s_object.
  DATA : lw_chains TYPE string,
         BEGIN OF ls_chain,
           f1(80) TYPE c,
           f2(80) TYPE c,
         END OF ls_chain,
         lt_chain LIKE TABLE OF ls_chain.

  PERFORM object_progress_bar USING fs_object-object fs_object-objtype
                                    'Finalizing document...'(m10).
* Update process chain list
  SORT t_used_pc.
  DELETE ADJACENT DUPLICATES FROM t_used_pc.

  REFRESH lt_chain.
  CLEAR ls_chain.
  ls_chain-f1 = 'Process Chain'.
  ls_chain-f2 = 'Description'.
  APPEND ls_chain TO lt_chain.

  IF NOT t_used_pc IS INITIAL.
    SELECT chain_id txtlg FROM rspcchaint
           APPENDING TABLE lt_chain
           FOR ALL ENTRIES IN t_used_pc
           WHERE chain_id = t_used_pc-id
           AND objvers = c_objvers_active
           AND langu = c_lang_default.
  ELSE.
    CLEAR ls_chain.
    ls_chain-f1 = '-'.
    ls_chain-f2 = '-'.
    APPEND ls_chain TO lt_chain.
  ENDIF.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_chain
      style   = cs_custo-table_with_head
    IMPORTING
      virtual = lw_chains.

  CALL METHOD o_doc->replace_virtual_field
    EXPORTING
      field        = 'process_chain'
      value        = lw_chains
      value_as_xml = cl_word=>c_true.

* Display process chain documentation
  LOOP AT t_used_pc INTO s_used_pc.
    PERFORM process_chain USING s_used_pc-id.
  ENDLOOP.
  REFRESH t_used_pc.

  CALL METHOD o_doc->set_params
    EXPORTING
      nospellcheck = cl_word=>c_true.

* Display includes
  PERFORM process_includes.

* Display "how to generate"
  IF p_split IS INITIAL.
    PERFORM howto_generate.
  ENDIF.

* Save document
  IF NOT w_doc_filename IS INITIAL.
    CALL METHOD o_doc->save
      EXPORTING
        url = w_doc_filename.
  ENDIF.
ENDFORM.                    " FINALIZE_DOC

*&---------------------------------------------------------------------*
*&      Form  ADD_OBJECT_TO_QUEUE
*&---------------------------------------------------------------------*
*       Add given object to the buffer
*----------------------------------------------------------------------*
*      -->FS_OBJECT  Object to add
*----------------------------------------------------------------------*
FORM add_object_to_queue USING fs_object LIKE s_object.

* Check if object is already processed
  READ TABLE t_objects_processed
             WITH KEY objtype = fs_object-objtype
                      object = fs_object-object
                      subobject = fs_object-subobject
             TRANSPORTING NO FIELDS.

  IF sy-subrc = 0.
    RETURN. "already processed
  ENDIF.

* Check if object is already in queue
  READ TABLE t_objects_to_process
             WITH KEY objtype = fs_object-objtype
                      object = fs_object-object
                      subobject = fs_object-subobject
             TRANSPORTING NO FIELDS.
  IF sy-subrc = 0.
    RETURN. "already in queue
  ENDIF.

* Add object in queue
  APPEND fs_object TO t_objects_to_process.

ENDFORM.                    " ADD_OBJECT_TO_QUEUE

*&---------------------------------------------------------------------*
*&      Form  GET_USED_PC
*&---------------------------------------------------------------------*
*       Get list of process chain where the InfoProvider is loaded
*----------------------------------------------------------------------*
*      -->FW_INFOPROV  Target infoprovider
*      -->FW_TYPE      Type of infoprovider
*----------------------------------------------------------------------*
FORM get_used_pc USING fw_infoprov
                       fw_type TYPE rstlogo.
  PERFORM object_progress_bar USING fw_infoprov fw_type
                                    'Search process chains usage...'(m11).

  SELECT DISTINCT chain_id APPENDING TABLE t_used_pc
  FROM rspcchain
  WHERE objvers = c_objvers_active
  AND variante IN (
  SELECT t0~logdpid
    FROM rsldpio AS t0
    WHERE
* Active update rule exist for the target
  t0~logdpid IN ( SELECT t2~logdpid
                    FROM rsupdinfo AS t1
                    JOIN rsldpio AS t2
                    ON t1~isource = t2~source
                    AND t1~objvers = t2~objvers
                    WHERE t1~infocube = fw_infoprov
                    AND t1~objvers = c_objvers_active  )
  AND
* target is checked in the infopackage
    ( EXISTS  ( SELECT logdpid
                FROM rsldpsel
                WHERE logdpid = t0~logdpid
                AND objvers = c_objvers_active
                AND selupdic = fw_infoprov
                 )
* "all target" checked in the infopackage
    OR NOT EXISTS ( SELECT logdpid
                     FROM rsldpsel
                WHERE logdpid = t0~logdpid
                AND objvers = c_objvers_active
                AND selupdic NE '' )
    )
  )
* Process chain is in a node (= in plan batch)
  AND EXISTS ( SELECT chain_id
               FROM rspcchainattr
               WHERE chain_id = rspcchain~chain_id
               AND objvers = c_objvers_active
               AND applnm NE '' )
  .

* For infoObjects, add direct infosource infopackage process chain
  IF fw_type = c_iobj.
    SELECT DISTINCT chain_id APPENDING TABLE t_used_pc
    FROM rspcchain
    WHERE objvers = c_objvers_active
    AND variante IN (
                  SELECT logdpid
                  FROM rsldpio
                  WHERE objvers = c_objvers_active
                  AND source = fw_infoprov
    )
    AND EXISTS ( SELECT chain_id
                 FROM rspcchainattr
                 WHERE chain_id = rspcchain~chain_id
                 AND objvers = c_objvers_active
                 AND applnm NE '' )
    .
  ENDIF.

* Chain with DTP
  SELECT DISTINCT chain_id APPENDING TABLE t_used_pc
  FROM rspcchain
  WHERE objvers = c_objvers_active
  AND variante IN (
         SELECT DISTINCT dtp
         FROM rsbkdtp
         WHERE tgt = fw_infoprov
         AND   objvers = c_objvers_active
  )
  AND EXISTS ( SELECT chain_id
               FROM rspcchainattr
               WHERE chain_id = rspcchain~chain_id
               AND objvers = c_objvers_active
               AND applnm NE '' )
  .
ENDFORM.                    " GET_USED_PC

*&---------------------------------------------------------------------*
*&      Form  GET_DOC_TITLE
*&---------------------------------------------------------------------*
*       Determine title of the document
*----------------------------------------------------------------------*
*      -->FS_OBJTYPE Type of object
*      -->FS_OBJECT  Object name
*      -->FS_SUBOBJECT  SubObject name
*      <--FW_TITLE   Title of the document
*----------------------------------------------------------------------*
FORM get_doc_title USING    fs_objtype TYPE rstlogo
                            fs_object TYPE string
                            fs_subobject TYPE string
                   CHANGING fw_title TYPE string.
  IF NOT p_flow IS INITIAL.
    fw_title = p_flow.
    RETURN.
  ENDIF.

  CASE fs_objtype.
    WHEN c_cube.
      CONCATENATE 'Cube' fs_object INTO fw_title SEPARATED BY space.
    WHEN c_dso.
      CONCATENATE 'DSO' fs_object INTO fw_title SEPARATED BY space.
    WHEN c_is3 OR c_is7.
      CONCATENATE 'Infosource' fs_object
                   INTO fw_title SEPARATED BY space.
    WHEN c_ds.
      CONCATENATE 'Datasource' fs_object '(' fs_subobject ')'
                   INTO fw_title SEPARATED BY space.
    WHEN c_iobj.
      CONCATENATE 'InfoObject' fs_object
                   INTO fw_title SEPARATED BY space.
    WHEN c_multi.
      CONCATENATE 'MultiProvider' fs_object
                   INTO fw_title SEPARATED BY space.
    WHEN c_wb.
      SELECT SINGLE title INTO fw_title
             FROM rsrwbindext
             WHERE workbookid = fs_object
             AND langu = c_lang_default.
      CONCATENATE 'Workbook' fw_title
                  INTO fw_title SEPARATED BY space.
    WHEN c_wad.
      CONCATENATE 'Bex Web Template' fs_object
                  INTO fw_title SEPARATED BY space.
    WHEN c_query.
      CONCATENATE 'Query' fs_object
                  INTO fw_title SEPARATED BY space.
    WHEN c_chain.
      CONCATENATE 'Process Chain' fs_object
                  INTO fw_title SEPARATED BY space.
    WHEN c_iset.
      CONCATENATE 'InfoSet' fs_object
                  INTO fw_title SEPARATED BY space.
    WHEN c_oh.
      CONCATENATE 'Open Hub Destination' fs_object
                  INTO fw_title SEPARATED BY space.
    WHEN OTHERS.
      fw_title = '???'.
  ENDCASE.

ENDFORM.                    " GET_DOC_TITLE

*&---------------------------------------------------------------------*
*&      Form  object_progress_bar
*&---------------------------------------------------------------------*
*       Display progression
*----------------------------------------------------------------------*
*      -->FW_OBJECT  Object processed
*      -->FW_OBJTYPE Object type
*      -->FW_STEP    Current step
*----------------------------------------------------------------------*
FORM object_progress_bar USING fw_object
                               fw_objtype TYPE rstlogo
                               fw_step TYPE string.
  DATA : lw_lines_done  TYPE i,
         lw_lines_total TYPE i,
         lw_percent     TYPE i,
         lw_progress    TYPE string,
         lw_doc         TYPE string,
         lw_stat(1)     TYPE c.


  DESCRIBE TABLE t_objects_to_process LINES lw_lines_total.
  DESCRIBE TABLE t_objects_processed LINES lw_lines_done.
  lw_lines_total = lw_lines_total + lw_lines_done.
  IF lw_lines_total = 0.
    lw_percent = 0.
  ELSE.
    lw_percent = 100 * lw_lines_done / lw_lines_total.
  ENDIF.
  CASE fw_objtype.
    WHEN c_cube.
      lw_doc = 'Cube'.
    WHEN c_dso.
      lw_doc = 'DSO'.
    WHEN c_is3 OR c_is7.
      lw_doc = 'Infosource'.
    WHEN c_iobj.
      lw_doc = 'InfoObject'.
    WHEN c_ds.
      lw_doc = 'Datasource'.
    WHEN c_multi.
      lw_doc = 'Multiprovider'.
    WHEN c_wb.
      lw_doc = 'Workbook'.
    WHEN c_wad.
      lw_doc = 'Bex Web Template'.
    WHEN c_chain.
      lw_doc = 'Process Chain'.
    WHEN c_query.
      lw_doc = 'Query'.
    WHEN c_iset.
      lw_doc = 'InfoSet'.
    WHEN OTHERS.
      lw_doc = 'Document'.
  ENDCASE.
  CONCATENATE lw_doc fw_object INTO lw_doc SEPARATED BY space.
  lw_progress = lw_lines_done && '/' && lw_lines_total.

  IF cs_custo-progress_popup = space.
    CONCATENATE lw_doc fw_step '(&2/&3)'
                INTO lw_progress SEPARATED BY space.
    CALL METHOD cl_progress_indicator=>progress_indicate
      EXPORTING
        i_text               = lw_progress
        i_total              = lw_lines_total
        i_processed          = lw_lines_done
        i_output_immediately = 'X'.
  ELSE.
* First display, create popup
    IF w_progress_winid = space.
      lw_stat = space.
    ELSE.
* Further display, update popup
      lw_stat = 3.
    ENDIF.

    CALL FUNCTION 'PROGRESS_POPUP'
      EXPORTING
*       BTN_TXT = ' '
        curval = lw_lines_done
        maxval = lw_lines_total
        stat   = lw_stat
        text_1 = lw_doc
        text_2 = lw_progress
        text_3 = fw_step
        title  = 'Technical document generation in progress...'
        winid  = w_progress_winid
      IMPORTING
        rwnid  = w_progress_winid.
  ENDIF.

ENDFORM.                    "object_progress_bar

*&---------------------------------------------------------------------*
*&      Form  object_progress_bar_close
*&---------------------------------------------------------------------*
*       Close progression popup
*----------------------------------------------------------------------*
FORM object_progress_bar_close.
  IF cs_custo-progress_popup NE space.
    CALL FUNCTION 'GRAPH_DIALOG'
      EXPORTING
        close = 'X'
        kwdid = w_progress_winid.
    CLEAR w_progress_winid.
  ENDIF.
ENDFORM.                    "object_progress_bar_close

*&---------------------------------------------------------------------*
*&      Form  TRSF_LIST
*&---------------------------------------------------------------------*
*       Get list of transformations
*----------------------------------------------------------------------*
*      -->FW_OBJECT Target of the transformation
*      -->FW_OBJTYP Target type
*----------------------------------------------------------------------*
FORM trsf_list USING fw_object
                     fw_objtyp TYPE rstlogo.
  DATA: BEGIN OF ls_transf,
          tranid TYPE rstran-tranid,
          srctp  TYPE rstran-sourcetype,
          src    TYPE rstran-sourcename,
        END OF ls_transf,
        lt_transf LIKE TABLE OF ls_transf,
        BEGIN OF ls_dtp,
          dtp   TYPE rsbkdtp-dtp,
          src   TYPE rsbkdtp-src,
          srctp TYPE rsbkdtp-srctlogo,
        END OF ls_dtp,
        lt_dtp     LIKE TABLE OF ls_dtp,
        lw_objtyp  TYPE rstran-targettype,
        ls_object  LIKE s_object,
        lw_tpl(30) TYPE c,
        lw_ref     LIKE p_ref.

  CLEAR lw_objtyp.
  CASE fw_objtyp.
    WHEN c_iobj
    OR c_dso
    OR c_cube
    OR c_is7
    OR c_oh.
      lw_objtyp = fw_objtyp.
    WHEN OTHERS.
      RETURN.
  ENDCASE.

* Transformations 7x
  SELECT tranid sourcetype sourcename
         INTO TABLE lt_transf
         FROM rstran
         WHERE targettype = lw_objtyp
         AND targetname = fw_object
         AND objvers = c_objvers_active
         AND ( objstat = 'ACT' OR objstat = 'PRO' ).

* DTP list
  IF p_skip = space.
    CASE p_ipdisp.
      WHEN c_ip_display_yes.
* Get all active DTP on the target
        SELECT dtp src srctlogo
               INTO TABLE lt_dtp
               FROM rsbkdtp
               WHERE tgttlogo = lw_objtyp
               AND tgt = fw_object
               AND objvers = 'A'.

      WHEN c_ip_display_chain.
* Get all active DTP on the target used in a process chain
        SELECT dtp src srctlogo
               INTO TABLE lt_dtp
               FROM rsbkdtp
               WHERE tgttlogo = lw_objtyp
               AND tgt = fw_object
               AND objvers = 'A'
               AND EXISTS ( SELECT *
                            FROM rspcchain
                            WHERE objvers = 'A'
                            AND type = 'DTP_LOAD'
                            AND variante = rsbkdtp~dtp  ).

      WHEN c_ip_display_node.
* Get all active DTP on the target used in a process chain in a node
        SELECT dtp src srctlogo
               INTO TABLE lt_dtp
               FROM rsbkdtp
               WHERE tgttlogo = lw_objtyp
               AND tgt = fw_object
               AND objvers = 'A'
               AND EXISTS ( SELECT *
                            FROM rspcchain
                            JOIN rspcchainattr
                            ON rspcchain~chain_id = rspcchainattr~chain_id
                            AND rspcchain~objvers = rspcchainattr~objvers
                            WHERE rspcchain~objvers = 'A'
                            AND rspcchain~type = 'DTP_LOAD'
                            AND rspcchain~variante = rsbkdtp~dtp
                            AND rspcchainattr~applnm NE '' ).

      WHEN OTHERS.
    ENDCASE.
  ENDIF.

  LOOP AT lt_transf INTO ls_transf.
* filter duplicates when reference object is given
    IF NOT p_ref IS INITIAL AND
    ( ls_transf-srctp = c_dso OR ls_transf-srctp = c_cube ).
      PERFORM get_reference USING    ls_transf-src
                            CHANGING lw_tpl lw_ref.

* Keep only cubes from reference object & non duplicated cubes
      IF lw_tpl NE space AND NOT lw_ref IS INITIAL
      AND lw_ref NE p_ref.
        DELETE lt_transf.
        DELETE lt_dtp WHERE src = ls_transf-src
                      AND srctp = ls_transf-srctp.
        CONTINUE.
      ENDIF.
    ENDIF.

    IF p_skip = space.
      PERFORM trsf USING ls_transf-tranid
                         fw_object
                         fw_objtyp
                         ls_transf-src.
    ENDIF.
  ENDLOOP.

  IF p_skip = space.
    LOOP AT lt_dtp INTO ls_dtp.
      PERFORM dtp USING ls_dtp-dtp
                        fw_object
                        fw_objtyp
                        ls_dtp-src.
*      IF ls_dtp-srctp = 'RSDS'.
*        condense ls_dtp-src.
*        SPLIT ls_dtp-src AT space INTO lw_src lw_logsys.
*        PERFORM ip_list USING fw_object fw_objtyp lw_logsys lw_src.
*      ENDIF.
    ENDLOOP.
  ENDIF.

  LOOP AT lt_transf INTO ls_transf.
    CASE ls_transf-srctp.
      WHEN c_dso
      OR c_cube
      OR c_iobj.
        IF p_recurs NE space.
          CLEAR ls_object.
          ls_object-objtype = ls_transf-srctp.
          ls_object-object = ls_transf-src.
          PERFORM add_object_to_queue USING ls_object.
        ENDIF.
      WHEN c_is7. "Infosource
        CLEAR ls_object.
        ls_object-objtype = c_is7.
        ls_object-object = ls_transf-src.
        PERFORM add_object_to_queue USING ls_object.
      WHEN c_ds. "Datasource
        CLEAR ls_object.
        ls_object-objtype = c_ds.
        CONDENSE ls_transf-src.
        SPLIT ls_transf-src AT space INTO ls_object-object ls_object-subobject.
        PERFORM add_object_to_queue USING ls_object.
      WHEN c_query. "Query
        IF p_recurs NE space AND p_recqry NE space.
          CLEAR ls_object.
          ls_object-objtype = c_query.
          SELECT SINGLE compid
                 INTO ls_object-object
                 FROM rsrrepdir
                 WHERE compuid = ls_transf-src
                 AND objvers = c_objvers_active.
          "ls_object-object = ls_transf-src.
          PERFORM add_object_to_queue USING ls_object.
        ENDIF.
      WHEN OTHERS.

    ENDCASE.
  ENDLOOP.

ENDFORM.                    " TRSF_LIST

*&---------------------------------------------------------------------*
*&      Form  TRSF
*&---------------------------------------------------------------------*
*       Display documentation for a transformation
*----------------------------------------------------------------------*
*      -->FW_TRANID Transformation ID
*----------------------------------------------------------------------*
FORM trsf USING fw_tranid TYPE rstranid
                fw_target
                fw_tgttp TYPE rstlogo
                fw_source TYPE rstran-sourcename.

  DATA : lo_rstran          TYPE REF TO cl_rstran_trfn,
         lo_routine         TYPE REF TO cl_rstran_step_rout,
         lo_constant        TYPE REF TO cl_rstran_step_constant,
         lo_master          TYPE REF TO cl_rstran_step_master,
         ls_source          TYPE rstran_s_tlogo,
         ls_target          TYPE rstran_s_tlogo,
         lw_domval          TYPE val_text,
         lw_texte           TYPE string,
         lt_abap_start_code TYPE rstran_t_abapsource,
         lt_abap_end_code   TYPE rstran_t_abapsource,
         lt_abap_global     TYPE rstran_t_abapsource,
         lt_abap_global2    TYPE rstran_t_abapsource,
         ls_abap_code       LIKE LINE OF lt_abap_start_code,
         lt_tranrule        TYPE rstran_t_rule_ref,
         ls_tranrule        LIKE LINE OF lt_tranrule,
         lw_trantxt         TYPE rstxtlg,
         lt_code            TYPE ty_code_table,
         BEGIN OF ls_tab,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
           f5 TYPE cl_word=>ty_table_style_field,
           f6 TYPE cl_word=>ty_table_style_field,
         END OF ls_tab,
         lt_tab LIKE TABLE OF ls_tab,
         BEGIN OF ls_data,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_routine_tbd,
           target  TYPE string,
           routine TYPE REF TO cl_rstran_step_rout,
         END OF ls_routine_tbd,
         lt_routine_tbd LIKE TABLE OF ls_routine_tbd,
         BEGIN OF ls_formula_tbd,
           target  TYPE string,
           formula TYPE REF TO cl_rstran_step_formula,
         END OF ls_formula_tbd,
         lt_formula_tbd  LIKE TABLE OF ls_formula_tbd,
         lt_tlogo        TYPE rso_th_tlogo,
         ls_ruleinfo     TYPE rstranrule,
         lt_rulesteps    TYPE rstran_t_rulestep,
         ls_rulesteps    LIKE LINE OF lt_rulesteps,
         lt_sourcemap    TYPE rstran_tx_mapped_field,
         ls_sourcemap    LIKE LINE OF lt_sourcemap,
         ls_targetfield  TYPE rstran_sx_mapped_field,
         lw_constant_val TYPE rstran_constant,
         ls_source_field TYPE rstran_sx_step_field_param,
         lw_ruletxt      TYPE rstxtlg,
         lw_position     TYPE i,
         ls_transf       TYPE rstran,
         lt_group        TYPE rstran_t_group,
         ls_group        LIKE LINE OF lt_group,
         lt_segment      TYPE rstran_t_segment,
         lw_group        TYPE rstran_groupid,
         lw_groupname    TYPE string,
         lw_groups       TYPE i,
         lw_segments     TYPE i,
         lt_sourceseg    TYPE rstran_t_segid,
         ls_sourceseg    LIKE LINE OF lt_sourceseg,
         BEGIN OF ls_segmentt,
           segid TYPE rsdssegt-segid,
           txtsh TYPE rsdssegt-txtsh,
           txtlg TYPE rsdssegt-txtlg,
         END OF ls_segmentt,
         lt_segmentt LIKE TABLE OF ls_segmentt.

  CONCATENATE 'Writing transformation...'(m12)
              fw_source '=>' fw_target
              INTO lw_texte SEPARATED BY space.
  PERFORM object_progress_bar USING fw_target fw_tgttp
                                    lw_texte.

  TRY.
      CALL METHOD cl_rstran_trfn=>factory
        EXPORTING
          i_tranid = fw_tranid
        RECEIVING
          r_r_tran = lo_rstran.
    CATCH cx_rstran_not_found.
      MESSAGE e000(rstran) WITH 'TRFN' fw_tranid 'not found'.
    CATCH cx_rstran_input_invalid.
      MESSAGE e000(rstran) WITH 'TRFN' fw_tranid 'invalid'.
    CATCH cx_rstran_error_with_message.
      MESSAGE e000(rstran) WITH 'TRFN' fw_tranid 'with error'.
  ENDTRY.

* Get transformation info
  CALL METHOD lo_rstran->get_info_current
    EXPORTING
      i_tranid     = fw_tranid
      i_th_tlogo   = lt_tlogo
    IMPORTING
      e_tran_txt   = lw_trantxt
      e_s_info     = ls_transf
      e_t_tranrule = lt_tranrule.

* Get list of rules group
  CALL METHOD lo_rstran->get_info_act
    IMPORTING
      e_t_group   = lt_group
      e_t_segment = lt_segment.

  DELETE lt_group WHERE groupid = '00'. "remove start/end routine group
  DELETE lt_segment WHERE segid = '0000'. "remove start/end routine segment
  DESCRIBE TABLE lt_group LINES lw_groups.
  DESCRIBE TABLE lt_segment LINES lw_segments.
  IF lw_segments GT 1 AND ls_transf-sourcetype = c_ds.
    SELECT segid txtsh txtlg
           INTO TABLE lt_segmentt
           FROM rsdssegt
           WHERE langu = sy-langu
           AND datasource = ls_transf-sourcename(30)
           AND logsys = ls_transf-sourcename+30(10).
  ENDIF.

* Get target
  CALL METHOD lo_rstran->get_target
    IMPORTING
      e_s_target = ls_target.

* Get source
  CALL METHOD lo_rstran->get_source
    IMPORTING
      e_s_source = ls_source.

* Get Start routine
  CALL METHOD lo_rstran->get_start_routine
    RECEIVING
      r_routine = lo_routine.
  IF NOT lo_routine IS INITIAL.
    CALL METHOD lo_routine->get_code
      IMPORTING
        e_t_routine_source = lt_abap_start_code
        e_t_global_source  = lt_abap_global
        e_t_global_source2 = lt_abap_global2.
  ENDIF.

* End routine
  CLEAR lo_routine.
  CALL METHOD lo_rstran->get_end_routine
    RECEIVING
      r_routine = lo_routine.
  IF NOT lo_routine IS INITIAL.
    CALL METHOD lo_routine->get_code
      IMPORTING
        e_t_routine_source = lt_abap_end_code
        e_t_global_source  = lt_abap_global
        e_t_global_source2 = lt_abap_global2.
  ENDIF.

* Transformation title
  CONCATENATE 'Transformation' lw_trantxt
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title2.

* Insert embbeded documents
  PERFORM special_note USING 'TRFN' fw_tranid
                             cs_custo-style_title3.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title3.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Transformation ID'.
  ls_data-f2-textline = fw_tranid.
  APPEND ls_data TO lt_data.

* Source info
  CLEAR ls_data.
  ls_data-f1-textline = 'Source Object type'.
  PERFORM get_domain_value USING 'RSSB_TLOGO_SRC' ls_source-tlogo
                           CHANGING lw_domval.
  ls_data-f2-textline = lw_domval.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Source Name'.
  ls_data-f2-textline = ls_source-objnm.
  APPEND ls_data TO lt_data.

* Target info
  CLEAR ls_data.
  ls_data-f1-textline = 'Target Object type'.
  PERFORM get_domain_value USING 'RSSB_TLOGO_TGT' ls_target-tlogo
                           CHANGING lw_domval.
  ls_data-f2-textline = lw_domval.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Target Name'.
  ls_data-f2-textline = ls_target-objnm.
  APPEND ls_data TO lt_data.

* Start routine
  CLEAR ls_data.
  ls_data-f1-textline = 'Start routine'.
  IF lt_abap_start_code IS INITIAL.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

* End routine
  CLEAR ls_data.
  ls_data-f1-textline = 'End routine'.
  IF lt_abap_end_code IS INITIAL.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

* Epert routine
  CLEAR ls_data.
  ls_data-f1-textline = 'Expert routine'.
  IF ls_transf-expert IS INITIAL.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.


* Display ABAP global declaration
  IF NOT lt_abap_global IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'ABAP Global declaration'
        line_style = cs_custo-style_title3.
    REFRESH lt_code.
    LOOP AT lt_abap_global INTO ls_abap_code.
      APPEND ls_abap_code-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDIF.

  IF NOT lt_abap_global2 IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'ABAP Global declaration 2'
        line_style = cs_custo-style_title3.
    REFRESH lt_code.
    LOOP AT lt_abap_global2 INTO ls_abap_code.
      APPEND ls_abap_code-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDIF.

  IF NOT lt_abap_start_code IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'ABAP Start routine'
        line_style = cs_custo-style_title3.
    REFRESH lt_code.
    LOOP AT lt_abap_start_code INTO ls_abap_code.
      APPEND ls_abap_code-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDIF.

  IF NOT lt_abap_end_code IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'ABAP End routine'
        line_style = cs_custo-style_title3.
    REFRESH lt_code.
    LOOP AT lt_abap_end_code INTO ls_abap_code.
      APPEND ls_abap_code-line TO lt_code.
    ENDLOOP.
    PERFORM code_display USING lt_code.
  ENDIF.

* Transformation rules
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Transformation rules'
      line_style = cs_custo-style_title3.

  REFRESH lt_tab.
  CLEAR ls_tab.
  ls_tab-f1-textline = 'Position'.
  ls_tab-f2-textline = 'Source Object'.
  ls_tab-f3-textline = 'Rule Type'.
  ls_tab-f4-textline = 'Rule Name'.
  ls_tab-f5-textline = 'Target Object'.
  ls_tab-f6-textline = 'Description'.
  APPEND ls_tab TO lt_tab.
  CLEAR lw_position.
  CLEAR lw_group.
  LOOP AT lt_tranrule INTO ls_tranrule.
    CALL METHOD ls_tranrule-r_rule->get_info
      IMPORTING
        e_s_ruleinfo      = ls_ruleinfo
        e_t_source_fields = lt_sourcemap
        e_t_rulesteps     = lt_rulesteps
        e_s_target_field  = ls_targetfield
        e_txtlg           = lw_ruletxt.

    SORT lt_rulesteps BY stepid.
    READ TABLE lt_rulesteps INDEX 1 INTO ls_rulesteps.

* Skip start & end routine
    IF ls_ruleinfo-ruletype = 'START' OR ls_ruleinfo-ruletype = 'END'.
      CONTINUE.
    ENDIF.

* Add line for rule group
    IF lw_group NE ls_ruleinfo-groupid AND lw_groups GT 1.
      CLEAR lw_position.
      CLEAR lw_groupname.
      lw_group = ls_ruleinfo-groupid.
      CLEAR ls_tab.
      READ TABLE lt_group INTO ls_group WITH KEY groupid = lw_group.
      IF sy-subrc = 0.
        lw_groupname = ls_group-r_group->get_txt( ).
        CONCATENATE 'Rule group:' lw_groupname
                    INTO lw_groupname SEPARATED BY space.
* For herarchy, get segment
        IF lw_segments GT 1.
          CLEAR : ls_sourceseg,
                  ls_segmentt.
          lt_sourceseg = ls_group-r_group->get_source_segments( ).
          READ TABLE lt_sourceseg INTO ls_sourceseg INDEX 1.
          IF sy-subrc = 0.
            READ TABLE lt_segmentt INTO ls_segmentt
                       WITH KEY segid = ls_sourceseg-segid.
            IF sy-subrc NE 0.
              CONCATENATE '(segment:' ls_sourceseg-segid ')'
                          INTO ls_segmentt-txtlg.
            ELSE.
              CONCATENATE '(' ls_segmentt-txtsh ')'
                          INTO ls_segmentt-txtlg.
            ENDIF.
          ENDIF.
          CONCATENATE lw_groupname ls_segmentt-txtlg
                      INTO lw_groupname SEPARATED BY space.
        ENDIF.
      ENDIF.
      ls_tab-f1-textline = lw_groupname.
      ls_tab-f1-merge = 6.
      APPEND ls_tab TO lt_tab.
    ENDIF.
    ADD 1 TO lw_position.

    CLEAR ls_tab.
    ls_tab-f1-textline = lw_position.
    CONDENSE ls_tab-f1-textline NO-GAPS.

** Zone source
    CASE ls_ruleinfo-ruletype.
      WHEN 'CONSTANT'.
        ls_tab-f2-textline = '-'.
      WHEN 'EXPERT'.
        ls_tab-f2-textline = '-'.
      WHEN OTHERS.
        LOOP AT lt_sourcemap INTO ls_sourcemap.
          IF ls_tab-f2-textline IS INITIAL.
            IF ls_sourcemap-iobjnm IS INITIAL.
              ls_tab-f2-textline = ls_sourcemap-fieldnm.
            ELSE.
              ls_tab-f2-textline = ls_sourcemap-iobjnm.
            ENDIF.
          ELSE.
            IF ls_sourcemap-iobjnm IS INITIAL.
              CONCATENATE ls_tab-f2-textline ls_sourcemap-fieldnm
                          INTO ls_tab-f2-textline SEPARATED BY ', '.
            ELSE.
              CONCATENATE ls_tab-f2-textline ls_sourcemap-iobjnm
                          INTO ls_tab-f2-textline SEPARATED BY ', '.
            ENDIF.
          ENDIF.
        ENDLOOP.
    ENDCASE.

    CASE ls_ruleinfo-ruletype.
* Direct assignment
      WHEN 'DIRECT' OR 'TIME'.
        ls_tab-f3-textline = 'Direct assignment'.
        ls_tab-f4-textline = '-'.

* Expert routine
      WHEN 'EXPERT'.
        ls_tab-f3-textline = 'Expert routine'.
        ls_tab-f4-textline = lw_ruletxt.
        CLEAR ls_routine_tbd.
        ls_routine_tbd-routine ?= ls_rulesteps-r_rulestep.
        APPEND ls_routine_tbd TO lt_routine_tbd.
* ABAP Routine
      WHEN 'ROUTINE'.
        ls_tab-f3-textline = 'Routine'.
        ls_tab-f4-textline = lw_ruletxt.
        CLEAR ls_routine_tbd.
        IF NOT lw_groupname IS INITIAL.
          CONCATENATE ls_targetfield-iobjnm ' [' lw_groupname ']'
                      INTO ls_routine_tbd-target RESPECTING BLANKS.
        ELSE.
          IF ls_targetfield-iobjnm IS INITIAL.
            ls_routine_tbd-target = ls_targetfield-fieldnm.
          ELSE.
            ls_routine_tbd-target = ls_targetfield-iobjnm.
          ENDIF.
        ENDIF.
        ls_routine_tbd-routine ?= ls_rulesteps-r_rulestep.
        APPEND ls_routine_tbd TO lt_routine_tbd.
* Constant
      WHEN 'CONSTANT'.
        lo_constant ?= ls_rulesteps-r_rulestep.
        CALL METHOD lo_constant->get_constant
          IMPORTING
            e_constant = lw_constant_val.
        ls_tab-f3-textline = 'Constant'.
        ls_tab-f4-textline = lw_constant_val.

* Derivation
      WHEN 'MASTER'.
        lo_master ?= ls_rulesteps-r_rulestep.
        CALL METHOD lo_master->get_source_field
          IMPORTING
            e_s_source_field = ls_source_field.
        ls_tab-f3-textline = 'Read Master Data'.
        ls_tab-f4-textline = ls_source_field-iobjnm.
* Formula
      WHEN 'FORMULA'.
        ls_tab-f3-textline = 'Formula'.
        ls_tab-f4-textline = lw_ruletxt.
        CLEAR ls_formula_tbd.
        IF NOT lw_groupname IS INITIAL.
          CONCATENATE ls_targetfield-iobjnm ' [' lw_groupname ']'
                      INTO ls_routine_tbd-target RESPECTING BLANKS.
        ELSE.
          ls_routine_tbd-target = ls_targetfield-iobjnm.
        ENDIF.
        ls_formula_tbd-formula ?= ls_rulesteps-r_rulestep.
        APPEND ls_formula_tbd TO lt_formula_tbd.
* Not yet managed : Read DSO
      WHEN OTHERS.
        ls_tab-f3-textline = ls_ruleinfo-ruletype.
        ls_tab-f4-textline = 'Rule'.
    ENDCASE.

    IF ls_targetfield-iobjnm IS INITIAL.
      ls_tab-f5-textline = ls_targetfield-fieldnm.
    ELSE.
      ls_tab-f5-textline = ls_targetfield-iobjnm.
    ENDIF.
    ls_tab-f6-textline = ls_targetfield-txtlg.
    APPEND ls_tab TO lt_tab.
  ENDLOOP.
  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_tab
      style   = cs_custo-table_with_head.

* Display individual routines
  LOOP AT lt_routine_tbd INTO ls_routine_tbd.
    REFRESH lt_abap_start_code.
    IF lt_abap_global IS INITIAL AND lt_abap_global2 IS INITIAL.
      CALL METHOD ls_routine_tbd-routine->get_code
        IMPORTING
          e_t_routine_source = lt_abap_start_code
          e_t_global_source  = lt_abap_global
          e_t_global_source2 = lt_abap_global2.
      IF NOT lt_abap_global IS INITIAL.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline   = 'ABAP Global declaration'
            line_style = cs_custo-style_title3.
        REFRESH lt_code.
        LOOP AT lt_abap_global INTO ls_abap_code.
          APPEND ls_abap_code-line TO lt_code.
        ENDLOOP.
        PERFORM code_display USING lt_code.
      ENDIF.

      IF NOT lt_abap_global2 IS INITIAL.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline   = 'ABAP Global declaration 2'
            line_style = cs_custo-style_title3.
        REFRESH lt_code.
        LOOP AT lt_abap_global2 INTO ls_abap_code.
          APPEND ls_abap_code-line TO lt_code.
        ENDLOOP.
        PERFORM code_display USING lt_code.
      ENDIF.
    ELSE.
      CALL METHOD ls_routine_tbd-routine->get_code
        IMPORTING
          e_t_routine_source = lt_abap_start_code.
    ENDIF.

    IF NOT lt_abap_start_code IS INITIAL.
      IF ls_routine_tbd-target IS INITIAL.
        lw_texte = 'Expert routine'.
      ELSE.
        CONCATENATE 'Routine' ls_routine_tbd-target
                    INTO lw_texte SEPARATED BY space.
      ENDIF.

      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = lw_texte
          line_style = cs_custo-style_title3.
      REFRESH lt_code.
      LOOP AT lt_abap_start_code INTO ls_abap_code.
        APPEND ls_abap_code-line TO lt_code.
      ENDLOOP.
      PERFORM code_display USING lt_code.
    ENDIF.
  ENDLOOP.

* Display Formulas
  LOOP AT lt_formula_tbd INTO ls_formula_tbd.

    CONCATENATE 'Formula' ls_formula_tbd-target
                INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title3.

    lw_texte = ls_formula_tbd-formula->get_formula_as_string( ).
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_code.

  ENDLOOP.

ENDFORM.                    " TRSF

*&---------------------------------------------------------------------*
*&      Form  ISOURCE7
*&---------------------------------------------------------------------*
*       Display documentation for Infosource 7x
*----------------------------------------------------------------------*
*      -->FW_ISOURCE Infosource
*----------------------------------------------------------------------*
FORM isource7 USING fw_isource TYPE string.

  DATA : BEGIN OF ls_isource_detail,
           isource TYPE rsksnew-isource,
           applnm  TYPE rsksnew-applnm,
           txtlg   TYPE rsksnewt-txtlg,
         END OF ls_isource_detail,
         BEGIN OF ls_isource_fields,
           iobjnm     TYPE rsksfieldnew-iobjnm,
           keyflag    TYPE rsksfieldnew-keyflag,
           unifieldnm TYPE rsksfieldnew-unifieldnm,
           convexit   TYPE rsksfieldnew-convexit,
           posit      TYPE rsksfieldnew-posit,
         END OF ls_isource_fields,
         lt_isource_fields LIKE TABLE OF ls_isource_fields,
         BEGIN OF ls_iobj,
           iobjnm TYPE rsdiobjt-iobjnm,
           txtlg  TYPE rsdiobjt-txtlg,
         END OF ls_iobj,
         lt_iobj LIKE TABLE OF ls_iobj.

  DATA : BEGIN OF ls_com,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
           f5 TYPE cl_word=>ty_table_style_field,
           f6 TYPE cl_word=>ty_table_style_field,
         END OF ls_com,
         lt_com   LIKE TABLE OF ls_com,
         lw_texte TYPE string.

  ls_isource_detail-isource = fw_isource.
  IF w_skip = space.
    PERFORM object_progress_bar USING fw_isource c_is7
                                      'Writing infosource info...'(m07).
  ENDIF.


  IF w_skip = space.

    SELECT SINGLE applnm FROM rsksnew
           INTO ls_isource_detail-applnm
           WHERE isource = ls_isource_detail-isource
           AND objvers = c_objvers_active.
    SELECT SINGLE txtlg FROM rsksnewt
           INTO ls_isource_detail-txtlg
           WHERE isource = ls_isource_detail-isource
           AND objvers = c_objvers_active
           AND langu = c_lang_default.
    IF sy-subrc NE 0.
      SELECT SINGLE txtlg FROM rsksnewt
             INTO ls_isource_detail-txtlg
             WHERE isource = ls_isource_detail-isource
             AND objvers = c_objvers_active
             AND langu = c_lang_default.
    ENDIF.
    SELECT iobjnm keyflag unifieldnm convexit posit
           FROM rsksfieldnew
           INTO TABLE lt_isource_fields
           WHERE isource = ls_isource_detail-isource
           AND objvers = c_objvers_active.
    IF NOT lt_isource_fields IS INITIAL.
      SELECT iobjnm txtlg
             INTO TABLE lt_iobj
             FROM rsdiobjt
             FOR ALL ENTRIES IN lt_isource_fields
             WHERE iobjnm = lt_isource_fields-iobjnm
             AND objvers = c_objvers_active
             AND langu = c_lang_default.
      SORT lt_iobj BY iobjnm.
    ENDIF.

    IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
      CALL METHOD o_doc->write_newpage.
    ENDIF.

    CONCATENATE 'Infosource' ls_isource_detail-isource
    INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title1.

    CONCATENATE 'Description:' ls_isource_detail-txtlg
    INTO lw_texte SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cl_word=>c_style_normal.

* Insert embbeded documents
    PERFORM special_note USING c_is7 fw_isource
                               cs_custo-style_title2.

* Do not display comm structure for direct infosource
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Communication structure'
        line_style = cs_custo-style_title2.

    REFRESH lt_com.
    CLEAR ls_com.
    ls_com-f1-textline = 'InfoObject'.
    ls_com-f2-textline = 'Description'.
    ls_com-f3-textline = 'Key'.
    ls_com-f4-textline = 'Unit'.
    ls_com-f5-textline = 'Conversion exit'.
    ls_com-f6-textline = 'Position'.
    APPEND ls_com TO lt_com.

    SORT lt_isource_fields BY posit.

    LOOP AT lt_isource_fields INTO ls_isource_fields.
      CLEAR ls_com.
      ls_com-f1-textline = ls_isource_fields-iobjnm.
      READ TABLE lt_iobj INTO ls_iobj WITH KEY iobjnm = ls_isource_fields-iobjnm.
      ls_com-f2-textline = ls_iobj-txtlg.
      IF ls_isource_fields-keyflag = space.
        ls_com-f3-textline = cl_word=>c_symbol_checkbox.
      ELSE.
        ls_com-f3-textline = cl_word=>c_symbol_checkbox_checked.
      ENDIF.
      ls_com-f3-style_effect-font = cl_word=>c_font_symbol.
      ls_com-f4-textline = ls_isource_fields-unifieldnm.
      ls_com-f5-textline = ls_isource_fields-convexit.
      ls_com-f6-textline = ls_isource_fields-posit.
      APPEND ls_com TO lt_com.
    ENDLOOP.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_com
        style   = cs_custo-table_with_head.


  ENDIF.

* Add transformation
  PERFORM trsf_list USING ls_isource_detail-isource c_is7.

ENDFORM.                    " ISOURCE7

*&---------------------------------------------------------------------*
*&      Form  WB
*&---------------------------------------------------------------------*
*       Display documentation for workbook
*----------------------------------------------------------------------*
*      -->FW_WB  Workbook ID
*----------------------------------------------------------------------*
FORM wb USING fw_wb TYPE string.
  DATA : BEGIN OF ls_query,
           compid   TYPE rsrrepdir-compid,
           txtlg    TYPE rszelttxt-txtlg,
           infocube TYPE rsrrepdir-infocube,
           type     TYPE rstlogo,
         END OF ls_query,
         lt_query      LIKE TABLE OF ls_query,
         ls_query_last LIKE ls_query,
         lw_texte      TYPE string,
         BEGIN OF ls_tab,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
         END OF ls_tab,
         lt_tab    LIKE TABLE OF ls_tab,
         ls_object LIKE s_object.
  DATA : lw_imgurl    TYPE string,
         ls_linestyle TYPE cl_word=>ty_paragraph_style_effect,
         lw_wb_title  TYPE rsrwbindext-title.

  PERFORM object_progress_bar USING fw_wb c_wb
                                    'Writing workbook info...'(m13).

* Get list of Queries
  SELECT t4~compid
         t5~txtlg
         t4~infocube
         FROM rsrworkbook AS t3
         INNER JOIN rsrrepdir AS t4
         ON ( t3~genuniid = t4~genuniid AND t3~objvers = t4~objvers )
         INNER JOIN rszelttxt AS t5
         ON  ( t4~compuid = t5~eltuid AND t3~objvers = t5~objvers )
         INTO TABLE lt_query
         WHERE t3~workbookid = fw_wb
         AND t3~objvers = c_objvers_active.

* Get workbook title
  SELECT SINGLE title INTO lw_wb_title
         FROM rsrwbindext
         WHERE workbookid = fw_wb
         AND langu = c_lang_default.

* Flowmap for workbook
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Data flow'
      line_style = cs_custo-style_title2.

  SORT lt_query BY infocube.
  CLEAR ls_query_last.
  LOOP AT lt_query INTO ls_query.
    IF ls_query-infocube = ls_query_last-infocube.
      ls_query-type = ls_query_last-type.
      MODIFY lt_query FROM ls_query.
      CONTINUE.
    ENDIF.
    ls_query_last = ls_query.

* Determine infoprovider type
    PERFORM get_iprov_type USING ls_query-infocube
                           CHANGING ls_query-type.

    IF ls_query-type IS INITIAL.
      CONTINUE. "unknown object ?
    ENDIF.

* Save infoprovider type
    MODIFY lt_query FROM ls_query.
    ls_query_last-type = ls_query-type.

    PERFORM get_dataflow USING ls_query-infocube ls_query-type
                         CHANGING lw_imgurl.

    lw_texte = ls_query-infocube.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title3.

    o_doc->insert_image( url = lw_imgurl ).
    CLEAR ls_linestyle.
    ls_linestyle-alignment = cl_word=>c_align_center.
    CALL METHOD o_doc->write_line
      EXPORTING
        style_effect = ls_linestyle.
  ENDLOOP.

  IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
    CALL METHOD o_doc->write_newpage.
  ENDIF.

* Workbook title
  CONCATENATE 'Workbook' lw_wb_title
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Insert embbeded documents
  PERFORM special_note USING c_wb fw_wb
                             cs_custo-style_title2.

* List of queries in workbook
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'List of queries used'
      line_style = cs_custo-style_title2.

  REFRESH lt_tab.
  CLEAR ls_tab.
  ls_tab-f1 = 'Query ID'.
  ls_tab-f2 = 'Query Description'.
  ls_tab-f3 = 'Infoprovider'.
  ls_tab-f4 = 'Provider Type'.
  APPEND ls_tab TO lt_tab.

  SORT lt_query BY compid.
  LOOP AT lt_query INTO ls_query.
    CLEAR ls_tab.
    ls_tab-f1 = ls_query-compid.
    ls_tab-f2 = ls_query-txtlg.
    ls_tab-f3 = ls_query-infocube.
    CASE ls_query-type.
      WHEN c_iobj
      OR c_cube
      OR c_iset.
        ls_tab-f4 = ls_query-type.
      WHEN c_dso.
        ls_tab-f4 = 'DSO'.
      WHEN c_multi.
        ls_tab-f4 = 'MULTI'.
      WHEN c_oh.
        ls_tab-f4 = 'OPENHUB'.
    ENDCASE.
    APPEND ls_tab TO lt_tab.

    CLEAR ls_object.
    ls_object-objtype = c_query.
    ls_object-object = ls_query-compid.
    PERFORM add_object_to_queue USING ls_object.
  ENDLOOP.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_tab
      style   = cs_custo-table_with_head.

ENDFORM.                    " WB

*&---------------------------------------------------------------------*
*&      Form WAD
*&---------------------------------------------------------------------*
*       Display documentation for Bex Web Template (WAD)
*----------------------------------------------------------------------*
*      -->FW_WAD  Bex Web Template Name
*----------------------------------------------------------------------*
FORM wad USING fw_wad TYPE string.
  DATA : BEGIN OF ls_query,
           compid   TYPE rsrrepdir-compid,
           txtlg    TYPE rszelttxt-txtlg,
           infocube TYPE rsrrepdir-infocube,
           type     TYPE rstlogo,
         END OF ls_query,
         lt_query      LIKE TABLE OF ls_query,
         ls_query_last LIKE ls_query,
         lw_texte      TYPE string,
         BEGIN OF ls_tab,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
         END OF ls_tab,
         lt_tab    LIKE TABLE OF ls_tab,
         ls_object LIKE s_object.
  DATA : lw_imgurl    TYPE string,
         ls_linestyle TYPE cl_word=>ty_paragraph_style_effect,
         lw_wad_title TYPE rszwbtmpheadtxt-txtlg.

  PERFORM object_progress_bar USING fw_wad c_wad
                                    'Writing WAD info...'(m16).

* Get list of Queries
  SELECT t4~compid
         t5~txtlg
         t4~infocube
         FROM rszwbtmpxref   AS t3
         INNER JOIN rsrrepdir AS t4
         ON ( t3~objnm = t4~compuid AND t3~objvers = t4~objvers )
         INNER JOIN rszelttxt AS t5
         ON  ( t4~compuid = t5~eltuid AND t3~objvers = t5~objvers )
         INTO TABLE lt_query
         WHERE t3~objid = fw_wad
         AND t3~objvers = c_objvers_active
         AND t3~tlogo = c_query.

* Get WAD title
  SELECT SINGLE txtlg INTO lw_wad_title
         FROM rszwbtmpheadtxt
         WHERE objid = fw_wad
         AND objvers = c_objvers_active
         AND langu = c_lang_default.

* Flowmap for wad
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Data flow'
      line_style = cs_custo-style_title2.

  SORT lt_query BY infocube.
  CLEAR ls_query_last.
  LOOP AT lt_query INTO ls_query.
    IF ls_query-infocube = ls_query_last-infocube.
      ls_query-type = ls_query_last-type.
      MODIFY lt_query FROM ls_query.
      CONTINUE.
    ENDIF.
    ls_query_last = ls_query.

* Determine infoprovider type
    PERFORM get_iprov_type USING ls_query-infocube
                           CHANGING ls_query-type.


    IF ls_query-type IS INITIAL.
      CONTINUE. "unknown object ?
    ENDIF.

* Save infoprovider type
    MODIFY lt_query FROM ls_query.
    ls_query_last-type = ls_query-type.

    PERFORM get_dataflow USING ls_query-infocube ls_query-type
                         CHANGING lw_imgurl.

    lw_texte = ls_query-infocube.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title3.

    o_doc->insert_image( url = lw_imgurl ).
    CLEAR ls_linestyle.
    ls_linestyle-alignment = cl_word=>c_align_center.
    CALL METHOD o_doc->write_line
      EXPORTING
        style_effect = ls_linestyle.
  ENDLOOP.

  IF NOT cs_custo-force_pagebreak_title1 IS INITIAL.
    CALL METHOD o_doc->write_newpage.
  ENDIF.

* WAD title
  CONCATENATE 'Bex Web Template' lw_wad_title
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Insert embbeded documents
  PERFORM special_note USING c_wad fw_wad
                             cs_custo-style_title2.

* List of queries in the wad
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'List of queries used'
      line_style = cs_custo-style_title2.

  REFRESH lt_tab.
  CLEAR ls_tab.
  ls_tab-f1 = 'Query ID'.
  ls_tab-f2 = 'Query Description'.
  ls_tab-f3 = 'Infoprovider'.
  ls_tab-f4 = 'Provider Type'.
  APPEND ls_tab TO lt_tab.

  SORT lt_query BY compid.
  LOOP AT lt_query INTO ls_query.
    CLEAR ls_tab.
    ls_tab-f1 = ls_query-compid.
    ls_tab-f2 = ls_query-txtlg.
    ls_tab-f3 = ls_query-infocube.
    CASE ls_query-type.
      WHEN c_iobj
      OR c_cube
      OR c_iset.
        ls_tab-f4 = ls_query-type.
      WHEN c_dso.
        ls_tab-f4 = 'DSO'.
      WHEN c_multi.
        ls_tab-f4 = 'MULTI'.
      WHEN c_oh.
        ls_tab-f4 = 'OPENHUB'.
    ENDCASE.
    APPEND ls_tab TO lt_tab.

    CLEAR ls_object.
    ls_object-objtype = c_query.
    ls_object-object = ls_query-compid.
    PERFORM add_object_to_queue USING ls_object.
  ENDLOOP.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_tab
      style   = cs_custo-table_with_head.

ENDFORM.                    " WAD

*&---------------------------------------------------------------------*
*&      Form QUERY
*&---------------------------------------------------------------------*
*       Display documentation for Query
*----------------------------------------------------------------------*
*      -->FW_QUERY  Query name
*----------------------------------------------------------------------*
FORM query USING fw_query TYPE string.
  DATA : lw_texte    TYPE string,
         lw_xml      TYPE string,
         lw_xml_frag TYPE string,
         lw_tab      TYPE string,
         ls_object   LIKE s_object,
         lw_compuid  TYPE sysuuid_25,
         lw_compid   TYPE rszcompid,
         lw_subrc    TYPE sysubrc,
         ls_compic   TYPE rsz_x_compic,
         lt_compic   LIKE TABLE OF ls_compic,
         ls_eltdir   TYPE rsz_x_eltdir,
         lt_eltdir   LIKE TABLE OF ls_eltdir,
         ls_var      TYPE rsz_x_var,
         lt_var      LIKE TABLE OF ls_var,
         ls_select   TYPE rsz_x_select,
         lt_select   LIKE TABLE OF ls_select,
         ls_xref     TYPE rsz_x_eltxref,
         lt_xref     LIKE TABLE OF ls_xref,
         ls_range    TYPE rsz_x_range,
         ls_range2   LIKE ls_range,
         lt_range    LIKE TABLE OF ls_range,
         ls_prop     TYPE rsz_x_eltprop,
         lt_prop     LIKE TABLE OF ls_prop,
         ls_attr     TYPE rsz_x_eltattr,
         lt_attr     LIKE TABLE OF ls_attr,
         lt_compdir  TYPE rsza_t_compdir,
         lw_eltid    LIKE ls_eltdir-eltuid,
         lt_cells    TYPE rsza_t_cel,
         lw_laytp    LIKE ls_xref-laytp,
         lo_dta      TYPE REF TO cl_rsd_dta,
         ls_dta      TYPE rsd_s_dta,
         BEGIN OF ls_infoarea,
           infoarea   TYPE rsdareav-infoarea,
           txtlg      TYPE rsdareav-txtlg,
           infoarea_p TYPE rsdareav-infoarea_p,
         END OF ls_infoarea,
         lt_infoarea LIKE TABLE OF ls_infoarea,
         lw_filter   TYPE c.
  DATA : BEGIN OF ls_node,
           hier   TYPE rsz_x_eltdir-eltuid,
           id     TYPE rsz_x_eltdir-eltuid,
           parent TYPE rsz_x_eltdir-eltuid,
           order  TYPE i,
           level  TYPE i,
         END OF ls_node,
         lt_node  LIKE TABLE OF ls_node,
         lw_order TYPE i.
  FIELD-SYMBOLS <fs> LIKE ls_node.
  DATA : BEGIN OF ls_data,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_list,
           f1 TYPE string,
         END OF ls_list,
         lt_list LIKE TABLE OF ls_list.


  PERFORM object_progress_bar USING fw_query c_query
                                    'Writing Query info...'(m17).
  lw_compid = fw_query.
  CALL FUNCTION 'RSZ_X_COMPONENT_GET'
    EXPORTING
*     I_GENUNIID        =
      i_compid          = lw_compid
*     I_COMPUID         =
*     I_OBJVERS         = 'A'
*     I_WITH_TEMPLATES  = ' '
*     I_BY_INFOCUBE     =
*     I_TEMPLATE_TYPE   = 'NIL'
*     I_VARIABLE_TYPES  =
*     I_VARIABLE_INFOOBJECT       =
*     I_LANGUAGE        = SY-LANGU
*     I_USE_BUFFER      =
*     I_QD_VERSION      = ' '
      i_designtime_call = space "RS_C_TRUE
    IMPORTING
      e_compuid         = lw_compuid
      e_subrc           = lw_subrc
*     E_BACKUP_EXISTS   =
    TABLES
      c_t_eltdir        = lt_eltdir
*     C_T_ELTTXT_UI     =
      c_t_eltprop       = lt_prop
*     C_T_ELTPRIO       =
*     C_T_ELTPRIO_2     =
      c_t_eltattr       = lt_attr
      c_t_eltxref       = lt_xref
      c_t_compdir       = lt_compdir
      c_t_compic        = lt_compic
      c_t_select        = lt_select
      c_t_range         = lt_range
*     C_T_CALC          =
      c_t_cell          = lt_cells
      c_t_var           = lt_var
*     C_T_UID_SERVER    =
*     C_T_ELTTXT        =
*     E_T_HIER_INFO     =
    .
  IF lw_subrc NE 0.
    MESSAGE 'Erreur avec la query' && fw_query TYPE 'E'.
  ENDIF.

* Read query main information
  READ TABLE lt_compic INTO ls_compic WITH KEY compuid = lw_compuid.

* Source infoprovider informations
  CALL METHOD cl_rsd_dta=>factory
    EXPORTING
      i_infoprov = ls_compic-infocube
    RECEIVING
      r_r_dta    = lo_dta
    EXCEPTIONS
      not_found  = 1
      OTHERS     = 2.
  IF sy-subrc = 0.
    CALL METHOD lo_dta->if_rsd_dta~dta_get_info
      IMPORTING
        e_s_dta         = ls_dta
      EXCEPTIONS
        dta_not_found   = 1
        iobj_not_found  = 2
        objvers_invalid = 3
        OTHERS          = 4.
  ENDIF.

* Query title
  CONCATENATE 'Query' fw_query
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Insert embbeded documents
  PERFORM special_note USING c_query lw_compuid
                             cs_custo-style_title2.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title2.

  REFRESH lt_data.
  CLEAR ls_data.
  READ TABLE lt_eltdir INTO ls_eltdir WITH KEY eltuid = lw_compuid.
  ls_data-f1-textline = 'Description'.
  ls_data-f2-textline = ls_eltdir-txtlg.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Internal Unique ID'.
  ls_data-f2-textline = lw_compuid.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  CLEAR ls_object.
  ls_data-f1-textline = 'Source'.
  CASE ls_dta-tlogo.
    WHEN c_cube.
      CONCATENATE 'Cube' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      ls_object-objtype = c_cube.
    WHEN c_dso.
      CONCATENATE 'DSO' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      ls_object-objtype = c_dso.
    WHEN 'ALVL'.
      CONCATENATE 'Agregation Level' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      SELECT SINGLE infoprov INTO ls_compic-infocube
             FROM rspls_alvl
             WHERE aggrlevel = ls_compic-infocube
             AND objvers = c_objvers_active.
      CONCATENATE ls_data-f2-textline '(on' ls_compic-infocube
                  INTO ls_data-f2-textline
                  SEPARATED BY space.
      CONCATENATE ls_data-f2-textline ')'
                  INTO ls_data-f2-textline.
* Get cubes from infoprov used in multi
      SELECT SINGLE infocube cubetype
             INTO (ls_compic-infocube, ls_object-objtype)
             FROM rsdcube
             WHERE infocube = ls_compic-infocube
             AND objvers = c_objvers_active.
      IF sy-subrc = 0.
        IF ls_object-objtype = 'M'.
          ls_object-objtype = c_multi.
        ELSE.
          ls_object-objtype = c_cube.
        ENDIF.
      ELSE.
* Get DSO from infoprov used in multi
        SELECT SINGLE odsobject INTO ls_compic-infocube
               FROM rsdodso
               WHERE odsobject = ls_compic-infocube
               AND objvers = c_objvers_active.
        IF sy-subrc = 0.
          ls_object-objtype = c_dso.
        ELSE.
* Get MD from infoprov used in multi
          SELECT SINGLE iobjnm INTO ls_compic-infocube
                 FROM rsdiobj
                 WHERE iobjnm = ls_compic-infocube
                 AND objvers = c_objvers_active.
          IF sy-subrc = 0.
            ls_object-objtype = c_iobj.
          ENDIF.
        ENDIF.
      ENDIF.
    WHEN c_iobj.
      CONCATENATE 'Info object' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      ls_object-objtype = c_iobj.
    WHEN c_multi.
      CONCATENATE 'Multiprovider' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      ls_object-objtype = c_multi.
    WHEN c_iset.
      CONCATENATE 'Infoset' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      ls_object-objtype = c_iset.
    WHEN c_oh.
      CONCATENATE 'OpenHub Destination' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
      ls_object-objtype = c_oh.
    WHEN OTHERS.
      CONCATENATE 'Infoprovider' ls_compic-infocube
              INTO ls_data-f2-textline SEPARATED BY space.
  ENDCASE.
  APPEND ls_data TO lt_data.

  IF NOT ls_object-objtype IS INITIAL.
    ls_object-object = ls_compic-infocube.
    PERFORM add_object_to_queue USING ls_object.
  ENDIF.

* Infoarea tree
  CLEAR lw_texte.
  CLEAR lw_xml.
  CLEAR lw_xml_frag.
  IF NOT ls_dta-infoarea IS INITIAL.
    ls_infoarea-infoarea = ls_dta-infoarea.
    DO.
      IF ls_infoarea-infoarea IS INITIAL.
        EXIT. "exit do
      ENDIF.
      SELECT SINGLE infoarea txtlg infoarea_p
             FROM rsdareav
             INTO ls_infoarea
             WHERE infoarea = ls_infoarea-infoarea
             AND objvers = 'A'
             AND langu = c_lang_default.
      IF sy-subrc NE 0.
        EXIT. "exit do
      ENDIF.
      INSERT ls_infoarea INTO lt_infoarea INDEX 1.
      ls_infoarea-infoarea = ls_infoarea-infoarea_p.
    ENDDO.
    LOOP AT lt_infoarea INTO ls_infoarea.
      IF NOT lw_xml IS INITIAL.
        CALL METHOD o_doc->write_break CHANGING virtual = lw_xml.
      ENDIF.
      CONCATENATE lw_tab ls_infoarea-txtlg INTO lw_texte.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_texte
        IMPORTING
          virtual  = lw_xml_frag.
      CONCATENATE lw_xml lw_xml_frag INTO lw_xml.
      IF lw_tab IS INITIAL.
        CONCATENATE '+' cl_abap_char_utilities=>horizontal_tab INTO lw_tab.
      ELSE.
        CONCATENATE cl_abap_char_utilities=>horizontal_tab lw_tab INTO lw_tab.
      ENDIF.
    ENDLOOP.
    IF NOT lw_xml IS INITIAL.
      CALL METHOD o_doc->write_line
        CHANGING
          virtual = lw_xml.
    ENDIF.
    CLEAR ls_data.
    ls_data-f1-textline = 'Info Area'.
    ls_data-f2-xml = lw_xml.
    APPEND ls_data TO lt_data.
  ENDIF.

* Variable sequence
  CLEAR lw_texte.
  CLEAR lw_xml.
  CLEAR lw_xml_frag.
  LOOP AT lt_var INTO ls_var WHERE varinput = 'X'.
    READ TABLE lt_eltdir INTO ls_eltdir
                         WITH KEY eltuid = ls_var-varuniid.
    IF sy-subrc NE 0.
      CLEAR ls_eltdir.
    ENDIF.
    IF NOT lw_xml IS INITIAL.
      CALL METHOD o_doc->write_break CHANGING virtual = lw_xml.
    ENDIF.
    CONCATENATE '[' ls_var-vnam ']' ls_eltdir-txtlg INTO lw_texte.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline = lw_texte
      IMPORTING
        virtual  = lw_xml_frag.
    CONCATENATE lw_xml lw_xml_frag INTO lw_xml.
  ENDLOOP.
  IF NOT lw_xml IS INITIAL.
    CALL METHOD o_doc->write_line
      CHANGING
        virtual = lw_xml.
  ENDIF.
  CLEAR ls_data.
  ls_data-f1-textline = 'Variable sequence'.
  ls_data-f2-xml = lw_xml.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Filters'
      line_style = cs_custo-style_title2.

* Search filter object
  READ TABLE lt_xref INTO ls_xref
                     WITH KEY seltuid = lw_compuid
                              laytp = 'SOB'.
  lw_eltid = ls_xref-teltuid.
  REFRESH lt_data.
  LOOP AT lt_xref INTO ls_xref WHERE seltuid = lw_eltid
                               AND NOT posn IS INITIAL.
    READ TABLE lt_eltdir INTO ls_eltdir
                         WITH KEY eltuid = ls_xref-teltuid.
    READ TABLE lt_select INTO ls_select
                         WITH KEY eltuid = ls_xref-teltuid.
    CLEAR ls_data.
* For info object, long text is missing
    IF ls_eltdir-txtlg IS INITIAL.
      PERFORM get_iobj_text USING ls_select-iobjnm
                            CHANGING ls_eltdir-txtlg.
    ENDIF.
    CONCATENATE ls_eltdir-txtlg '['
                INTO ls_data-f1-textline SEPARATED BY space.
    CONCATENATE ls_data-f1-textline ls_select-iobjnm ']'
                INTO ls_data-f1-textline.
    CLEAR : lw_xml,
            lw_xml_frag.
    LOOP AT lt_range INTO ls_range WHERE eltuid = ls_xref-teltuid
                                   AND iobjnm = ls_select-iobjnm
                                   AND sotp = 1.
      IF NOT lw_xml IS INITIAL.
        CALL METHOD o_doc->write_break CHANGING virtual = lw_xml.
      ENDIF.
      CLEAR ls_eltdir.
      PERFORM get_range_text USING lt_eltdir[]
                                   lt_var[]
                                   lt_compdir[]
                                   ls_eltdir
                             CHANGING ls_range.
      PERFORM selopt_to_text USING space ls_range-sign ls_range-opt
                                   ls_range-lowtxtlg ls_range-hightxtlg
                             CHANGING lw_texte.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_texte
        IMPORTING
          virtual  = lw_xml_frag.
      CONCATENATE lw_xml lw_xml_frag INTO lw_xml.
    ENDLOOP.
    IF NOT lw_xml IS INITIAL.
      CALL METHOD o_doc->write_line
        CHANGING
          virtual = lw_xml.
      ls_data-f2-xml = lw_xml.
    ENDIF.
    APPEND ls_data TO lt_data.
  ENDLOOP.
  IF NOT lt_data IS INITIAL.
    CLEAR ls_data.
    ls_data-f1-textline = 'Object'.
    ls_data-f2-textline = 'Restriction'.
    INSERT ls_data INTO lt_data INDEX 1.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Characteristics Restriction'
        line_style = cs_custo-style_title3.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_with_head.
    lw_filter = abap_true.
  ELSE.
    lw_filter = space.
  ENDIF.

* Default values
  REFRESH lt_data.
  LOOP AT lt_xref INTO ls_xref WHERE seltuid = lw_eltid
                               AND posn IS INITIAL.
    CLEAR ls_data.

    PERFORM get_query_elem_lbl USING ls_xref-teltuid
                                     lt_eltdir[]
                                     lt_range[]
                                     lt_var[]
                                     lt_select[]
                                     lt_compdir[]
                               CHANGING lw_texte
                                        ls_eltdir.
    ls_data-f1-textline = lw_texte.

    READ TABLE lt_select INTO ls_select
                         WITH KEY eltuid = ls_xref-teltuid.

** Folllowing is replaced by PERFORM get_query_elem_lbl
*    READ TABLE lt_eltdir INTO ls_eltdir
*                         WITH KEY eltuid = ls_xref-teltuid.
** For info object, long text is missing
*    IF ls_eltdir-txtlg IS INITIAL.
*      IF ls_select-iobjnm IS INITIAL
*      AND ls_eltdir-defaulthint = '1KYFNM'.
*        ls_select-iobjnm = ls_eltdir-defaulthint.
*      ENDIF.
*
*      PERFORM get_iobj_text USING ls_select-iobjnm
*                            CHANGING ls_eltdir-txtlg.
*    ENDIF.
*    CONCATENATE ls_eltdir-txtlg '['
*                INTO ls_data-f1-textline SEPARATED BY space.
*    CONCATENATE ls_data-f1-textline ls_select-iobjnm ']'
*                INTO ls_data-f1-textline.

    CLEAR : lw_xml,
            lw_xml_frag.
    LOOP AT lt_range INTO ls_range WHERE eltuid = ls_xref-teltuid
                                   AND iobjnm = ls_select-iobjnm
                                   AND sotp = 2.
      IF NOT lw_xml IS INITIAL.
        CALL METHOD o_doc->write_break CHANGING virtual = lw_xml.
      ENDIF.
      CLEAR ls_eltdir.
      PERFORM get_range_text USING lt_eltdir[]
                                   lt_var[]
                                   lt_compdir[]
                                   ls_eltdir
                             CHANGING ls_range.
      PERFORM selopt_to_text USING space ls_range-sign ls_range-opt
                                   ls_range-lowtxtlg ls_range-hightxtlg
                             CHANGING lw_texte.

      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_texte
        IMPORTING
          virtual  = lw_xml_frag.
      CONCATENATE lw_xml lw_xml_frag INTO lw_xml.
    ENDLOOP.
* Do not keep "default value" without restriction
    IF sy-subrc NE 0 OR lw_xml IS INITIAL.
      CONTINUE.
    ENDIF.
    CALL METHOD o_doc->write_line
      CHANGING
        virtual = lw_xml.
    ls_data-f2-xml = lw_xml.
    APPEND ls_data TO lt_data.
  ENDLOOP.
  IF NOT lt_data IS INITIAL.
    CLEAR ls_data.
    ls_data-f1-textline = 'Object'.
    ls_data-f2-textline = 'Restriction'.
    INSERT ls_data INTO lt_data INDEX 1.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Default Values'
        line_style = cs_custo-style_title3.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_with_head.
  ELSEIF lw_filter = space.
* no filter nor default value, write -
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = '-'
        line_style = cl_word=>c_style_normal.
  ENDIF.

* xref posn is sometimes broken... have to redo the sort...
  LOOP AT lt_eltdir INTO ls_eltdir WHERE deftp = 'STR'.
    CLEAR ls_node.
    ls_node-hier = ls_eltdir-eltuid.
    LOOP AT lt_xref INTO ls_xref WHERE seltuid = ls_eltdir-eltuid.
      ls_node-id = ls_xref-teltuid.
      READ TABLE lt_prop INTO ls_prop WITH KEY eltuid = ls_xref-teltuid.
      IF sy-subrc = 0.
        ls_node-parent = ls_prop-parent.
      ENDIF.
      APPEND ls_node TO lt_node.
    ENDLOOP.
    lw_order = 1.
    DO.
      READ TABLE lt_node ASSIGNING <fs> WITH KEY order = 0
                                                 parent = ''.
      IF sy-subrc NE 0.
        EXIT. "exit do
      ENDIF.
      <fs>-order = lw_order.
      <fs>-level = 0.
      ADD 1 TO lw_order.
      PERFORM get_elmt_child USING 0
                             CHANGING lt_node[]
                                      <fs>-id
                                      lw_order.

    ENDDO.
  ENDLOOP.
  SORT lt_node BY order.

  DO 3 TIMES.
    CASE sy-index.
      WHEN 1.
        lw_texte = 'Rows'.
        lw_laytp = 'ROW'.
      WHEN 2.
        lw_texte = 'Columns'.
        lw_laytp = 'COL'.
      WHEN 3.
        lw_texte = 'Free characteristics'.
        lw_laytp = 'AGG'.
      WHEN OTHERS.
        CONTINUE.
    ENDCASE.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title2.

    REFRESH lt_list.
    READ TABLE lt_eltdir INTO ls_eltdir WITH KEY deftp = 'SHT'.
    IF sy-subrc NE 0.
      READ TABLE lt_eltdir INTO ls_eltdir WITH KEY deftp = 'REP'.
    ENDIF.
    IF sy-subrc NE 0.
      CONTINUE.
    ENDIF.
    lw_eltid = ls_eltdir-eltuid.
    LOOP AT lt_xref INTO ls_xref WHERE seltuid = lw_eltid
                                 AND laytp = lw_laytp.
      CLEAR ls_list.
      PERFORM get_query_elem_lbl USING ls_xref-teltuid
                                       lt_eltdir[]
                                       lt_range[]
                                       lt_var[]
                                       lt_select[]
                                       lt_compdir[]
                                 CHANGING lw_texte
                                          ls_eltdir.

      ls_list-f1 = lw_texte.
      APPEND ls_list TO lt_list.

* Structure : read components
      lw_eltid = ls_xref-teltuid.
      IF ls_eltdir-deftp = 'STR'.
        "LOOP AT lt_xref INTO ls_xref WHERE seltuid = lw_eltid.
        LOOP AT lt_node INTO ls_node WHERE hier = lw_eltid.

          PERFORM get_query_elem_lbl USING ls_node-id "ls_xref-teltuid
                                           lt_eltdir[]
                                           lt_range[]
                                           lt_var[]
                                           lt_select[]
                                           lt_compdir[]
                                     CHANGING lw_texte
                                              ls_eltdir.
          IF ls_eltdir IS INITIAL.
            CONTINUE.
          ENDIF.

          CLEAR ls_list.
          CONCATENATE '+' cl_abap_char_utilities=>horizontal_tab lw_texte
                      INTO lw_texte.

          IF NOT ls_node-level IS INITIAL.
            DO ls_node-level TIMES.
              CONCATENATE cl_abap_char_utilities=>horizontal_tab lw_texte
                          INTO lw_texte.
            ENDDO.
          ENDIF.
          ls_list-f1 = lw_texte.
          APPEND ls_list TO lt_list.
        ENDLOOP.
      ENDIF.

* Get attributes
      LOOP AT lt_attr INTO ls_attr WHERE eltuid = lw_eltid.
        CLEAR : ls_list,
                ls_eltdir-txtlg.

        PERFORM get_iobj_text USING ls_attr-attrinm
                            CHANGING ls_eltdir-txtlg.
        CONCATENATE '+' cl_abap_char_utilities=>horizontal_tab ls_eltdir-txtlg
                    INTO ls_eltdir-txtlg.
        CONCATENATE ls_eltdir-txtlg '[' INTO ls_list-f1 SEPARATED BY space.
        CONCATENATE ls_list-f1 ls_attr-attrinm ']' INTO ls_list-f1.
        APPEND ls_list TO lt_list.
      ENDLOOP.

    ENDLOOP.
    IF lt_list IS INITIAL.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = '-'
          line_style = cl_word=>c_style_normal.
    ELSE.
      CALL METHOD o_doc->write_table
        EXPORTING
          content = lt_list
          style   = cs_custo-table_without_head.
    ENDIF.
  ENDDO.

* Conditions
  REFRESH lt_data.
  SORT lt_xref BY posn flat_posn.
  LOOP AT lt_xref INTO ls_xref WHERE laytp = 'NIL' AND NOT posn IS INITIAL.
    READ TABLE lt_eltdir INTO ls_eltdir WITH KEY eltuid = ls_xref-teltuid.
    IF sy-subrc NE 0 OR ls_eltdir-subdeftp NE 'CON'.
      CONTINUE.
    ENDIF.
    CLEAR ls_data.
    IF ls_eltdir-defaulttext = 'X'.
      CONCATENATE 'Condition' ls_eltdir-defaulthint
                  INTO ls_data-f1-textline.
    ELSE.
      ls_data-f1-textline = ls_eltdir-txtlg.
    ENDIF.
    CLEAR ls_eltdir.
    CLEAR : lw_xml,
            lw_xml_frag.
    LOOP AT lt_range INTO ls_range WHERE eltuid = ls_xref-teltuid
                                   AND faciobjnm = '1STRUC'.

      READ TABLE lt_range INTO ls_range2
                          WITH KEY eltuid = ls_range-low.
      PERFORM get_range_text USING lt_eltdir[]
                                   lt_var[]
                                   lt_compdir[]
                                   ls_eltdir
                             CHANGING ls_range2.

      READ TABLE lt_range INTO ls_range
                          WITH KEY eltuid = ls_xref-teltuid
                                   term = ls_range-term
                                   faciobjnm = '1VALUE'.


      IF NOT lw_xml IS INITIAL.
        CALL METHOD o_doc->write_break CHANGING virtual = lw_xml.
      ENDIF.
      PERFORM get_range_text USING lt_eltdir[]
                                   lt_var[]
                                   lt_compdir[]
                                   ls_eltdir
                             CHANGING ls_range.
      PERFORM selopt_to_text USING ls_range2-lowtxtlg
                                   ls_range-sign ls_range-opt
                                   ls_range-lowtxtlg ls_range-hightxtlg
                             CHANGING lw_texte.

      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_texte
        IMPORTING
          virtual  = lw_xml_frag.
      CONCATENATE lw_xml lw_xml_frag INTO lw_xml.
    ENDLOOP.
    IF NOT lw_xml IS INITIAL.
      CALL METHOD o_doc->write_line
        CHANGING
          virtual = lw_xml.
      ls_data-f2-xml = lw_xml.
    ENDIF.
    APPEND ls_data TO lt_data.
  ENDLOOP.
  IF NOT lt_data IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Conditions'
        line_style = cs_custo-style_title2.
    CLEAR ls_data.
    ls_data-f1-textline = 'Name'.
    ls_data-f2-textline = 'Restrictions'.
    INSERT ls_data INTO lt_data INDEX 1.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_with_head.
  ENDIF.

* Exceptions
  REFRESH lt_data.
  LOOP AT lt_xref INTO ls_xref WHERE laytp = 'NIL' AND NOT posn IS INITIAL.
    READ TABLE lt_eltdir INTO ls_eltdir WITH KEY eltuid = ls_xref-teltuid.
    IF sy-subrc NE 0 OR ls_eltdir-subdeftp NE 'EXC'.
      CONTINUE.
    ENDIF.
    CLEAR ls_data.

* Get exception name
    IF ls_eltdir-defaulttext = 'X'.
      CONCATENATE 'Exception' ls_eltdir-defaulthint
                  INTO ls_data-f1-textline.
    ELSE.
      ls_data-f1-textline = ls_eltdir-txtlg.
    ENDIF.

* Get field to apply exception
    READ TABLE lt_range INTO ls_range
                        WITH KEY eltuid = ls_xref-teltuid
                                 faciobjnm = '1STRUC'.
    READ TABLE lt_range INTO ls_range2
                        WITH KEY eltuid = ls_range-low.
    PERFORM get_range_text USING lt_eltdir[]
                                 lt_var[]
                                 lt_compdir[]
                                 ls_eltdir
                           CHANGING ls_range2.
* Get exception values
    CLEAR : lw_xml,
            lw_xml_frag.
    LOOP AT  lt_range INTO ls_range
                      WHERE eltuid = ls_xref-teltuid
                      AND faciobjnm = '1VALUE'.
      IF lw_xml IS INITIAL.
        lw_texte = ls_range2-lowtxtlg.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = lw_texte
          IMPORTING
            virtual  = lw_xml.
      ENDIF.
      CALL METHOD o_doc->write_break CHANGING virtual = lw_xml.

      PERFORM get_range_text USING lt_eltdir[]
                                   lt_var[]
                                   lt_compdir[]
                                   ls_eltdir
                             CHANGING ls_range.
      PERFORM selopt_to_text USING space
                                   ls_range-sign ls_range-opt
                                   ls_range-lowtxtlg ls_range-hightxtlg
                             CHANGING lw_texte.

      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_texte
        IMPORTING
          virtual  = lw_xml_frag.
      CONCATENATE lw_xml lw_xml_frag INTO lw_xml.
    ENDLOOP.
    IF NOT lw_xml IS INITIAL.
      CALL METHOD o_doc->write_line
        CHANGING
          virtual = lw_xml.
      ls_data-f2-xml = lw_xml.
    ENDIF.
    APPEND ls_data TO lt_data.
  ENDLOOP.
  IF NOT lt_data IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Exceptions'
        line_style = cs_custo-style_title2.
    CLEAR ls_data.
    ls_data-f1-textline = 'Name'.
    ls_data-f2-textline = 'Restrictions'.
    INSERT ls_data INTO lt_data INDEX 1.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_with_head.
  ENDIF.

* Cells
  IF NOT lt_cells IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Cells'
        line_style = cs_custo-style_title2.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'There is parametrized cells'
        line_style = cl_word=>c_style_normal.

  ENDIF.
ENDFORM.                    " QUERY


*&---------------------------------------------------------------------*
*&      Form InfoSet
*&---------------------------------------------------------------------*
*       Display documentation for BW InfoSet
*----------------------------------------------------------------------*
*      -->FW_ISET  InfoSet Name
*----------------------------------------------------------------------*
FORM infoset USING fw_iset TYPE string.

  DATA : lw_texte TYPE string,
         lo_gui   TYPE REF TO cl_rsq_gui_iset,
         ls_iset  TYPE rsq_s_iset_cat,
         BEGIN OF ls_source,
           talias TYPE rsqtobj-talias,
           tname  TYPE rsqtobj-tname,
           ttype  TYPE rsqtobj-ttype,
         END OF ls_source,
         lt_sources LIKE TABLE OF ls_source,
         BEGIN OF ls_tab,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
         END OF ls_tab,
         lt_tab        LIKE TABLE OF ls_tab,
         ls_object     LIKE s_object,
         lw_filename   TYPE string,
         lw_rc         TYPE i,
         lw_filename_c TYPE catfilnam.
*  DATA : lw_srctyp,
*         lw_upone,
*         lw_imgurl    TYPE string,
*         ls_linestyle TYPE cl_word=>ty_paragraph_style_effect,
*         lw_rc        TYPE i,
*         lw_wad_title TYPE rszwbtmpheadtxt-txtlg.

  PERFORM object_progress_bar USING fw_iset c_iset
                                    'Writing InfoSet info...'(m18).

* Get InfoSet sources
* ttype OA = DSO, IC = Infocube, CP & CQ = IOBJ
  SELECT talias tname ttype INTO TABLE lt_sources
         FROM rsqtobj
         WHERE infoset = fw_iset
         AND objvers = c_objvers_active.

* Determinate filename of the infoset graphic
  CALL METHOD cl_gui_frontend_services=>get_temp_directory
    CHANGING
      temp_dir = lw_filename.
  IF lw_filename IS INITIAL.
    CALL METHOD cl_gui_frontend_services=>get_sapgui_workdir
      CHANGING
        sapworkdir = lw_filename.
  ENDIF.
  IF lw_filename IS INITIAL.
    lw_filename = cs_custo-dataflow_default_path.
  ENDIF.
  CONCATENATE lw_filename '\' fw_iset '.jpg' INTO lw_filename.

* If the file exists, delete it
  IF cl_gui_frontend_services=>file_exist( lw_filename ) = 'X'.
    CALL METHOD cl_gui_frontend_services=>file_delete
      EXPORTING
        filename = lw_filename
      CHANGING
        rc       = lw_rc.
  ENDIF.

* Generate Graphic
  ls_iset-infoset = fw_iset.
  ls_iset-objvers = c_objvers_active.
  TRY.
      CREATE OBJECT lo_gui
        EXPORTING
          i_r_container_parent = cl_gui_container=>screen9
          i_iset_cat           = ls_iset
          i_objvers            = c_objvers_active.
    CATCH cx_root.
      CLEAR lo_gui.
  ENDTRY.
  IF NOT lo_gui IS INITIAL.
    lw_filename_c = lw_filename.
    CALL METHOD lo_gui->p_r_join_cntrl->save_as_jpg
      EXPORTING
        i_filename = lw_filename_c.
    CALL METHOD cl_gui_cfw=>flush.
  ENDIF.

* InfoSet title
  CONCATENATE 'InfoSet' fw_iset
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Insert embbeded documents
  PERFORM special_note USING c_iset fw_iset
                             cs_custo-style_title2.

* List of infoproviders in the infoset
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'List of infoproviders used'
      line_style = cs_custo-style_title2.

  REFRESH lt_tab.
  CLEAR ls_tab.
  ls_tab-f1 = 'Alias'.
  ls_tab-f2 = 'Provider type'.
  ls_tab-f3 = 'Name'.
  APPEND ls_tab TO lt_tab.

  LOOP AT lt_sources INTO ls_source.
    CLEAR ls_object.
    CLEAR ls_tab.
    ls_tab-f1 = ls_source-talias.
    ls_tab-f2 = ls_source-tname.
    CASE ls_source-ttype.
      WHEN 'OA'.
        ls_tab-f3 = 'DSO'.
        ls_object-objtype = c_dso.
      WHEN 'IC'.
        ls_tab-f3 = 'CUBE'.
        ls_object-objtype = c_cube.
      WHEN 'CP' OR 'CQ'.
        ls_tab-f3 = 'IOBJ'.
        ls_object-objtype = c_iobj.
      WHEN OTHERS.
        CONTINUE.
    ENDCASE.
    APPEND ls_tab TO lt_tab.

    ls_object-object = ls_source-tname.
    PERFORM add_object_to_queue USING ls_object.
  ENDLOOP.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_tab
      style   = cs_custo-table_with_head.

* Mapping
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Graphic'
      line_style = cs_custo-style_title2.

  CALL METHOD o_doc->insert_image
    EXPORTING
      url = lw_filename.

ENDFORM.                    " InfoSet

*&---------------------------------------------------------------------*
*&      Form  f4_cube
*&---------------------------------------------------------------------*
*       InfoCube search help
*----------------------------------------------------------------------*
*      -->FW_FIELDNAME Name of field in dynpro
*      -->FW_TYPE      Type of cube
*      -->FW_VAL       Choosen value
*----------------------------------------------------------------------*
FORM f4_cube USING fw_fieldname TYPE dynfnam
                   fw_type TYPE rstlogo
             CHANGING fw_val TYPE rsd_infocube.
  DATA : ls_cubetype TYPE rsd_s_cubetype,
         lt_cubetype TYPE rsd_t_cubetype.

  CASE fw_type.
    WHEN c_cube.
      ls_cubetype-cubetype = rsd_c_cubetype-basic_ic.
      APPEND ls_cubetype TO lt_cubetype.
      ls_cubetype-cubetype = rsd_c_cubetype-virtual.
      APPEND ls_cubetype TO lt_cubetype.
    WHEN c_multi.
      ls_cubetype-cubetype = rsd_c_cubetype-multi_ic.
      APPEND ls_cubetype TO lt_cubetype.
    WHEN OTHERS.
      RETURN.
  ENDCASE.

  CALL FUNCTION 'RSDC_CUBE_F4_DYNP_UPDATE'
    EXPORTING
      i_repid      = sy-repid
      i_dynnr      = sy-dynnr
      i_fname      = fw_fieldname
      i_t_cubetype = lt_cubetype
      i_objvers    = c_objvers_active
    IMPORTING
      e_infocube   = fw_val.

ENDFORM.                    "f4_cube

*&---------------------------------------------------------------------*
*&      Form  f4_dso
*&---------------------------------------------------------------------*
*       DSO search help
*----------------------------------------------------------------------*
*      -->FW_FIELDNAME Name of field in dynpro
*      -->FW_VAL       Choosen value
*----------------------------------------------------------------------*
FORM f4_dso USING fw_fieldname TYPE dynfnam
            CHANGING fw_val TYPE rsd_infocube.

  CALL FUNCTION 'RSDC_ODSO_F4_DYNP_UPDATE'
    EXPORTING
      i_repid     = sy-repid
      i_dynnr     = sy-dynnr
      i_fname     = fw_fieldname
      i_objvers   = c_objvers_active
    IMPORTING
      e_odsobject = fw_val.

ENDFORM.                    "f4_dso

*&---------------------------------------------------------------------*
*&      Form  f4_file
*&---------------------------------------------------------------------*
*       Searchhelp for local folder selection
*----------------------------------------------------------------------*
FORM f4_file.
  DATA : lw_len       TYPE i,
         lw_file      TYPE string,
         lt_dynpfield TYPE TABLE OF dynpread,
         ls_dynpfield LIKE LINE OF lt_dynpfield.

  CALL FUNCTION 'DYNP_VALUES_READ'
    EXPORTING
      dyname     = sy-repid
      dynumb     = sy-dynnr
      request    = 'A'
    TABLES
      dynpfields = lt_dynpfield
    EXCEPTIONS
      OTHERS     = 9.

  READ TABLE lt_dynpfield INTO ls_dynpfield
             WITH KEY fieldname = 'P_FILE'.
  p_file = ls_dynpfield-fieldvalue.

  IF NOT p_file IS INITIAL.
    lw_len = strlen( p_file ).
    lw_len = lw_len - 1.
    IF p_file+lw_len(1) = '\'.
      lw_file = p_file(lw_len).
    ELSE.
      lw_file = p_file.
    ENDIF.
  ENDIF.

  CALL METHOD cl_gui_frontend_services=>directory_browse
    EXPORTING
*     window_title    = w_title
      initial_folder  = lw_file
    CHANGING
      selected_folder = lw_file
    EXCEPTIONS
      OTHERS          = 1.

  IF sy-subrc = 0 AND NOT lw_file IS INITIAL.
    CONCATENATE lw_file '\' INTO p_file .
  ENDIF.
ENDFORM.                    "f4_file

*&---------------------------------------------------------------------*
*&      Form  F4_WB
*&---------------------------------------------------------------------*
*       Workbook search help
*----------------------------------------------------------------------*
FORM f4_wb.

  DATA : lt_field TYPE ddfields,
         ls_field TYPE dfies,
         BEGIN OF ls_value,
           value TYPE help_info-fldvalue,
         END OF ls_value,
         lt_values LIKE TABLE OF ls_value,
         BEGIN OF ls_wb,
           workbookid TYPE rsrwbindext-workbookid,
           title      TYPE rsrwbindext-title,
         END OF ls_wb,
         lt_wb         LIKE TABLE OF ls_wb,
         lt_return     TYPE TABLE OF ddshretval,
         ls_return     LIKE LINE OF lt_return,
         lt_dynpfields TYPE TABLE OF dynpread,
         ls_dynpfields LIKE LINE OF lt_dynpfields.

* Get list of Core Workbooks from ROLES
  IF NOT cs_custo-workbook_role_template IS INITIAL.
    SELECT workbookid title
           FROM rsrwbindext
           INTO TABLE lt_wb
           WHERE workbookid IN (
      SELECT t1~sap_guid
           FROM agr_hier AS t1
           WHERE t1~agr_name LIKE cs_custo-workbook_role_template
           AND t1~report EQ 'RRMX'
           AND t1~sap_guid NE space
      )
      AND langu = c_lang_default
      AND objvers = c_objvers_active.
  ELSE.
    SELECT workbookid title
           FROM rsrwbindext
           INTO TABLE lt_wb
           WHERE langu = c_lang_default
           AND objvers = c_objvers_active.
  ENDIF.
* Fill columns informations
  CLEAR ls_field.
  ls_field-tabname = 'RSRWBINDEXT'.
  ls_field-fieldname = 'WORKBOOKID'.
  APPEND ls_field TO lt_field.
  CLEAR ls_field.
  ls_field-tabname = 'RSRWBINDEXT'.
  ls_field-fieldname = 'TITLE'.
  APPEND ls_field TO lt_field.

* Fill values
  LOOP AT lt_wb INTO ls_wb.
    CLEAR ls_value.
    ls_value-value = ls_wb-workbookid.
    APPEND ls_value TO lt_values.
    ls_value-value = ls_wb-title.
    APPEND ls_value TO lt_values.
  ENDLOOP.

* Call search help
  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield     = 'WORKBOOKID'
      dynprofield  = 'P_WB'
      dynpprog     = sy-repid
      dynpnr       = sy-dynnr
      window_title = 'Choose Workbook'
      value_org    = 'C' " Value return: C: cell by cell, S: structured
    TABLES
      value_tab    = lt_values
      field_tab    = lt_field
      return_tab   = lt_return
    EXCEPTIONS
      OTHERS       = 1.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ELSE.
    CLEAR ls_return.
    READ TABLE lt_return INTO ls_return INDEX 1.
    p_wb = ls_return-fieldval.
    CLEAR ls_wb.
    READ TABLE lt_wb INTO ls_wb WITH KEY workbookid = p_wb.

    CLEAR ls_dynpfields.
    ls_dynpfields-fieldname = 'P_WB_LBL'.
    ls_dynpfields-fieldvalue = ls_wb-title.
    APPEND ls_dynpfields TO lt_dynpfields.

    CALL FUNCTION 'DYNP_VALUES_UPDATE'
      EXPORTING
        dyname     = sy-cprog
        dynumb     = sy-dynnr
      TABLES
        dynpfields = lt_dynpfields
      EXCEPTIONS
        OTHERS     = 0.
  ENDIF.

ENDFORM.                    " F4_WB

*&---------------------------------------------------------------------*
*&      Form  F4_WAD
*&---------------------------------------------------------------------*
*       Bex Web Template (wad) search help
*----------------------------------------------------------------------*
FORM f4_wad.

  DATA : lt_field TYPE ddfields,
         ls_field TYPE dfies,
         BEGIN OF ls_value,
           value TYPE help_info-fldvalue,
         END OF ls_value,
         lt_values LIKE TABLE OF ls_value,
         BEGIN OF ls_wad,
           objid TYPE rszwbtmpheadtxt-objid,
           txtlg TYPE rszwbtmpheadtxt-txtlg,
         END OF ls_wad,
         lt_wad    LIKE TABLE OF ls_wad,
         lt_return TYPE TABLE OF ddshretval,
         ls_return LIKE LINE OF lt_return.

  SELECT objid txtlg
         FROM rszwbtmpheadtxt
         INTO TABLE lt_wad
         WHERE langu = c_lang_default
         AND objvers = c_objvers_active.

* Fill columns informations
  CLEAR ls_field.
  ls_field-tabname = 'RSZWBTMPHEADTXT'.
  ls_field-fieldname = 'OBJID'.
  APPEND ls_field TO lt_field.
  CLEAR ls_field.
  ls_field-tabname = 'RSZWBTMPHEADTXT'.
  ls_field-fieldname = 'TXTLG'.
  APPEND ls_field TO lt_field.

* Fill values
  LOOP AT lt_wad INTO ls_wad.
    CLEAR ls_value.
    ls_value-value = ls_wad-objid.
    APPEND ls_value TO lt_values.
    ls_value-value = ls_wad-txtlg.
    APPEND ls_value TO lt_values.
  ENDLOOP.

* Call search help
  CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield     = 'OBJID'
      dynprofield  = 'P_WAD'
      dynpprog     = sy-repid
      dynpnr       = sy-dynnr
      window_title = 'Choose Bex Web Template'
      value_org    = 'C' " Value return: C: cell by cell, S: structured
    TABLES
      value_tab    = lt_values
      field_tab    = lt_field
      return_tab   = lt_return
    EXCEPTIONS
      OTHERS       = 1.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ELSE.
    CLEAR ls_return.
    READ TABLE lt_return INTO ls_return INDEX 1.
    p_wad = ls_return-fieldval.
  ENDIF.

ENDFORM.                    " F4_WAD

*&---------------------------------------------------------------------*
*&      Form  dtp
*&---------------------------------------------------------------------*
*       Display documentation for a DTP
*----------------------------------------------------------------------*
*      -->FW_DTP    DTP
*      -->FW_OBJECT Target of the DTP
*      -->FW_OBJTYP Target type
*      -->FW_OBJECT Source of the DTP
*----------------------------------------------------------------------*
FORM dtp USING fw_dtp TYPE rsbkdtp-dtp
               fw_object
               fw_objtyp TYPE rstlogo
               fw_src TYPE rsbkdtp-src.

  DATA: BEGIN OF ls_dtp,
          src           TYPE rsbkdtp-src,
          srctp         TYPE rsbkdtp-srctlogo,
          tgt           TYPE rsbkdtp-tgt,
          tgttp         TYPE rsbkdtp-tgttlogo,
          updmode       TYPE rsbkdtp-updmode,
          deltaonlyonce TYPE rsbkdtp-deltaonlyonce,
          processmode   TYPE rsbkdtp-processmode,
          errorhandling TYPE rsbkdtp-errorhandling,
          noaggr        TYPE rsbkdtp-noaggr,
          number_at_err TYPE rsbkdtp-number_at_err,
          autoqualok    TYPE rsbkdtp-autoqualok,
          warningtstate TYPE rsbkdtp-warningtstate,
          dtptype       TYPE rsbkdtp-dtptype,
        END OF ls_dtp,
        lt_varseltab TYPE mch_t_var_select,
        lt_seltab    TYPE mch_t_select,
        lt_dtprule   TYPE mch_t_sourcecode,
        lt_selfields TYPE mch_t_field,
        ls_varseltab LIKE LINE OF lt_varseltab,
        ls_dtprule   LIKE LINE OF lt_dtprule,
        lt_range     TYPE rsbk_th_range,
        ls_range     LIKE LINE OF lt_range,
        lt_gf        TYPE rsbk_tx_fields_keyfl,
        ls_gf        LIKE LINE OF lt_gf,
        lw_txtlg     TYPE rsbkdtpt-txtlg,
        ls_fields    LIKE LINE OF ls_gf-t_fields,
        lt_code      TYPE ty_code_table,
        lw_texte     TYPE string,
        lw_domval    TYPE val_text,
        BEGIN OF ls_data,
          f1 TYPE cl_word=>ty_table_style_field,
          f2 TYPE cl_word=>ty_table_style_field,
        END OF ls_data,
        lt_data LIKE TABLE OF ls_data,
        BEGIN OF ls_sem,
          f1 TYPE cl_word=>ty_table_style_field,
          f2 TYPE cl_word=>ty_table_style_field,
          f3 TYPE cl_word=>ty_table_style_field,
        END OF ls_sem,
        lt_sem LIKE TABLE OF ls_sem,
        BEGIN OF ls_data2,
          f1(80) TYPE c,
          f2(80) TYPE c,
        END OF ls_data2,
        lt_data2      LIKE TABLE OF ls_data2,

        lo_dtp        TYPE REF TO cl_rsbk_dtp,
        lo_update_cmd TYPE REF TO cl_rsbc_u_odso_tpl,
        lo_filter     TYPE REF TO cl_rsbc_filter.

  CONCATENATE 'Writing DTP'(m14) fw_src '=>' fw_object
              INTO lw_texte SEPARATED BY space.
  PERFORM object_progress_bar USING fw_object fw_objtyp
                                    lw_texte.

  SELECT SINGLE src srctlogo tgt tgttlogo updmode deltaonlyonce
         processmode errorhandling noaggr number_at_err
         autoqualok warningtstate dtptype
         INTO ls_dtp
         FROM rsbkdtp
         WHERE dtp = fw_dtp
         AND   objvers = 'A'.

  SELECT SINGLE txtlg INTO lw_txtlg
         FROM rsbkdtpt
         WHERE langu = c_lang_default
         AND   dtp = fw_dtp
         AND   objvers = 'A'.
  IF sy-subrc NE 0 OR lw_txtlg IS INITIAL.
    CONCATENATE fw_src '=>' fw_object INTO lw_txtlg SEPARATED BY space.
    CONDENSE lw_txtlg.
  ENDIF.

  CALL METHOD cl_rsbk_dtp=>factory
    EXPORTING
      i_dtp   = fw_dtp
    RECEIVING
      r_r_dtp = lo_dtp.
  TRY.
      lo_update_cmd  ?= lo_dtp->get_obj_ref_tpl_u( ).
    CATCH cx_sy_move_cast_error.
    CATCH cx_rs_access_error.
    CLEANUP.
  ENDTRY.

  TRY.
      lo_filter ?= lo_dtp->get_obj_ref_filter( ).
    CATCH cx_rs_error_with_message .
    CATCH cx_rs_access_error.
  ENDTRY.

  TRY.
      CALL METHOD lo_filter->get_all
        IMPORTING
* Special filters (FIELD / SEL_ROUTINE = id routine, BEX_VARIABLE = bex variable, SEL_TYPE = 6 for routine, 7 for olap)
          e_t_varseltab = lt_varseltab
* Classical select options filters FIELD/SIGN/OPTION/LOW/HIGH
          e_t_seltab    = lt_seltab
* ABAP code FIELD/SEL_ROUTINE
          e_t_dtprule   = lt_dtprule
          e_t_selfields = lt_selfields.
    CATCH cx_rs_program_error.
  ENDTRY.

  REFRESH lt_range.
  lt_range = lo_dtp->if_rsbk_dtp_display~get_th_range( i_with_variables = rs_c_true ).

  REFRESH lt_gf.
  CALL METHOD lo_dtp->get_groupfields
    IMPORTING
      e_t_groupfields = lt_gf.

* DTP title
  CONCATENATE 'DTP:' lw_txtlg
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title2.

* Insert embbeded documents
  PERFORM special_note USING c_dtp fw_dtp
                             cs_custo-style_title3.

* General info
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title3.

  REFRESH lt_data2.
  CLEAR ls_data2.
  ls_data2-f1 = 'DTP type'.
  PERFORM get_domain_value USING 'RSBKDTPTYPE'
                                 ls_dtp-dtptype
                           CHANGING lw_domval.
  ls_data2-f2 = lw_domval.
  APPEND ls_data2 TO lt_data2.

  CLEAR ls_data2.
  ls_data2-f1 = 'Target'.
  ls_data2-f2 = ls_dtp-tgt.
  APPEND ls_data2 TO lt_data2.

  CLEAR ls_data2.
  ls_data2-f1 = 'Target type'.
  PERFORM get_domain_value USING 'RSSB_TLOGO_TGT'
                                 ls_dtp-tgttp
                           CHANGING lw_domval.
  ls_data2-f2 = lw_domval.
  APPEND ls_data2 TO lt_data2.

  CLEAR ls_data2.
  ls_data2-f1 = 'Source'.
  ls_data2-f2 = ls_dtp-src.
  APPEND ls_data2 TO lt_data2.

  CLEAR ls_data2.
  ls_data2-f1 = 'Source type'.
  PERFORM get_domain_value USING 'RSSB_TLOGO_SRC'
                                 ls_dtp-srctp
                           CHANGING lw_domval.
  ls_data2-f2 = lw_domval.
  APPEND ls_data2 TO lt_data2.

  CLEAR ls_data2.
  ls_data2-f1 = 'ID'.
  ls_data2-f2 = fw_dtp.
  APPEND ls_data2 TO lt_data2.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data2
      style   = cs_custo-table_without_head.

* Extraction
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Extraction parameters'
      line_style = cs_custo-style_title3.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Extraction mode'.
  PERFORM get_domain_value USING 'RSBKUPDMODE'
                                 ls_dtp-updmode
                           CHANGING lw_domval.
  ls_data-f2-textline = lw_domval.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Only get delta once'.
  IF ls_dtp-deltaonlyonce = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Filter'.
  IF lt_range[] IS INITIAL.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Semantic groups'.
  IF lt_gf[] IS INITIAL.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

  IF NOT lt_range[] IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Filters'
        line_style = cs_custo-style_title3.
    REFRESH lt_data2.
    CLEAR ls_data2.
    ls_data2-f1 = 'InfoObject'.
    ls_data2-f2 = 'Value'.
    APPEND ls_data2 TO lt_data2.
    LOOP AT lt_range INTO ls_range.
      CLEAR ls_data2.
      ls_data2-f1 = ls_range-fieldnm.
      IF ls_range-sign = 'E'.
        ls_data2-f2 = 'Exclude:'.
      ENDIF.
      CASE ls_range-option.
        WHEN 'EQ'.
          CONCATENATE ls_data2-f2 '=' INTO ls_data2-f2 SEPARATED BY space.
        WHEN 'NE'.
          CONCATENATE ls_data2-f2 '<>' INTO ls_data2-f2 SEPARATED BY space.
        WHEN OTHERS.
          CONCATENATE ls_data2-f2 ls_range-option INTO ls_data2-f2 SEPARATED BY space.
      ENDCASE.

      CONDENSE ls_range-low.
      CONCATENATE ls_data2-f2 ls_range-low INTO ls_data2-f2 SEPARATED BY space.

      IF NOT ls_range-high IS INITIAL.
        CONDENSE ls_range-high.
        CONCATENATE ls_data2-f2 '-' ls_range-high INTO ls_data2-f2 SEPARATED BY space.
      ENDIF.
      APPEND ls_data2 TO lt_data2.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data2
        style   = cs_custo-table_with_head.

    LOOP AT lt_varseltab INTO ls_varseltab WHERE sel_type = 6.

      AT FIRST.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline   = 'Filters declaration routine'
            line_style = cs_custo-style_title3.
        REFRESH lt_code.
        LOOP AT lt_dtprule INTO ls_dtprule WHERE field = space.
          APPEND ls_dtprule-line TO lt_code.
        ENDLOOP.
        PERFORM code_display USING lt_code.
      ENDAT.

      CONCATENATE 'Filters routine:' ls_varseltab-sel_routine
                   INTO lw_texte SEPARATED BY space.

      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = lw_texte
          line_style = cs_custo-style_title3.

      REFRESH lt_code.
      LOOP AT lt_dtprule INTO ls_dtprule WHERE field = ls_varseltab-field AND sel_routine = ls_varseltab-sel_routine.
        APPEND ls_dtprule-line TO lt_code.
      ENDLOOP.
      PERFORM code_display USING lt_code.
    ENDLOOP.
  ENDIF.

* Display semantic group detail if required
  IF NOT lt_gf[] IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Semantic group'
        line_style = cs_custo-style_title3.

    REFRESH lt_sem.
    CLEAR ls_sem.
    ls_sem-f1-textline = 'Field Name'.
    ls_sem-f2-textline = 'Long description'.
    ls_sem-f3-textline = 'Key field'.
    APPEND ls_sem TO lt_sem.

    LOOP AT lt_gf INTO ls_gf.
      LOOP AT ls_gf-t_fields INTO ls_fields.
        CLEAR ls_sem.
        ls_sem-f1-textline = ls_fields-fieldname.
        ls_sem-f2-textline = ls_fields-txtlg.
        IF ls_fields-keyfield = space.
          ls_sem-f3-textline = cl_word=>c_symbol_checkbox.
        ELSE.
          ls_sem-f3-textline = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        ls_sem-f3-style_effect-font = cl_word=>c_font_symbol.
        APPEND ls_sem TO lt_sem.
      ENDLOOP.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_sem
        style   = cs_custo-table_with_head.
  ENDIF.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Update'
      line_style = cs_custo-style_title3.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Error handling'.
  PERFORM get_domain_value USING 'RSBKERRORHANDLING'
                                 ls_dtp-errorhandling
                           CHANGING lw_domval.
  ls_data-f2-textline = lw_domval.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Max number of errors per pack'.
  ls_data-f2-textline = ls_dtp-number_at_err.
  CONDENSE ls_data-f2-textline NO-GAPS.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'No aggregation'.
  IF ls_dtp-noaggr = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  CONDENSE ls_data-f2-textline NO-GAPS.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'No further process without master data'.
  IF lo_update_cmd IS INITIAL OR lo_update_cmd->n_only_check_sids = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  CONDENSE ls_data-f2-textline NO-GAPS.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Execute'
      line_style = cs_custo-style_title3.
  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Technical request status'.
  PERFORM get_domain_value USING 'RSBKSTATE'
                                 ls_dtp-warningtstate
                           CHANGING lw_domval.
  ls_data-f2-textline = lw_domval.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Set overalll status automatically'.
  IF ls_dtp-autoqualok = space.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  ls_data-f1-textline = 'Processing mode'.
  PERFORM get_domain_value USING 'RSBKPROCESSMODE'
                                 ls_dtp-processmode
                           CHANGING lw_domval.
  ls_data-f2-textline = lw_domval.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

ENDFORM. "dtp

*&---------------------------------------------------------------------*
*&      Form ip
*&---------------------------------------------------------------------*
*       Display documentation for an infopackage
*----------------------------------------------------------------------*
*      -->FW_IP     Infopackage
*      -->FW_OBJECT Infosource / Target of the infopackage
*      -->FW_OBJTYP Object type
*      -->FW_OBJECT Source of the Infopackage
*----------------------------------------------------------------------*
FORM ip USING fw_ip TYPE rsldpio-logdpid
              fw_object TYPE string
              fw_objtyp TYPE rstlogo
              fw_src.
  DATA : lw_texte TYPE string,
         BEGIN OF ls_prop,
           name  TYPE cl_word=>ty_table_style_field,
           value TYPE cl_word=>ty_table_style_field,
         END OF ls_prop,
         lt_prop LIKE TABLE OF ls_prop,
         BEGIN OF ls_data,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
           f5(80) TYPE c,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_details,
           infopackage TYPE rsldpio-logdpid,
           infosource  TYPE rsldpio-source,
           datasource  TYPE rsldpio-oltpsource,
           logsys      TYPE rsldpio-logsys,
         END OF ls_details,
         lw_description TYPE rstxtlg,
         BEGIN OF ls_sel,
           fieldname      TYPE rsldpsel-fieldname,
           iobjnm         TYPE rsldpsel-iobjnm,
           low            TYPE rsldpsel-low,
           high           TYPE rsldpsel-high,
           selupdic       TYPE rsldpsel-selupdic,
           ziel           TYPE rsldpsel-ziel,
           chavl_check    TYPE rsldpsel-chavl_check,
           init_simu      TYPE rsldpsel-init_simu,
           update_cube    TYPE rsldpsel-update_cube,
           repair_full    TYPE rsldpsel-repair_full,
           inittodelta    TYPE rsldpsel-inittodelta,
           vartyp         TYPE rsldpsel-vartyp,
           bex_variable   TYPE rsldpsel-bex_variable,
           hienm          TYPE rsldpsel-hienm,
           hievers        TYPE rsldpsel-hievers,
           hieclass       TYPE rsldpsel-hieclass,
           new_hiename_on TYPE rsldpsel-new_hiename_on,
           new_hienm      TYPE rsldpsel-new_hienm,
           hieract        TYPE rsldpsel-hieract,
           rfcfieldnm     TYPE rsldpsel-rfcfieldnm,
           rfcvalue       TYPE rsldpsel-rfcvalue,
           location       TYPE rsldpsel-location,
           filename       TYPE rsldpsel-filename,
           filetyp        TYPE rsldpsel-filetyp,
           filesep        TYPE rsldpsel-filesep,
           esc            TYPE rsldpsel-esc,
           ignorelines    TYPE rsldpsel-ignorelines,
         END OF ls_sel,
         lt_sel    LIKE TABLE OF ls_sel,
         ls_option LIKE ls_sel,
         BEGIN OF ls_batch,
           updmode   TYPE rssdbatch-updmode,
           metaupdic TYPE rssdbatch-metaupdic,
         END OF ls_batch,
         lw_domval TYPE val_text,
         BEGIN OF ls_iprov,
           iprov(30) TYPE c,
           txtlg     TYPE rstxtlg,
         END OF ls_iprov,
         lt_iprov     LIKE TABLE OF ls_iprov,
         lw_hierarchy TYPE rstxtlg,
         BEGIN OF ls_idoc,
           maxsize  TYPE roosprms-maxsize,
           statfrqu TYPE roosprms-statfrqu,
           maxprocs TYPE roosprms-maxprocs,
           maxdpaks TYPE roosprms-maxdpaks,
         END OF ls_idoc,
         BEGIN OF ls_abap,
           fieldname TYPE rsldprule-fieldname,
           lnr       TYPE rsldprule-lnr,
           iobjnm    TYPE rsldprule-iobjnm,
           line      TYPE rsldprule-line,
         END OF ls_abap,
         lt_abap LIKE TABLE OF ls_abap,
         lt_code TYPE ty_code_table.

  CONCATENATE 'Writing IP'(m15) fw_src '=>' fw_object
              INTO lw_texte SEPARATED BY space.
  PERFORM object_progress_bar USING fw_object fw_objtyp
                                    lw_texte.

  ls_details-infopackage = fw_ip.
  SELECT SINGLE logdpid source oltpsource logsys
         INTO ls_details
         FROM rsldpio
         WHERE logdpid = ls_details-infopackage
         AND objvers = c_objvers_active.

  SELECT SINGLE text INTO lw_description
         FROM rsldpiot
           WHERE langu = c_lang_default
           AND logdpid = ls_details-infopackage
           AND objvers = c_objvers_active.
  IF sy-subrc NE 0.
    SELECT SINGLE text INTO lw_description
           FROM rsldpiot
             WHERE logdpid = ls_details-infopackage
             AND objvers = c_objvers_active.
  ENDIF.

  SELECT SINGLE updmode metaupdic
         INTO ls_batch
         FROM rssdbatch
         WHERE logid = ls_details-infopackage
         AND objvers = c_objvers_active.

  SELECT fieldname iobjnm low high selupdic ziel chavl_check init_simu
         update_cube repair_full inittodelta vartyp bex_variable
* Hierarchy data
         hienm hievers hieclass new_hiename_on new_hienm hieract
* 3rd party data
         rfcfieldnm rfcvalue
* File data
         location filename filetyp filesep esc ignorelines
         INTO TABLE lt_sel
         FROM rsldpsel
         WHERE logdpid = ls_details-infopackage
         AND objvers = c_objvers_active.

  IF NOT lt_sel[] IS INITIAL.
* Read option of infopackage stored in selection table...
    READ TABLE lt_sel INTO ls_option INDEX 1.

    SELECT infocube txtlg
           INTO TABLE lt_iprov
           FROM rsdcubet
           FOR ALL ENTRIES IN lt_sel
           WHERE infocube = lt_sel-selupdic
           AND objvers = c_objvers_active.
    SELECT odsobject txtlg
           APPENDING TABLE lt_iprov
           FROM rsdodsot
           FOR ALL ENTRIES IN lt_sel
           WHERE odsobject = lt_sel-selupdic
           AND objvers = c_objvers_active.
    SELECT iobjnm txtlg
           APPENDING TABLE lt_iprov
           FROM rsdiobjt
           FOR ALL ENTRIES IN lt_sel
           WHERE iobjnm = lt_sel-selupdic
           AND objvers = c_objvers_active.
    SORT lt_iprov BY iprov.
    DELETE ADJACENT DUPLICATES FROM lt_iprov COMPARING iprov.

    READ TABLE lt_sel WITH KEY vartyp = '6'
                      TRANSPORTING NO FIELDS.
    IF sy-subrc = 0.
      SELECT fieldname lnr iobjnm line
             INTO TABLE lt_abap
             FROM rsldprule
             WHERE logdpid = ls_details-infopackage
             AND objvers = c_objvers_active.
      SORT lt_abap BY fieldname iobjnm lnr.
    ENDIF.
  ENDIF.

  IF ls_option-hienm NE space.
    SELECT SINGLE txtlg INTO lw_hierarchy
           FROM rsosohiet
           WHERE langu = c_lang_default
           AND osource = ls_details-datasource
           AND objvers = c_objvers_active
           AND hienm = ls_option-hienm
           AND hievers = ls_option-hievers
           AND hieclass = ls_option-hieclass.
    IF sy-subrc NE 0.
      SELECT SINGLE txtlg INTO lw_hierarchy
             FROM rsosohiet
             WHERE langu = c_lang_default
             AND osource = ls_details-datasource
             AND objvers = c_objvers_active
             AND hienm = ls_option-hienm
             AND hievers = ls_option-hievers
             AND hieclass = ls_option-hieclass.
    ENDIF.
  ENDIF.

  SELECT SINGLE maxsize statfrqu maxprocs maxdpaks
         INTO ls_idoc
         FROM roosprms
         WHERE oltpsource = ls_details-datasource
         AND srlogsys = ls_details-logsys
         AND updmode = ls_batch-updmode.

  CONCATENATE 'IP' lw_description
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title2.

* Insert embbeded documents
  PERFORM special_note USING c_ip fw_ip
                             cs_custo-style_title3.

* General informations
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title3.

  REFRESH lt_prop.
  CLEAR ls_prop.
  ls_prop-name-textline = 'Description'.
  ls_prop-value-textline = lw_description.
  APPEND ls_prop TO lt_prop.

  IF NOT ls_details-infosource IS INITIAL.
    CLEAR ls_prop.
    ls_prop-name-textline = 'Infosource'.
    ls_prop-value-textline = ls_details-infosource.
    APPEND ls_prop TO lt_prop.
  ENDIF.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Datasource'.
  ls_prop-value-textline = ls_details-datasource.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Source system'.
  ls_prop-value-textline = ls_details-logsys.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'ID'.
  ls_prop-value-textline = ls_details-infopackage.
  APPEND ls_prop TO lt_prop.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_prop
      style   = cs_custo-table_without_head.

* Data selection
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Data selection'
      line_style = cs_custo-style_title3.
  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1 = 'InfoObject'.
  ls_data-f2 = 'Technical name'.
  ls_data-f3 = 'From value'.
  ls_data-f4 = 'To value'.
  ls_data-f5 = 'Type'.
  APPEND ls_data TO lt_data.

  LOOP AT lt_sel INTO ls_sel WHERE NOT fieldname IS INITIAL
                             OR NOT iobjnm IS INITIAL.
    ls_data-f1 = ls_sel-iobjnm.
    ls_data-f2 = ls_sel-fieldname.
    ls_data-f3 = ls_sel-low.
    ls_data-f4 = ls_sel-high.
    IF NOT ls_sel-vartyp IS INITIAL.
      PERFORM get_domain_value USING 'RSVARTYPD'
                                     ls_sel-vartyp
                               CHANGING lw_domval.
      ls_data-f5 = lw_domval.
      IF ls_sel-vartyp = '7'. "bex variable
        CONCATENATE ls_data-f5 ls_sel-bex_variable
                    INTO ls_data-f5 SEPARATED BY ': '.
      ENDIF.
    ENDIF.
    APPEND ls_data TO lt_data.
  ENDLOOP.
  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_with_head.

* Display abap data declaration (for routine)
  IF NOT lt_abap IS INITIAL.
    REFRESH lt_code.
    LOOP AT lt_abap INTO ls_abap WHERE fieldname IS INITIAL
                                 AND iobjnm IS INITIAL.
      APPEND ls_abap-line TO lt_code.
    ENDLOOP.
    IF NOT lt_code[] IS INITIAL.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Data declaration'
          line_style = cs_custo-style_title3.
      PERFORM code_display USING lt_code.
    ENDIF.
  ENDIF.

* Display used routines
  LOOP AT lt_sel INTO ls_sel WHERE vartyp = '6'.
    REFRESH lt_code.
    LOOP AT lt_abap INTO ls_abap WHERE fieldname = ls_sel-fieldname
                                 AND iobjnm = ls_sel-iobjnm.
      APPEND ls_abap-line TO lt_code.
    ENDLOOP.
    IF NOT lt_code[] IS INITIAL.
      CONCATENATE 'Routine for InfoObject'
                  ls_sel-iobjnm
                  INTO lw_texte SEPARATED BY space.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = lw_texte
          line_style = cs_custo-style_title3.
      PERFORM code_display USING lt_code.
    ENDIF.
  ENDLOOP.

* Processing & Update
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Processing & update'
      line_style = cs_custo-style_title3.
  REFRESH lt_prop.
  CLEAR ls_prop.
  ls_prop-name-textline = 'Consistency check for characteristic value in transfer rules'.
  IF ls_option-chavl_check = space.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Update data'.
  PERFORM get_domain_value USING 'RSZIELD'
                                 ls_option-ziel
                           CHANGING lw_domval.
  ls_prop-value-textline = lw_domval.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Update subsequently in Data Target'.
  IF ls_option-update_cube = space.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Update mode'.
  CASE ls_batch-updmode.
    WHEN 'F'.
      ls_prop-value-textline = 'Full'.
    WHEN 'C'.
      IF ls_option-init_simu = space.
        ls_prop-value-textline = 'Init'.
      ELSE.
        ls_prop-value-textline = 'Init without data transfer'.
      ENDIF.
    WHEN 'D'.
      ls_prop-value-textline = 'Delta'.
    WHEN 'I'.
      ls_prop-value-textline = 'Transfer of an opening balance for non-cumulative values'.
    WHEN OTHERS.
      ls_prop-value-textline = '???'.
  ENDCASE.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Switch Infopack in PC to delta'.
  IF ls_option-inittodelta = space.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Data update type in the data target'.
  PERFORM get_domain_value USING 'RSMETAUPDIC'
                                 ls_batch-metaupdic
                           CHANGING lw_domval.
  ls_prop-value-textline = lw_domval.
  APPEND ls_prop TO lt_prop.

  CLEAR ls_prop.
  ls_prop-name-textline = 'Repair mode'.
  IF ls_option-repair_full = space.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox.
  ELSE.
    ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
  ENDIF.
  ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
  APPEND ls_prop TO lt_prop.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_prop
      style   = cs_custo-table_without_head.

* Data targets (except for "only in PSA")
  IF ls_option-ziel NE '1'.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Data target'
        line_style = cs_custo-style_title3.
    REFRESH lt_prop.
    CLEAR ls_prop.
    ls_prop-name-textline = 'Infoprovider'.
    ls_prop-value-textline = 'Description'.
    APPEND ls_prop TO lt_prop.
    LOOP AT lt_sel INTO ls_sel WHERE NOT selupdic IS INITIAL.
      CLEAR ls_prop.
      ls_prop-name-textline = ls_sel-selupdic.
      READ TABLE lt_iprov INTO ls_iprov WITH KEY iprov = ls_sel-selupdic.
      ls_prop-value-textline = ls_iprov-txtlg.
      APPEND ls_prop TO lt_prop.
    ENDLOOP.
    IF sy-subrc NE 0.
      CLEAR ls_prop.
      ls_prop-name-textline = '-'.
      ls_prop-value-textline = 'All targets'.
      ls_prop-value-style_effect-italic = 1.
      APPEND ls_prop TO lt_prop.
    ENDIF.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_with_head.
  ENDIF.

  IF NOT ls_idoc IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Specific settings for sending data'
        line_style = cs_custo-style_title3.
    REFRESH lt_prop.
    CLEAR ls_prop.
    ls_prop-name-textline = 'Max size of a data packet in kByte'.
    ls_prop-value-textline = ls_idoc-maxsize.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Frequency with which status Idocs are sent'.
    ls_prop-value-textline = ls_idoc-statfrqu.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Maximum number of parallel processes for data transfer'.
    ls_prop-value-textline = ls_idoc-maxprocs.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Maximum Number of Data Packages in a Delta Request'.
    ls_prop-value-textline = ls_idoc-maxdpaks.
    APPEND ls_prop TO lt_prop.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_without_head.
  ENDIF.

* FILE TAB
  IF NOT ls_option-location IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Extraction'
        line_style = cs_custo-style_title3.

    REFRESH lt_prop.
    CLEAR ls_prop.
    ls_prop-name-textline = 'External system type'.
    PERFORM get_domain_value USING 'RSLOCD'
                                   ls_option-location
                             CHANGING lw_domval.
    ls_prop-value-textline = lw_domval.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'File Name'.
    ls_prop-value-textline = ls_option-filename.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'File type'.
    PERFORM get_domain_value USING 'RSFILETYPD'
                                   ls_option-filetyp
                             CHANGING lw_domval.
    ls_prop-value-textline = lw_domval.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Header rows to be ignored'.
    ls_prop-value-textline = ls_option-ignorelines.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Data separator'.
    ls_prop-value-textline = cl_abap_conv_in_ce=>uccp( ls_option-filesep ).
    IF ls_prop-value-textline IS INITIAL.
      ls_prop-value-textline = ls_option-filesep.
      CONCATENATE '(x' ls_prop-value-textline ')' INTO ls_prop-value-textline.
    ENDIF.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Escape sign'.
    ls_prop-value-textline = cl_abap_conv_in_ce=>uccp( ls_option-esc ).
    IF ls_prop-value-textline IS INITIAL.
      ls_prop-value-textline = ls_option-esc.
      CONCATENATE '(x' ls_prop-value-textline ')' INTO ls_prop-value-textline.
    ENDIF.
    APPEND ls_prop TO lt_prop.

    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_without_head.
  ENDIF.

* Hierarchy tab
  IF ls_option-hienm NE space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Hierarchy'
        line_style = cs_custo-style_title3.
    REFRESH lt_prop.
    CLEAR ls_prop.
    ls_prop-name-textline = 'Hierarchy'.
    ls_prop-value-textline = lw_hierarchy.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Technical name'.
    ls_prop-value-textline = ls_option-hienm.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Hierarchy class'.
    ls_prop-value-textline = ls_option-hieclass.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Activate after loading'.
    IF ls_option-hieract = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'Rename hierarchy after loading'.
    IF ls_option-new_hiename_on = space.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox.
    ELSE.
      ls_prop-value-textline = cl_word=>c_symbol_checkbox_checked.
    ENDIF.
    ls_prop-value-style_effect-font = cl_word=>c_font_symbol.
    APPEND ls_prop TO lt_prop.

    CLEAR ls_prop.
    ls_prop-name-textline = 'New hierarchy name'.
    ls_prop-value-textline = ls_option-new_hienm.
    APPEND ls_prop TO lt_prop.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_without_head.
  ENDIF.

* 3rd party tab
  IF ls_option-rfcfieldnm NE space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Third party selection'
        line_style = cs_custo-style_title3.
    REFRESH lt_prop.
    CLEAR ls_prop.
    ls_prop-name-textline = 'Name'.
    ls_prop-value-textline = 'Input Value'.
    APPEND ls_prop TO lt_prop.
    LOOP AT lt_sel INTO ls_sel WHERE rfcfieldnm NE space.
      CLEAR ls_prop.
      ls_prop-name-textline = ls_sel-rfcfieldnm.
      ls_prop-value-textline = ls_sel-rfcvalue.
      APPEND ls_prop TO lt_prop.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_prop
        style   = cs_custo-table_with_head.
  ENDIF.

ENDFORM.                    "ip

*&---------------------------------------------------------------------*
*&      Form code_display
*&---------------------------------------------------------------------*
*       Write a code paragraph in document
*----------------------------------------------------------------------*
*      -->FT_CODE Code to be displayed
*----------------------------------------------------------------------*
FORM code_display USING ft_code TYPE ty_code_table.
  DATA : lw_prev_empty TYPE c,
         lw_code       TYPE string.

* Search includes
  PERFORM scan_abap USING ft_code.

  lw_prev_empty = 'X'.
  LOOP AT ft_code INTO lw_code.

* Print only first blank line of a pack, skip all successives ones.
    IF lw_code CO space.
      IF lw_prev_empty = 'X'.
        CONTINUE.
      ELSE.
        lw_prev_empty = 'X'.
      ENDIF.
    ENDIF.

* If line start with *, write line as comment
    IF NOT lw_code IS INITIAL AND lw_code(1) = '*'.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_code
          style    = cs_custo-style_comment.
    ELSE.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline = lw_code.
    ENDIF.
    CALL METHOD o_doc->write_break.
  ENDLOOP.

* Finally add the code style to paragraph
  CALL METHOD o_doc->write_line
    EXPORTING
      style = cs_custo-style_code.
ENDFORM.                    "code_display

*&---------------------------------------------------------------------*
*&      Form scan_abap
*&---------------------------------------------------------------------*
*       Search includes in the given abap code
*----------------------------------------------------------------------*
*      -->FT_ABAP : Abap code to scan
*----------------------------------------------------------------------*
FORM scan_abap USING ft_abap TYPE ty_code_table.
  DATA : ls_find     TYPE match_result,
         lt_find     TYPE match_result_tab,
         lt_find_sub TYPE match_result_tab,
         ls_sub      LIKE LINE OF ls_find-submatches,
         lw_lines    TYPE i,
         lt_abap     TYPE ty_code_table,
         lw_command  TYPE string,
         lt_commands LIKE TABLE OF lw_command,
         lw_prog     TYPE string,
         lw_prog_c   TYPE progname,
         lt_prog     LIKE TABLE OF lw_prog.
  FIELD-SYMBOLS <lfs_abap> LIKE LINE OF ft_abap.

  lt_abap[] = ft_abap[].

* 1 - Clean code
* Remove * comment
  LOOP AT lt_abap ASSIGNING <lfs_abap>.
    IF <lfs_abap> CS '*' AND <lfs_abap>(1) = '*'.
      CLEAR <lfs_abap>.
    ENDIF.
  ENDLOOP.

* Remove " comment
  LOOP AT lt_abap ASSIGNING <lfs_abap>.
    CHECK <lfs_abap> CS '"'.
*    condense ls_query-line.
    FIND ALL OCCURRENCES OF '"' IN <lfs_abap> RESULTS lt_find.
    IF sy-subrc NE 0. "may not occurs
      CONTINUE.
    ENDIF.
    LOOP AT lt_find INTO ls_find.
      IF ls_find-offset GT 0.
* Search open '
        FIND ALL OCCURRENCES OF '''' IN <lfs_abap>(ls_find-offset)
             RESULTS lt_find_sub.
        IF sy-subrc = 0.
          DESCRIBE TABLE lt_find_sub LINES lw_lines.
          lw_lines = lw_lines MOD 2.
          IF lw_lines = 1.
            CONTINUE.
          ENDIF.
        ENDIF.
        <lfs_abap> = <lfs_abap>(ls_find-offset).
        EXIT. "exit loop
      ELSE.
        CLEAR <lfs_abap>.
        EXIT. "exit loop
      ENDIF.
    ENDLOOP.
  ENDLOOP.

* Revove all empty lines
  LOOP AT lt_abap ASSIGNING <lfs_abap>.
    IF <lfs_abap> CO space.
      DELETE lt_abap.
    ENDIF.
  ENDLOOP.

  IF lt_abap[] IS INITIAL.
    RETURN.
  ENDIF.

* 2 - condense each command in 1 line
* Condense abap in 1 line
  CLEAR lw_command.
  LOOP AT lt_abap ASSIGNING <lfs_abap>.
    CONCATENATE lw_command <lfs_abap>
                INTO lw_command SEPARATED BY space.
  ENDLOOP.
  CONDENSE lw_command.

* Split by '.'
  DO.
    ls_find-length = strlen( lw_command ).
    IF ls_find-length = 0.
      EXIT. "exit do
    ENDIF.
    IF lw_command(1) CO space.
      lw_command = lw_command+1.
    ENDIF.
* find first occurrence, but to manage case of . in a character chain
* need to take all occurrences
    FIND ALL OCCURRENCES OF '.' IN lw_command
         RESULTS lt_find.
    IF sy-subrc NE 0.
      EXIT. "exit do
    ENDIF.
    LOOP AT lt_find INTO ls_find.
      IF ls_find-offset = 0.
        EXIT. "exit loop
      ENDIF.
* Search an oppened character chain
      FIND ALL OCCURRENCES OF '''' IN lw_command(ls_find-offset)
           RESULTS lt_find_sub.
      IF sy-subrc = 0.
        DESCRIBE TABLE lt_find_sub LINES lw_lines.
        lw_lines = lw_lines MOD 2.
        IF lw_lines = 1. "opened chain, take the next .
          CONTINUE.
        ENDIF.
      ENDIF.
      EXIT. "exit loop
    ENDLOOP.
    IF ls_find-offset GT 0.
      APPEND lw_command(ls_find-offset) TO lt_commands.
    ENDIF.
    ls_find-offset = ls_find-offset + 1.
    lw_command = lw_command+ls_find-offset.
  ENDDO.

* 3 - Search includes
  FIND ALL OCCURRENCES OF REGEX '^INCLUDE[:\s]+([^\s,]+[\s]*,[\s]*|[^\s,]+[\s]*$)' IN TABLE lt_commands
       RESULTS lt_find IGNORING CASE.
  IF sy-subrc = 0.
* for each include found, get source code
    LOOP AT lt_find INTO ls_find.
      READ TABLE lt_commands INTO lw_command INDEX ls_find-line.
      IF sy-subrc NE 0.
        CONTINUE.
      ENDIF.
      READ TABLE ls_find-submatches INTO ls_sub INDEX 1.
      IF sy-subrc NE 0.
        CONTINUE.
      ENDIF.
      lw_command = lw_command+ls_sub-offset.
      SPLIT lw_command AT ',' INTO TABLE lt_prog.
      LOOP AT lt_prog INTO lw_prog.
        CONDENSE lw_prog NO-GAPS.
        lw_prog_c = lw_prog.
        READ TABLE t_include_to_process WITH KEY = lw_prog
                   TRANSPORTING NO FIELDS.
        IF sy-subrc NE 0.
          READ TABLE t_include_processed WITH KEY = lw_prog
                     TRANSPORTING NO FIELDS.
        ENDIF.
        IF sy-subrc NE 0.
          APPEND lw_prog TO t_include_to_process.
        ENDIF.
      ENDLOOP.
    ENDLOOP.
  ENDIF.

ENDFORM. "scan_abap

*&---------------------------------------------------------------------*
*&      Form  GET_REFERENCE
*&---------------------------------------------------------------------*
* Check if an object is generic and return the corresponding generic
* template and the reference name
*----------------------------------------------------------------------*
*      -->FW_OBJ  DSO/cube object to check
*      <--FW_TPL  Generic template. If object name have a common part
*                 you could for example replace common part by xxx
*      <--FW_REF  Reference name. Use here same name as used in P_REF
*----------------------------------------------------------------------*
FORM get_reference USING    fw_obj
                   CHANGING fw_tpl
                            fw_ref LIKE p_ref.
  CLEAR : fw_tpl, fw_ref.

* Please implement here your specific rules to find duplicated objects
* Return the template (ie: the name displayed instead of object)
* and the reference name (ie: same name as used in P_REF)

* Bellow is a simple example
* we have 3 DSO, 1 by region EMEA, NCSA, APAC.
* Called ZDSO1 for EMEA, ZDSO2 for NCSA and ZDOS3 for APAC (yes, with
* an error in name)
*
* if fw_obj = 'ZDSO1'.
*   fw_tpl = 'ZDSOx'.
*   fw_ref = 'EMEA'.
*   return.
* endif.
* if fw_obj = 'ZDSO2'.
*   fw_tpl = 'ZDSOx'.
*   fw_ref = 'NCSA'.
*   return.
* endif.
* if fw_obj = 'ZDOS3'.
*   fw_tpl = 'ZDSOx'. "use same template for all duplicated objects
*   fw_ref = 'APAC'.
*   return.
* endif.

ENDFORM.                    " GET_REFERENCE

*&---------------------------------------------------------------------*
*&      Form  GET_DATAFLOW
*&---------------------------------------------------------------------*
*       Generate dataflow image
*----------------------------------------------------------------------*
*      -->FW_OBJECT  Top level object
*      -->FW_OBJTYPE Top level object type
*      <--FW_IMGURL  Dataflow JPG for the object
*----------------------------------------------------------------------*
FORM get_dataflow USING    fw_object
                           fw_objtype TYPE rstlogo
                  CHANGING fw_imgurl TYPE string.
  DATA : lw_rc     TYPE i.

* For first call, search local temp path
  IF fw_imgurl IS INITIAL.
    CALL METHOD cl_gui_frontend_services=>get_temp_directory
      CHANGING
        temp_dir = fw_imgurl.
    IF fw_imgurl IS INITIAL.
      CALL METHOD cl_gui_frontend_services=>get_sapgui_workdir
        CHANGING
          sapworkdir = fw_imgurl.
    ENDIF.
    IF fw_imgurl IS INITIAL.
      fw_imgurl = cs_custo-dataflow_default_path.
    ENDIF.
    CONCATENATE fw_imgurl '\flowmap.jpg' INTO fw_imgurl.
  ENDIF.

* If a previous flowmap img exists, delete it
  IF cl_gui_frontend_services=>file_exist( fw_imgurl ) = 'X'.
    CALL METHOD cl_gui_frontend_services=>file_delete
      EXPORTING
        filename = fw_imgurl
      CHANGING
        rc       = lw_rc.
  ENDIF.

  s_df-objtp = fw_objtype.
  s_df-object = fw_object.
  s_df-url = fw_imgurl.
  CALL SCREEN 007. "call module GENERATE_DATAFLOW
  RETURN.

ENDFORM.                    " GET_FLOWMAP

*&---------------------------------------------------------------------*
*&      Module  GENERATE_DATAFLOW  OUTPUT
*&---------------------------------------------------------------------*
*       In PBO of screen 007
*       Create the jpg file of the dataflow
*       Then exit from screen 007
*----------------------------------------------------------------------*
MODULE generate_dataflow OUTPUT.

  PERFORM generate_dataflow.

* Exit dummy screen without display
  LEAVE TO SCREEN 0.
ENDMODULE.                 " GENERATE_DATAFLOW  OUTPUT

*&---------------------------------------------------------------------*
*&      Form  IP_LIST
*&---------------------------------------------------------------------*
*       Get list of infopackage for a given datasource
*----------------------------------------------------------------------*
*      -->FW_OBJECT  Current object
*      -->FW_OBJTYP  Current object type
*      -->FW_LOGSYS  System source for datasource
*      -->FW_DS      Datasource
*----------------------------------------------------------------------*
FORM ip_list USING fw_object TYPE string
                   fw_objtyp TYPE rstlogo
                   fw_logsys
                   fw_ds.
  DATA : BEGIN OF ls_ip,
           ip TYPE rsldpio-logdpid,
         END OF ls_ip,
         lt_ip LIKE TABLE OF ls_ip,
         BEGIN OF ls_target,
           selupdic TYPE rsldpsel-selupdic,
         END OF ls_target,
         lt_targets   LIKE TABLE OF ls_target,
         lw_ref_other TYPE c,
         lw_ref_good  TYPE c,
         lw_tpl       TYPE rsdcube-infocube,
         lw_ref       LIKE p_ref.

  REFRESH lt_ip.
  CASE p_ipdisp.
    WHEN c_ip_display_yes.
      SELECT logdpid INTO TABLE lt_ip
             FROM rsldpio
             WHERE objvers = 'A'
             AND logsys = fw_logsys
             AND oltpsource = fw_ds.
    WHEN c_ip_display_chain.
      SELECT logdpid INTO TABLE lt_ip
             FROM rsldpio
             WHERE objvers = 'A'
             AND logsys = fw_logsys
             AND oltpsource = fw_ds
             AND EXISTS ( SELECT *
                          FROM rspcchain
                          WHERE objvers = 'A'
                          AND type = 'LOADING'
                          AND variante = rsldpio~logdpid  ).
    WHEN c_ip_display_node.
      SELECT logdpid INTO TABLE lt_ip
             FROM rsldpio
             WHERE objvers = 'A'
             AND logsys = fw_logsys
             AND oltpsource = fw_ds
             AND EXISTS ( SELECT *
                          FROM rspcchain
                          JOIN rspcchainattr
                          ON rspcchain~chain_id = rspcchainattr~chain_id
                          AND rspcchain~objvers = rspcchainattr~objvers
                          WHERE rspcchain~objvers = 'A'
                          AND rspcchain~type = 'LOADING'
                          AND rspcchain~variante = rsldpio~logdpid
                          AND rspcchainattr~applnm NE '' ).
    WHEN OTHERS.
  ENDCASE.

* Keep only IP if target is generics or reference
  IF NOT p_ref IS INITIAL.
    LOOP AT lt_ip INTO ls_ip.
* Get all targets
      SELECT DISTINCT selupdic
             INTO TABLE lt_targets
             FROM rsldpsel
             WHERE logdpid = ls_ip-ip
             AND objvers = 'A'
             AND selupdic NE space.
* If "all target" is checked, IP must be kept
      IF sy-subrc NE 0.
        CONTINUE.
      ENDIF.

* Search for reference in targets
      CLEAR : lw_ref_good,
              lw_ref_other.
      LOOP AT lt_targets INTO ls_target.
        PERFORM get_reference USING    ls_target-selupdic
                              CHANGING lw_tpl
                                       lw_ref.
        IF lw_ref IS INITIAL.
          CONTINUE.
        ENDIF.
        IF lw_ref = p_ref.
          lw_ref_good = abap_true.
          EXIT. "exit loop
        ELSE.
          lw_ref_other = abap_true.
        ENDIF.
      ENDLOOP.
* Remove infopackage that load other reference but not seleted one
      IF lw_ref_good IS INITIAL AND lw_ref_other = abap_true.
        DELETE lt_ip.
      ENDIF.
    ENDLOOP.
  ENDIF.

  LOOP AT lt_ip INTO ls_ip.
    PERFORM ip USING ls_ip-ip fw_object fw_objtyp fw_ds.
  ENDLOOP.

ENDFORM.                    " IP_LIST

*&---------------------------------------------------------------------*
*&      Form  GENERATE_DATAFLOW
*&---------------------------------------------------------------------*
*       In PBO of screen 007
*       Create the jpg file of the dataflow
*       Then exit from screen 007
*----------------------------------------------------------------------*
FORM generate_dataflow.
  DATA : lo_collect   TYPE REF TO cl_rsawbndf_collect_objects,
         lo_container TYPE REF TO cl_gui_container,
         lo_display   TYPE REF TO cl_rsawbndf_display_df,
         lo_netplan   TYPE REF TO if_gui_rsnetgraphic,
         ls_child     TYPE REF TO cl_gui_control,
         lo_split     TYPE REF TO cl_gui_splitter_container,
         lt_obj       TYPE rsawbn_t_awbobject,
         ls_obj       LIKE LINE OF lt_obj,
         lt_table     TYPE rsng_t_table,
         ls_table     LIKE LINE OF lt_table.

* Create object list
  CREATE OBJECT lo_collect.

* Create container for dataflow
  CREATE OBJECT lo_container
    EXPORTING
      clsid          = space
      container_name = 'CUSTOM'.

* Create display dataflow object
  CREATE OBJECT lo_display
    EXPORTING
      i_r_container          = lo_container
      i_r_cl_collect_objects = lo_collect.

  CASE s_df-objtp.
    WHEN c_iobj
    OR c_multi
    OR c_dso
    OR c_cube
    OR c_iset
    OR c_oh.
      ls_obj-awbobj = s_df-objtp.
    WHEN OTHERS.
      RETURN.
  ENDCASE.

* Build dataflow
  ls_obj-objnm = s_df-object.
  APPEND ls_obj TO lt_obj.

  CALL METHOD lo_collect->set_start_objects
    EXPORTING
      i_t_awbobject = lt_obj.

  CALL METHOD lo_collect->collect_dataflow.

* Create dataflow graphic
  CALL METHOD lo_display->create_graph.

* Get dataflow graphic
  READ TABLE lo_container->children INDEX 1 INTO ls_child.
  lo_split ?= ls_child.

  READ TABLE lo_split->children INDEX 2 INTO ls_child.
  lo_container ?= ls_child.

  READ TABLE lo_container->children INDEX 1 INTO ls_child.
  lo_netplan ?= ls_child.

* Display technical name of objects
  lt_table = lo_netplan->get_all_tables( ).
  LOOP AT lt_table INTO ls_table.
    CALL METHOD ls_table-r_table->set_row_properties
      EXPORTING
        i_rowindex = 2
        i_visible  = abap_true.
* Update table for netplan
    CALL METHOD lo_netplan->add_table
      EXPORTING
        i_r_table = ls_table-r_table.
  ENDLOOP.

* Send table again
  CALL METHOD lo_netplan->send_data_to_frontend.

* Refresh display
  CALL METHOD lo_netplan->arrange_objects.

* Generate JPG
  CALL METHOD lo_netplan->save_as_jpg
    EXPORTING
      i_filename = s_df-url.

* Sync GUI RFC
  CALL METHOD cl_gui_cfw=>flush.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  PROCESS_CHAIN
*&---------------------------------------------------------------------*
*       Display documentation for process chain
*----------------------------------------------------------------------*
*  -->  FW_CHAIN  Process chain name
*----------------------------------------------------------------------*
FORM process_chain USING fw_chain TYPE c.
  DATA : lw_texte      TYPE string,
         lw_chain      TYPE rspc_chain,
         lo_frontend   TYPE REF TO cl_rspc_frontend,
         lw_filename   TYPE string,
         lw_rc         TYPE i,
         lw_filename_c TYPE catfilnam.
  DATA : lt_chains           TYPE rspc_t_chain,
         ls_chains           LIKE LINE OF lt_chains,
         lt_chainattr        TYPE rspc_t_chainattr,
         ls_chainattr        LIKE LINE OF lt_chainattr,
         lt_chaint           TYPE rspc_t_chaint,
         ls_chaint           LIKE LINE OF lt_chaint,
         ls_trigger          TYPE  rspctrigger,
         lo_variant          TYPE REF TO cl_rspc_variant,
         lt_variant_process  TYPE rspc_t_variant,
         ls_variant_process  LIKE LINE OF lt_variant_process,
         ls_variantt         TYPE rspcvariantt,
         lt_variantt_process TYPE rspc_t_variantt,
         BEGIN OF ls_data,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_sub,
           f1(80) TYPE c,
           f2(80) TYPE c,
           f3(80) TYPE c,
           f4(80) TYPE c,
         END OF ls_sub,
         lt_sub LIKE TABLE OF ls_sub,
         lw_xml TYPE string.
* DTP detail data
  DATA: BEGIN OF ls_dtp,
          dtp     TYPE rsbkdtp-dtp,
          src     TYPE rsbkdtp-src,
          srctp   TYPE rsbkdtp-srctlogo,
          tgt     TYPE rsbkdtp-tgt,
          tgttp   TYPE rsbkdtp-tgttlogo,
          updmode TYPE rsbkdtp-updmode,
        END OF ls_dtp,
        lt_range     TYPE rsbk_th_range,
        lt_gf        TYPE rsbk_tx_fields_keyfl,
        lw_txtlg     TYPE rsbkdtpt-txtlg,
        lo_dtp       TYPE REF TO cl_rsbk_dtp,
        lw_domval    TYPE val_text,
        ls_style_box TYPE cl_word=>ty_character_style_effect.
* IP detail data
  DATA : BEGIN OF ls_ip_details,
           infopackage TYPE rsldpio-logdpid,
           infosource  TYPE rsldpio-source,
           datasource  TYPE rsldpio-oltpsource,
           logsys      TYPE rsldpio-logsys,
         END OF ls_ip_details,
         lw_ip_description TYPE rstxtlg,
         lw_hierarchy      TYPE rstxtlg,
         BEGIN OF ls_ip_sel,
           fieldname    TYPE rsldpsel-fieldname,
           iobjnm       TYPE rsldpsel-iobjnm,
           selupdic     TYPE rsldpsel-selupdic,
           ziel         TYPE rsldpsel-ziel,
           init_simu    TYPE rsldpsel-init_simu,
           update_cube  TYPE rsldpsel-update_cube,
           repair_full  TYPE rsldpsel-repair_full,
           inittodelta  TYPE rsldpsel-inittodelta,
           vartyp       TYPE rsldpsel-vartyp,
           bex_variable TYPE rsldpsel-bex_variable,
           hienm        TYPE rsldpsel-hienm,
           hievers      TYPE rsldpsel-hievers,
           hieclass     TYPE rsldpsel-hieclass,
         END OF ls_ip_sel,
         lt_ip_sel LIKE TABLE OF ls_ip_sel,
         ls_option LIKE ls_ip_sel,
         BEGIN OF ls_batch,
           updmode   TYPE rssdbatch-updmode,
           metaupdic TYPE rssdbatch-metaupdic,
         END OF ls_batch.
* Data to get NET_PLAN even if private
  DATA lw_shell TYPE i.
  DATA lo_fake TYPE REF TO lcl_gui_docking_container.
  DATA lo_object TYPE REF TO cl_gui_control.
  DATA lo_net TYPE REF TO cl_gui_rsnetgraphic_netplan.

  CONCATENATE 'Writing Process chain...'(m20)
              fw_chain
              INTO lw_texte SEPARATED BY space.
  PERFORM object_progress_bar USING fw_chain c_chain
                                    lw_texte.

* Generation of the graphic
  lw_chain = fw_chain.
  CREATE OBJECT lo_frontend
    EXPORTING
      i_chain         = lw_chain
      i_mode          = 'PLAN'
      i_display_only  = abap_true
    EXCEPTIONS
      aborted_by_user = 1
      OTHERS          = 2.
  IF sy-subrc NE 0.
    MESSAGE e000(38) WITH
            'Problem when saving picture of the Process Chain.'
            'The PC might be in Display/Change mode'
            'in another window'.
    RETURN.
  ENDIF.

  CALL METHOD lo_frontend->create_net
    EXPORTING
      i_repid = sy-repid
      i_dynnr = sy-dynnr.

* Get NET (private object...)
  CREATE OBJECT lo_fake
    EXPORTING
      repid     = sy-repid
      dynnr     = sy-dynnr
      extension = '1'.
  CALL METHOD lo_fake->get_shellid
    IMPORTING
      shellid = lw_shell.
  CLEAR lo_net.
  DO.
    lw_shell = lw_shell - 1.
    IF lw_shell LE 0.
      EXIT.
    ENDIF.
    CALL METHOD cl_gui_cfw=>get_subscriber_by_id
      EXPORTING
        shellid    = lw_shell
      IMPORTING
        subscriber = lo_object
      EXCEPTIONS
        cntl_error = 1.
    IF sy-subrc = 0.
      TRY.
          lo_net ?= lo_object.
        CATCH cx_sy_move_cast_error.
          sy-subrc = 1.
      ENDTRY.
    ENDIF.
    IF sy-subrc = 0.
      EXIT.
    ENDIF.
  ENDDO.

  IF NOT lo_net IS INITIAL.
* Determinate filename of the process chain graphic
    CALL METHOD cl_gui_frontend_services=>get_temp_directory
      CHANGING
        temp_dir = lw_filename.
    IF lw_filename IS INITIAL.
      CALL METHOD cl_gui_frontend_services=>get_sapgui_workdir
        CHANGING
          sapworkdir = lw_filename.
    ENDIF.
    IF lw_filename IS INITIAL.
      lw_filename = cs_custo-dataflow_default_path.
    ENDIF.
    CONCATENATE lw_filename '\' fw_chain '.jpg' INTO lw_filename.

* If the file exists, delete it
    IF cl_gui_frontend_services=>file_exist( lw_filename ) = 'X'.
      CALL METHOD cl_gui_frontend_services=>file_delete
        EXPORTING
          filename = lw_filename
        CHANGING
          rc       = lw_rc.
    ENDIF.

    lw_filename_c = lw_filename.
    CALL METHOD lo_net->if_gui_rsnetgraphic~save_as_jpg
      EXPORTING
        i_filename = lw_filename_c.
  ENDIF.

* Get Process chain data
  CALL FUNCTION 'RSPC_GET_CHAIN'
    EXPORTING
      i_chain         = lw_chain
    IMPORTING
      e_t_chains      = lt_chains
      e_t_chainattr   = lt_chainattr
      e_t_chaint      = lt_chaint
    EXCEPTIONS
      aborted_by_user = 1
      OTHERS          = 2.
  IF sy-subrc <> 0.
    RETURN.
  ENDIF.
  READ TABLE lt_chainattr INTO ls_chainattr WITH KEY objvers = c_objvers_active.
  READ TABLE lt_chaint INTO ls_chaint WITH KEY langu = c_lang_default
                                               objvers = c_objvers_active.
  IF sy-subrc NE 0.
    READ TABLE lt_chaint INTO ls_chaint WITH KEY objvers = c_objvers_active.
  ENDIF.

* Build document
  CONCATENATE 'Process chain' fw_chain
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cs_custo-style_title1.

* Insert embbeded documents
  PERFORM special_note USING c_chain fw_chain
                             cs_custo-style_title2.

* General informations
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title2.

  CONCATENATE 'Description:' ls_chaint-txtlg
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.

  CONCATENATE 'Node:' ls_chainattr-applnm
              INTO lw_texte SEPARATED BY space.
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = lw_texte
      line_style = cl_word=>c_style_normal.


  READ TABLE lt_chains INTO ls_chains WITH KEY type = 'TRIGGER'.
  IF sy-subrc = 0.

    CALL METHOD cl_rspc_trigger=>get_info_internal
      EXPORTING
        i_variant   = ls_chains-variante
        i_objvers   = c_objvers_active
      IMPORTING
        e_s_trigger = ls_trigger.

    IF ls_trigger-meta = space.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Scheduling: Direct scheduling'
          line_style = cl_word=>c_style_normal.

      IF ls_trigger-periodic NE space.
        IF ls_trigger-prdmonths EQ 1.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = 'Period: Monthly'
              line_style = cl_word=>c_style_normal.
        ELSEIF ls_trigger-prdweeks EQ 1.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = 'Period: Weekly'
              line_style = cl_word=>c_style_normal.
        ELSEIF ls_trigger-prddays EQ 1.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = 'Period: Daily'
              line_style = cl_word=>c_style_normal.
        ELSEIF ls_trigger-prdhours EQ 1.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = 'Period: Hourly'
              line_style = cl_word=>c_style_normal.
        ELSE.
          lw_texte = 'Period: '.
          IF ls_trigger-prdmonths GT 0.
            CONCATENATE lw_texte ls_trigger-prdmonths 'Months'
                        INTO lw_texte SEPARATED BY space.
          ENDIF.
          IF ls_trigger-prdweeks GT 0.
            CONCATENATE lw_texte ls_trigger-prdweeks 'Weeks'
                        INTO lw_texte SEPARATED BY space.
          ENDIF.
          IF ls_trigger-prddays GT 0.
            CONCATENATE lw_texte ls_trigger-prddays 'Days'
                        INTO lw_texte SEPARATED BY space.
          ENDIF.
          IF ls_trigger-prdhours GT 0.
            CONCATENATE lw_texte ls_trigger-prdhours 'Hours'
                        INTO lw_texte SEPARATED BY space.
          ENDIF.
          IF ls_trigger-prdmins GT 0.
            CONCATENATE lw_texte ls_trigger-prdmins 'Minuts'
                        INTO lw_texte SEPARATED BY space.
          ENDIF.
        ENDIF.
      ENDIF.
    ELSE.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = 'Scheduling: Start using Meta Chain or API'
          line_style = cl_word=>c_style_normal.
    ENDIF.
  ENDIF.


* Process chain graphic
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Graphic'
      line_style = cs_custo-style_title2.

  CALL METHOD o_doc->insert_image
    EXPORTING
      url = lw_filename.

* Process list
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'List of process'
      line_style = cs_custo-style_title2.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1-textline = 'Type'.
  ls_data-f2-textline = 'Variant'.
  ls_data-f3-textline = 'Description'.
  ls_data-f4-textline = 'Details'.
  APPEND ls_data TO lt_data.

  LOOP AT lt_chains INTO ls_chains.
    IF ls_chains-type = 'TRIGGER'
    OR ls_chains-type = 'AND'
    OR ls_chains-type = 'OR'.
      CONTINUE.
    ENDIF.

    CALL METHOD cl_rspc_variant=>create
      EXPORTING
        i_type         = ls_chains-type
        i_variant      = ls_chains-variante
        i_no_transport = abap_true
      RECEIVING
        r_r_variant    = lo_variant.

    CALL METHOD lo_variant->get_info
      IMPORTING
        e_t_rspcvariant  = lt_variant_process
        e_s_rspcvariantt = ls_variantt
        e_t_rspcvariantt = lt_variantt_process.

* Free loaded object
    CALL METHOD lo_variant->free.

    CLEAR ls_data.
    ls_data-f1-textline = ls_chains-type.
    ls_data-f2-textline = ls_chains-variante.
    ls_data-f3-textline = ls_variantt-txtlg.

    REFRESH lt_sub.
    CASE ls_chains-type.
      WHEN 'CHAIN'.
        SELECT SINGLE txtlg
               INTO ls_variantt-txtlg
               FROM rspcchaint
               WHERE langu = c_lang_default
               AND chain_id = ls_chains-variante
               AND objvers = c_objvers_active.
        ls_data-f3-textline = ls_variantt-txtlg.
      WHEN 'LOADING'.
* name, full, selection, target, source
* Get some IP information
        SELECT SINGLE logdpid source oltpsource logsys
               INTO ls_ip_details
               FROM rsldpio
               WHERE logdpid = ls_chains-variante
               AND objvers = c_objvers_active.
        SELECT SINGLE text INTO lw_ip_description
               FROM rsldpiot
                 WHERE langu = c_lang_default
                 AND logdpid = ls_ip_details-infopackage
                 AND objvers = c_objvers_active.
        IF sy-subrc NE 0.
          SELECT SINGLE text INTO lw_ip_description
                 FROM rsldpiot
                   WHERE logdpid = ls_ip_details-infopackage
                   AND objvers = c_objvers_active.
        ENDIF.
        SELECT SINGLE updmode metaupdic
               INTO ls_batch
               FROM rssdbatch
               WHERE logid = ls_ip_details-infopackage
               AND objvers = c_objvers_active.
        SELECT fieldname iobjnm selupdic ziel init_simu
               update_cube repair_full inittodelta vartyp bex_variable
               hienm hievers hieclass
               INTO TABLE lt_ip_sel
               FROM rsldpsel
               WHERE logdpid = ls_ip_details-infopackage
               AND objvers = c_objvers_active.
        CLEAR ls_option.
        READ TABLE lt_ip_sel INTO ls_option INDEX 1.
        IF ls_option-hienm NE space.
          SELECT SINGLE txtlg INTO lw_hierarchy
                 FROM rsosohiet
                 WHERE langu = c_lang_default
                 AND osource = ls_ip_details-datasource
                 AND objvers = c_objvers_active
                 AND hienm = ls_option-hienm
                 AND hievers = ls_option-hievers
                 AND hieclass = ls_option-hieclass.
          IF sy-subrc NE 0.
            SELECT SINGLE txtlg INTO lw_hierarchy
                   FROM rsosohiet
                   WHERE osource = ls_ip_details-datasource
                   AND objvers = c_objvers_active
                   AND hienm = ls_option-hienm
                   AND hievers = ls_option-hievers
                   AND hieclass = ls_option-hieclass.
          ENDIF.
        ENDIF.

* IP Name
        ls_data-f3-textline = lw_ip_description.
* IP Mode
        CASE ls_batch-updmode.
          WHEN 'F'.
            lw_texte = 'Full'.
          WHEN 'C'.
            IF ls_option-init_simu = space.
              lw_texte = 'Init'.
            ELSE.
              lw_texte = 'Init without data transfer'.
            ENDIF.
          WHEN 'D'.
            lw_texte = 'Delta'.
          WHEN 'I'.
            lw_texte = 'Transfer of an opening balance for non-cumulative values'.
          WHEN OTHERS.
            lw_texte = '???'.
        ENDCASE.
        CONCATENATE 'Update mode:' lw_texte
                    INTO lw_texte SEPARATED BY space.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = lw_texte
          IMPORTING
            virtual  = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        CALL METHOD o_doc->write_break
          CHANGING
            virtual = ls_data-f4-xml.

* Targets
        CLEAR lw_texte.
        LOOP AT lt_ip_sel INTO ls_ip_sel WHERE NOT selupdic IS INITIAL.
          IF lw_texte IS INITIAL.
            lw_texte = ls_ip_sel-selupdic.
          ELSE.
            CONCATENATE lw_texte ls_ip_sel-selupdic
                        INTO lw_texte SEPARATED BY ', '.
          ENDIF.
        ENDLOOP.
        IF lw_texte IS INITIAL.
          lw_texte = 'Targets: All'.
        ELSE.
          CONCATENATE 'Targets:' lw_texte
                      INTO lw_texte SEPARATED BY space.
        ENDIF.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = lw_texte
          IMPORTING
            virtual  = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        CALL METHOD o_doc->write_break
          CHANGING
            virtual = ls_data-f4-xml.

* Filter
        ls_style_box-font = cl_word=>c_font_symbol.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = 'Filter: '
          IMPORTING
            virtual  = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        LOOP AT lt_ip_sel INTO ls_ip_sel WHERE NOT fieldname IS INITIAL
                           OR NOT iobjnm IS INITIAL.
          EXIT.
        ENDLOOP.
        IF sy-subrc NE 0.
          lw_texte = cl_word=>c_symbol_checkbox.
        ELSE.
          lw_texte = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline     = lw_texte
            style_effect = ls_style_box
          IMPORTING
            virtual      = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.

* Hierarchy
        IF ls_option-hienm NE space.
          CALL METHOD o_doc->write_break
            CHANGING
              virtual = ls_data-f4-xml.
          CONCATENATE 'Hierarchy:' lw_hierarchy
                      INTO lw_texte SEPARATED BY space.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline = lw_texte
            IMPORTING
              virtual  = lw_xml.
          CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        ENDIF.

      WHEN 'DTP_LOAD'.
* Get some DTP information
        SELECT SINGLE dtp src srctlogo tgt tgttlogo updmode
                INTO ls_dtp
                FROM rsbkdtp
                WHERE dtp = ls_chains-variante
                AND   objvers = 'A'.

        SELECT SINGLE txtlg INTO lw_txtlg
               FROM rsbkdtpt
               WHERE langu = c_lang_default
               AND   dtp = ls_dtp-dtp
               AND   objvers = 'A'.
        IF sy-subrc NE 0 OR lw_txtlg IS INITIAL.
          CONCATENATE ls_dtp-src '=>' ls_dtp-tgt INTO lw_txtlg SEPARATED BY space.
          CONDENSE lw_txtlg.
        ENDIF.

        CALL METHOD cl_rsbk_dtp=>factory
          EXPORTING
            i_dtp   = ls_dtp-dtp
          RECEIVING
            r_r_dtp = lo_dtp.

        REFRESH lt_range.
        lt_range = lo_dtp->if_rsbk_dtp_display~get_th_range( i_with_variables = rs_c_true ).

        REFRESH lt_gf.
        CALL METHOD lo_dtp->get_groupfields
          IMPORTING
            e_t_groupfields = lt_gf.

* DTP Name
        ls_data-f3-textline = lw_txtlg.

* DTP Mode
        PERFORM get_domain_value USING 'RSBKUPDMODE'
                                       ls_dtp-updmode
                                 CHANGING lw_domval.
        CONCATENATE 'Extraction mode:' lw_domval
                    INTO lw_texte SEPARATED BY space.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = lw_texte
          IMPORTING
            virtual  = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        CALL METHOD o_doc->write_break
          CHANGING
            virtual = ls_data-f4-xml.

* Filter
        ls_style_box-font = cl_word=>c_font_symbol.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = 'Filter: '
          IMPORTING
            virtual  = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        IF lt_range[] IS INITIAL.
          lw_texte = cl_word=>c_symbol_checkbox.
        ELSE.
          lw_texte = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline     = lw_texte
            style_effect = ls_style_box
          IMPORTING
            virtual      = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        CALL METHOD o_doc->write_break
          CHANGING
            virtual = ls_data-f4-xml.

* Semantic group
        CALL METHOD o_doc->write_text
          EXPORTING
            textline = 'Semantic group: '
          IMPORTING
            virtual  = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        IF lt_gf[] IS INITIAL.
          lw_texte = cl_word=>c_symbol_checkbox.
        ELSE.
          lw_texte = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        CALL METHOD o_doc->write_text
          EXPORTING
            textline     = lw_texte
            style_effect = ls_style_box
          IMPORTING
            virtual      = lw_xml.
        CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.

      WHEN OTHERS.
* For all process (except dtp, IP, chain), display all non-empty options
* values (1 option by line)
        LOOP AT lt_variant_process INTO ls_variant_process
        WHERE low NE space OR high NE space.
          CLEAR ls_sub.
          IF NOT ls_data-f4-xml IS INITIAL.
            CALL METHOD o_doc->write_break
              CHANGING
                virtual = ls_data-f4-xml.
          ENDIF.
          CLEAR lw_texte.
          PERFORM selopt_to_text USING ls_variant_process-fnam
                                       ls_variant_process-sign
                                       ls_variant_process-opt
                                       ls_variant_process-low
                                       ls_variant_process-high
                                 CHANGING lw_texte.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline = lw_texte
            IMPORTING
              virtual  = lw_xml.
          CONCATENATE ls_data-f4-xml lw_xml INTO ls_data-f4-xml.
        ENDLOOP.
    ENDCASE.
    IF NOT ls_data-f4-xml IS INITIAL.
      CALL METHOD o_doc->write_line
        CHANGING
          virtual = ls_data-f4-xml.
    ENDIF.
    APPEND ls_data TO lt_data.
  ENDLOOP.
  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_with_head.

* Write documentation for each sub-chain
  LOOP AT lt_chains INTO ls_chains WHERE type = 'CHAIN'.
    PERFORM process_chain USING ls_chains-variante.
  ENDLOOP.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  selopt_to_text
*&---------------------------------------------------------------------*
*       Transform select option line to comprehensive text
*----------------------------------------------------------------------*
*  -->  FW_FIELD  Field
*  -->  FW_SIGN   Sign
*  -->  FW_OPT    Option
*  -->  FW_LOW    Low value
*  -->  FW_HIGH   High value
*  <--  FW_TEXT   Select-option translation text
*----------------------------------------------------------------------*
FORM selopt_to_text USING fw_field TYPE c
                          fw_sign TYPE c
                          fw_opt TYPE c
                          fw_low TYPE c
                          fw_high TYPE c
                    CHANGING fw_text TYPE string.
  CLEAR fw_text.

  IF fw_sign = 'E'.
    CONCATENATE 'not' fw_field INTO fw_text SEPARATED BY space.
  ELSE.
    fw_text = fw_field.
  ENDIF.

  CASE fw_opt.
    WHEN 'EQ' OR space.
      CONCATENATE fw_text '=' fw_low INTO fw_text
                  SEPARATED BY space.
    WHEN 'BT'.
      CONCATENATE fw_text 'between' fw_low 'and' fw_high
                  INTO fw_text SEPARATED BY space.
    WHEN 'GT'.
      CONCATENATE fw_text '>' fw_low INTO fw_text
                  SEPARATED BY space.
    WHEN 'GE'.
      CONCATENATE fw_text '>=' fw_low INTO fw_text
                  SEPARATED BY space.
    WHEN 'LT'.
      CONCATENATE fw_text '<' fw_low INTO fw_text
                  SEPARATED BY space.
    WHEN 'LE'.
      CONCATENATE fw_text '<=' fw_low INTO fw_text
                  SEPARATED BY space.
    WHEN 'CP'.
      CONCATENATE fw_text 'contain' fw_low INTO fw_text
                  SEPARATED BY space.
    WHEN 'NE'.
      CONCATENATE fw_text '<>' fw_low INTO fw_text
            SEPARATED BY space.
    WHEN 'NB'.
      CONCATENATE fw_text 'not between' fw_low 'and' fw_high
                  INTO fw_text SEPARATED BY space.
    WHEN 'NP'.
      CONCATENATE fw_text 'contain not' fw_low INTO fw_text
                  SEPARATED BY space.
  ENDCASE.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  GET_IOBJ_TEXT
*&---------------------------------------------------------------------*
*       Get info object label
*----------------------------------------------------------------------*
*      -->FW_IOBJNM  Info Object
*      <--FW_TXTLG   Info object long text
*----------------------------------------------------------------------*
FORM get_iobj_text  USING    fw_iobjnm TYPE c
                    CHANGING fw_txtlg TYPE rstxtlg.
  DATA : lw_iobjnm   TYPE rsd_iobjnm,
         ls_iobj     TYPE rsd_s_viobj,
         lw_dummy(1) TYPE c.
  lw_iobjnm = fw_iobjnm.
  IF fw_iobjnm IS INITIAL.
    RETURN.
  ENDIF.
  CALL FUNCTION 'RSD_IOBJ_GET'
    EXPORTING
      i_iobjnm       = lw_iobjnm
    IMPORTING
      e_s_viobj      = ls_iobj
    EXCEPTIONS
      iobj_not_found = 1.
  IF sy-subrc NE 0 AND fw_iobjnm CS '__'.
    SPLIT fw_iobjnm AT '__' INTO lw_dummy lw_iobjnm.
    CALL FUNCTION 'RSD_IOBJ_GET'
      EXPORTING
        i_iobjnm       = lw_iobjnm
      IMPORTING
        e_s_viobj      = ls_iobj
      EXCEPTIONS
        iobj_not_found = 1.
  ENDIF.

  fw_txtlg = ls_iobj-txtlg.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  GET_QUERY_ELEM_LBL
*&---------------------------------------------------------------------*
*       Calculate formated text for a query element
*----------------------------------------------------------------------*
*      -->FW_ELTUID  Id of the query element
*      -->FT_ELTDIR  Table of query elements
*      -->FT_RANGE   Table of range properties
*      -->FT_VAR     Table of vars
*      -->FT_SELECT  Table of selects
*      -->FT_COMPDIR Table of compdir
*      <--FW_TEXTE   Label of the query element
*      <--FS_ELTDIR  Query element infos
*----------------------------------------------------------------------*
FORM get_query_elem_lbl  USING    fw_eltuid TYPE rsz_x_eltdir-eltuid
                                  ft_eltdir TYPE rsza_t_eltdir
                                  ft_range TYPE rsza_t_range
                                  ft_var TYPE rsza_t_var
                                  ft_select TYPE rsza_t_select
                                  ft_compdir TYPE rsza_t_compdir
                         CHANGING fw_texte TYPE string
                                  fs_eltdir TYPE rsz_x_eltdir.
  DATA : ls_range  LIKE LINE OF ft_range,
         ls_select LIKE LINE OF ft_select.

  CLEAR : fs_eltdir,
          fw_texte.

  READ TABLE ft_eltdir INTO fs_eltdir WITH KEY eltuid = fw_eltuid.
  IF sy-subrc NE 0.
    RETURN.
  ENDIF.

  IF fs_eltdir-subdeftp = 'CHA' AND fs_eltdir-defaulttext = 'X'.
    PERFORM get_iobj_text USING fs_eltdir-defaulthint
                          CHANGING fs_eltdir-txtlg.
    CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
    CONCATENATE fw_texte fs_eltdir-defaulthint ']' INTO fw_texte.
    RETURN.
  ENDIF.

  IF fs_eltdir-subdeftp = 'CHA' AND NOT fs_eltdir-txtlg IS INITIAL.
    READ TABLE ft_select INTO ls_select WITH KEY eltuid = fw_eltuid.
    IF sy-subrc = 0 AND NOT ls_select-iobjnm IS INITIAL.
      fs_eltdir-mapname = ls_select-iobjnm.
      CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
      CONCATENATE fw_texte fs_eltdir-mapname ']' INTO fw_texte.
      RETURN.
    ENDIF.
  ENDIF.

  IF fs_eltdir-deftp = 'STR'.
    IF fs_eltdir-defaulthint = '1KYFNM'.
      fs_eltdir-txtlg = 'Key figure'.
    ELSE.
      fs_eltdir-txtlg = 'Structure'.
    ENDIF.
    IF NOT fs_eltdir-mapname IS INITIAL.
      fs_eltdir-defaulthint = fs_eltdir-mapname.
    ENDIF.
    IF fs_eltdir-defaulthint IS INITIAL.
      fw_texte = fs_eltdir-txtlg.
    ELSE.
      CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
      CONCATENATE fw_texte fs_eltdir-defaulthint ']' INTO fw_texte.
    ENDIF.
    RETURN.
  ENDIF.

  IF fs_eltdir-deftp = 'SEL'.
    IF fs_eltdir-defaulttext = 'X'
    AND NOT fs_eltdir-defaulthint IS INITIAL.
      PERFORM get_iobj_text USING fs_eltdir-defaulthint
                            CHANGING fs_eltdir-txtlg.
      IF NOT fs_eltdir-txtlg IS INITIAL.
        CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
        CONCATENATE fw_texte fs_eltdir-defaulthint ']' INTO fw_texte.
        RETURN.
      ENDIF.
    ENDIF.

    READ TABLE ft_range INTO ls_range
               WITH KEY eltuid = fw_eltuid
               enum = '0001'.
    IF sy-subrc = 0.

      PERFORM get_range_text USING ft_eltdir[]
                                   ft_var[]
                                   ft_compdir[]
                                   fs_eltdir
                             CHANGING ls_range.





      fw_texte = ls_range-lowtxtlg.
      IF NOT ls_range-hightxtlg IS INITIAL.
        CONCATENATE fw_texte '-' ls_range-hightxtlg INTO fw_texte.
      ENDIF.

      READ TABLE ft_range TRANSPORTING NO FIELDS
                 WITH KEY eltuid = fw_eltuid
                          enum = '0002'.
      IF sy-subrc = 0.
        CONCATENATE fw_texte ',...' INTO fw_texte.
      ENDIF.
      RETURN.
    ELSE.
      READ TABLE ft_select INTO ls_select WITH KEY eltuid = fw_eltuid.
      IF sy-subrc = 0 AND NOT ls_select-iobjnm IS INITIAL.
        fs_eltdir-mapname = ls_select-iobjnm.
      ENDIF.
      IF fs_eltdir-txtlg IS INITIAL.
        fs_eltdir-txtlg = 'TODO'. "Not managed case, never append...
      ENDIF.
      IF NOT fs_eltdir-mapname IS INITIAL.
        fs_eltdir-defaulthint = fs_eltdir-mapname.
      ENDIF.
      CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
      CONCATENATE fw_texte fs_eltdir-defaulthint ']' INTO fw_texte.
      RETURN.
    ENDIF.
  ENDIF.

  IF fs_eltdir-deftp = 'FML'.
    CONCATENATE 'Formula' fs_eltdir-txtlg
                INTO fs_eltdir-txtlg SEPARATED BY space.
    IF NOT fs_eltdir-mapname IS INITIAL.
      fs_eltdir-defaulthint = fs_eltdir-mapname.
    ENDIF.
    IF NOT fs_eltdir-defaulthint IS INITIAL.
      CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
      CONCATENATE fw_texte fs_eltdir-defaulthint ']' INTO fw_texte.
    ELSE.
      fw_texte = fs_eltdir-txtlg.
    ENDIF.
    RETURN.
  ENDIF.

  IF fs_eltdir-deftp = 'SOB'.
* This case may not append because txtlg filled or subtp may be CHA
    IF NOT fs_eltdir-mapname IS INITIAL.
      fs_eltdir-defaulthint = fs_eltdir-mapname.
    ENDIF.
    CONCATENATE fs_eltdir-txtlg '[' INTO fw_texte SEPARATED BY space.
    CONCATENATE fw_texte fs_eltdir-defaulthint ']' INTO fw_texte.
    RETURN.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  GET_ELMT_CHILD
*&---------------------------------------------------------------------*
*       Find childrens to build node table
*----------------------------------------------------------------------*
*      -->FW_LEVEL Current level
*      <--FT_NODE  Table of nodes
*      <--FW_ID    Id of the parent
*      <--FW_ORDER Position of the node
*----------------------------------------------------------------------*
FORM get_elmt_child USING fw_level TYPE i
                    CHANGING ft_node TYPE table
                             fw_id TYPE rsz_x_eltdir-eltuid
                             fw_order TYPE i.

  DATA : BEGIN OF ls_node,
           hier   TYPE rsz_x_eltdir-eltuid,
           id     TYPE rsz_x_eltdir-eltuid,
           parent TYPE rsz_x_eltdir-eltuid,
           order  TYPE i,
           level  TYPE i,
         END OF ls_node,
         lt_node  LIKE TABLE OF ls_node,
         lw_level TYPE i.
  FIELD-SYMBOLS <fs> LIKE ls_node.

  lt_node[] = ft_node[].
  lw_level = fw_level + 1.

  DO.
    READ TABLE lt_node ASSIGNING <fs> WITH KEY parent = fw_id
                                               order = 0.
    IF sy-subrc NE 0.
      EXIT. "exit do
    ENDIF.
    <fs>-order = fw_order.
    <fs>-level = lw_level.
    ADD 1 TO fw_order.
    PERFORM get_elmt_child USING lw_level
                           CHANGING lt_node[]
                                    <fs>-id
                                    fw_order.
  ENDDO.

  ft_node[] = lt_node[].
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  GET_RANGE_TEXT
*&---------------------------------------------------------------------*
*       Format range texts for display
*----------------------------------------------------------------------*
*      -->FT_ELTDIR  Table of elements
*      -->FT_VAR     Table of vars
*      -->FT_COMPDIR Table of compdir
*      -->FS_REF     Current element (optional)
*      <->FS_RANGE   Range formated
*----------------------------------------------------------------------*
FORM get_range_text  USING    ft_eltdir TYPE rsza_t_eltdir
                              ft_var TYPE rsza_t_var
                              ft_compdir TYPE rsza_t_compdir
                              fs_ref TYPE rsz_x_eltdir
                     CHANGING fs_range TYPE rsz_x_range.
  DATA : ls_eltdir  LIKE LINE OF ft_eltdir,
         ls_var     LIKE LINE OF ft_var,
         ls_compdir LIKE LINE OF ft_compdir.

  IF fs_range-lowflag = '3'.
    READ TABLE ft_eltdir INTO ls_eltdir
                         WITH KEY eltuid = fs_range-low.
    READ TABLE ft_var INTO ls_var
                      WITH KEY varuniid = fs_range-low.
    fs_range-low = ls_var-vnam.
    fs_range-lowtxtlg = ls_eltdir-txtlg.
  ELSEIF fs_range-lowflag = '2'.
    READ TABLE ft_eltdir INTO ls_eltdir
                         WITH KEY eltuid = fs_range-low.
* If no technical name, try to find him in comp table
    IF ls_eltdir-mapname IS INITIAL.
      READ TABLE ft_compdir INTO ls_compdir
                            WITH KEY compuid = fs_range-low.
      IF sy-subrc = 0 AND NOT ls_compdir-compid IS INITIAL.
        fs_range-low = ls_compdir-compid.
      ELSE.
        fs_range-low = ls_eltdir-mapname.
      ENDIF.
    ELSE.
      fs_range-low = ls_eltdir-mapname.
    ENDIF.
    IF fs_ref-defaulttext = 'X' OR fs_ref-txtlg IS INITIAL.
      fs_range-lowtxtlg = ls_eltdir-txtlg.
    ELSE.
      fs_range-lowtxtlg = fs_ref-txtlg.
    ENDIF.
  ENDIF.
  IF fs_range-highflag = '3'.
    READ TABLE ft_eltdir INTO ls_eltdir
                         WITH KEY eltuid = fs_range-high.
    READ TABLE ft_var INTO ls_var
                      WITH KEY varuniid = fs_range-high.
    fs_range-high = ls_var-vnam.
    fs_range-hightxtlg = ls_eltdir-txtlg.
  ELSEIF fs_range-highflag = '2'.
    READ TABLE ft_eltdir INTO ls_eltdir
                         WITH KEY eltuid = fs_range-high.
    fs_range-high = ls_eltdir-mapname.
    fs_range-hightxtlg = ls_eltdir-txtlg.
  ENDIF.
  IF fs_range-lowtxtlg NE fs_range-low.
    CONCATENATE fs_range-lowtxtlg '['
                INTO fs_range-lowtxtlg SEPARATED BY space.
    CONCATENATE fs_range-lowtxtlg fs_range-low ']'
                INTO fs_range-lowtxtlg.
  ENDIF.
  IF NOT fs_range-high IS INITIAL
  AND fs_range-hightxtlg NE fs_range-high.
    CONCATENATE fs_range-hightxtlg '['
                INTO fs_range-hightxtlg SEPARATED BY space.
    CONCATENATE fs_range-hightxtlg fs_range-high ']'
                INTO fs_range-hightxtlg.
  ENDIF.
  IF NOT fs_range-shiftlow IS INITIAL
  AND fs_range-shiftlow NE '0'.
    IF fs_range-shiftlow CS '-'.
      TRANSLATE fs_range-shiftlow USING '- '.
      CONCATENATE fs_range-lowtxtlg '-' fs_range-shiftlow
                  INTO fs_range-lowtxtlg.
    ELSE.
      CONCATENATE fs_range-lowtxtlg '+' fs_range-shiftlow
                  INTO fs_range-lowtxtlg.
    ENDIF.
  ENDIF.
  IF NOT fs_range-shifthigh IS INITIAL
  AND fs_range-shifthigh NE '0'.
    IF fs_range-shifthigh CS '-'.
      TRANSLATE fs_range-shifthigh USING '- '.
      CONCATENATE fs_range-hightxtlg '-' fs_range-shifthigh
                  INTO fs_range-hightxtlg.
    ELSE.
      CONCATENATE fs_range-hightxtlg '+' fs_range-shifthigh
                  INTO fs_range-hightxtlg.
    ENDIF.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  PROCESS_INCLUDES
*&---------------------------------------------------------------------*
*       Display all includes found in code
*----------------------------------------------------------------------*
FORM process_includes.
  DATA : lw_include   LIKE LINE OF t_include_to_process,
         lw_include_c TYPE progname,
         lt_abap      TYPE TABLE OF string.

  IF t_include_to_process[] IS INITIAL.
    RETURN.
  ENDIF.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Include list'
      line_style = cs_custo-style_title1.

  WHILE NOT t_include_to_process IS INITIAL.
    READ TABLE t_include_to_process INTO lw_include INDEX 1.
    IF sy-subrc NE 0.
      EXIT. "exit while
    ENDIF.
    APPEND lw_include TO t_include_processed.
    DELETE t_include_to_process INDEX 1.
    lw_include_c = lw_include.
    REFRESH lt_abap.
    READ REPORT lw_include_c INTO lt_abap.
    IF NOT lt_abap[] IS INITIAL.
      CONCATENATE 'Include' lw_include_c
                  INTO lw_include SEPARATED BY space.
      CALL METHOD o_doc->write_text
        EXPORTING
          textline   = lw_include
          line_style = cs_custo-style_title2.

      PERFORM code_display USING lt_abap.
    ENDIF.
  ENDWHILE.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  HOWTO_GENERATE
*&---------------------------------------------------------------------*
*       Display a How to generate appendix
*----------------------------------------------------------------------*
FORM howto_generate.
  DATA : BEGIN OF ls_data,
           f1(80) TYPE c,
           f2(80) TYPE c,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_info,
           flag    TYPE c,
           olength TYPE x,
           line    TYPE raldb-infoline,
         END OF ls_info,
         lt_info LIKE TABLE OF ls_info.

  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'How to regenerate this documentation'
      line_style = cs_custo-style_title1.

* Write general informations
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'General informations'
      line_style = cs_custo-style_title2.
  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1 = 'BW system used'.
  CONCATENATE sy-sysid sy-mandt INTO ls_data-f2 SEPARATED BY space.
  APPEND ls_data TO lt_data.

  IF sy-tcode = 'SE38'
  OR sy-tcode = 'SA38'
  OR sy-tcode = 'SE80'
  OR sy-tcode = 'SE93'.
    CLEAR ls_data.
    ls_data-f1 = 'Program to execute'.
    ls_data-f2 = sy-repid.
    APPEND ls_data TO lt_data.
  ELSE.
    CLEAR ls_data.
    ls_data-f1 = 'Transaction to execute'.
    ls_data-f2 = sy-tcode.
    APPEND ls_data TO lt_data.
  ENDIF.
  CLEAR ls_data.
  ls_data-f1 = 'Generation date'.
  CONCATENATE sy-datum+6(2) sy-datum+4(2) sy-datum(4)
              INTO ls_data-f2 SEPARATED BY '.'.
  APPEND ls_data TO lt_data.

  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_without_head.

* Read selection screen
  CALL FUNCTION 'PRINT_SELECTIONS'
    EXPORTING
      mode      = 'TABLE'
      rname     = sy-cprog
      rvariante = sy-slset
    TABLES
      infotab   = lt_info.

* Write selection screen parameters values
  CALL METHOD o_doc->write_text
    EXPORTING
      textline   = 'Selection screen'
      line_style = cs_custo-style_title2.

  REFRESH lt_data.
  CLEAR ls_data.
  ls_data-f1 = 'Parameter'.
  ls_data-f2 = 'Value'.
  APPEND ls_data TO lt_data.

  CLEAR ls_data.
  LOOP AT lt_info INTO ls_info FROM 6.
    IF NOT ls_info-line+2(1) IS INITIAL.
      CLEAR ls_data.
      ls_data-f1 = ls_info-line+2(20).
    ELSE.
      IF ls_info-line CO ' |' OR ls_info-line+38(1) = space.
        CLEAR ls_data.
      ELSE.
        CASE ls_data-f1.
          WHEN 'Folder where save do'.
            ls_data-f2 = p_file.
          WHEN 'Main object'.
            ls_data-f2 = p_main.
          WHEN 'Flow name'.
            ls_data-f2 = p_flow.
          WHEN OTHERS.
            ls_data-f2 = ls_info-line+1(77).
            CONDENSE ls_data-f2.
        ENDCASE.
        APPEND ls_data TO lt_data.
      ENDIF.
    ENDIF.
  ENDLOOP.
  CALL METHOD o_doc->write_table
    EXPORTING
      content = lt_data
      style   = cs_custo-table_with_head.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  GET_IPROV_TYPE
*&---------------------------------------------------------------------*
*       Search infoprovider type from his name
*----------------------------------------------------------------------*
*      -->FW_IPROV Infoprovider name
*      <--FW_TYPE  Infoprovider type
*----------------------------------------------------------------------*
FORM get_iprov_type  USING    fw_iprov TYPE rsinfocube
                     CHANGING fw_type TYPE rstlogo.
  DATA lw_iprov TYPE string.

  CLEAR fw_type.

* Infocube or Multiprovider ?
  SELECT SINGLE cubetype
         INTO lw_iprov
         FROM rsdcube
         WHERE infocube = fw_iprov
         AND objvers = c_objvers_active.
  IF sy-subrc = 0.
    IF lw_iprov = 'M'.
      fw_type = c_multi.
    ELSE.
      fw_type = c_cube.
    ENDIF.
  ENDIF.

* DSO ?
  IF fw_type IS INITIAL.
    SELECT SINGLE odsobject
           INTO lw_iprov
           FROM rsdodso
           WHERE odsobject = fw_iprov
           AND objvers = c_objvers_active.
    IF sy-subrc = 0.
      fw_type = c_dso.
    ENDIF.
  ENDIF.

* Info Object ?
  IF fw_type IS INITIAL.
    SELECT SINGLE iobjnm
           INTO lw_iprov
           FROM rsdiobj
           WHERE iobjnm = fw_iprov
           AND objvers = c_objvers_active.
    IF sy-subrc = 0.
      fw_type = c_iobj.
    ENDIF.
  ENDIF.

* Infoset ?
  IF fw_type IS INITIAL.
    SELECT SINGLE infoset
           INTO lw_iprov
           FROM rsqiset
           WHERE infoset = fw_iprov
           AND objvers = c_objvers_active.
    IF sy-subrc = 0.
      fw_type = c_iset.
    ENDIF.
  ENDIF.

* Open Hub Destination
  IF fw_type IS INITIAL.
    SELECT SINGLE ohdest
           INTO lw_iprov
           FROM rsbohdest
           WHERE ohdest = fw_iprov
           AND objvers = c_objvers_active.
    IF sy-subrc = 0.
      fw_type = c_oh.
    ENDIF.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  openhub
*&---------------------------------------------------------------------*
*       Display documentation for an Open Hub Destination
*----------------------------------------------------------------------*
*  -->  fw_open    Open Hub Destination
*----------------------------------------------------------------------*
FORM openhub USING fw_open TYPE string.
  DATA : lo_open      TYPE REF TO cl_rsb_dest,
         ls_dest      TYPE rsbo_s_vdest,
         lt_field     TYPE rsbgui_t_fields,
         ls_field     LIKE LINE OF lt_field,
         lt_field_txt TYPE rsbgui_t_field_text,
         ls_field_txt LIKE LINE OF lt_field_txt,
         lw_domval    TYPE val_text,
         lw_texte     TYPE string,
         BEGIN OF ls_data,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
         END OF ls_data,
         lt_data LIKE TABLE OF ls_data,
         BEGIN OF ls_fieldtab,
           f1 TYPE cl_word=>ty_table_style_field,
           f2 TYPE cl_word=>ty_table_style_field,
           f3 TYPE cl_word=>ty_table_style_field,
           f4 TYPE cl_word=>ty_table_style_field,
           f5 TYPE cl_word=>ty_table_style_field,
           f6 TYPE cl_word=>ty_table_style_field,
           f7 TYPE cl_word=>ty_table_style_field,
           f8 TYPE cl_word=>ty_table_style_field,
           "f9 TYPE cl_word=>ty_table_style_field,
         END OF ls_fieldtab,
         lt_fieldtab LIKE TABLE OF ls_fieldtab.

  IF w_skip = space.
    PERFORM object_progress_bar USING fw_open c_oh
                                      'Writing OpenHub info...'(m19).
    ls_dest-ohdest = fw_open.

    CALL METHOD cl_rsb_dest=>factory
      EXPORTING
        i_dest   = ls_dest-ohdest
      RECEIVING
        r_r_dest = lo_open.
    IF lo_open IS INITIAL.
      RETURN.
    ENDIF.

    CALL METHOD lo_open->get_info
      EXPORTING
        i_objvers      = c_objvers_active
      IMPORTING
        e_s_vdest      = ls_dest
        e_t_field      = lt_field
        e_t_field_text = lt_field_txt
      EXCEPTIONS
        not_found      = 1
        OTHERS         = 2.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

* OpenHub Title
    CONCATENATE 'Open Hub Destination' ls_dest-ohdest INTO lw_texte
                SEPARATED BY space.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = lw_texte
        line_style = cs_custo-style_title1.

* Insert embbeded documents
    PERFORM special_note USING c_oh fw_open
                               cs_custo-style_title2.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Destination'
        line_style = cs_custo-style_title2.

    REFRESH lt_data.
* Description
    CLEAR ls_data.
    ls_data-f1-textline = 'Description'.
    ls_data-f2-textline = ls_dest-txtlg.
    APPEND ls_data TO lt_data.

* Infoarea
    CLEAR ls_data.
    ls_data-f1-textline = 'Infoarea'.
    ls_data-f2-textline = ls_dest-infoarea.
    APPEND ls_data TO lt_data.

* Destination type
    CLEAR ls_data.
    ls_data-f1-textline = 'Destination type'.
    PERFORM get_domain_value USING 'RSDESTTYPE'
                                   ls_dest-desttype
                             CHANGING lw_domval.
    ls_data-f2-textline = lw_domval.
    APPEND ls_data TO lt_data.

    CASE ls_dest-desttype.
      WHEN 'TAB'.
* Database Table
        CLEAR ls_data.
        ls_data-f1-textline = 'Database Table'.
        ls_data-f2-textline = ls_dest-dbtab.
        APPEND ls_data TO lt_data.

* DB Connection Name
        CLEAR ls_data.
        ls_data-f1-textline = 'DB Connection Name'.
        ls_data-f2-textline = ls_dest-dbconnection.
        APPEND ls_data TO lt_data.

* Delete data from table
        CLEAR ls_data.
        ls_data-f1-textline = 'Delete data from table'.
        IF ls_dest-writemode IS INITIAL.
          ls_data-f2-textline = cl_word=>c_symbol_checkbox.
        ELSE.
          ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
        APPEND ls_data TO lt_data.

* Technical/semantic Key
        CLEAR ls_data.
        ls_data-f1-textline = 'Key'.
        IF ls_dest-genkey IS INITIAL.
          ls_data-f2-textline = 'Semantic'.
        ELSE.
          ls_data-f2-textline = 'Technical'.
        ENDIF.
        APPEND ls_data TO lt_data.

      WHEN 'FILE'.
* Application server
        CLEAR ls_data.
        ls_data-f1-textline = 'Application server'.
        IF ls_dest-appserver IS INITIAL.
          ls_data-f2-textline = cl_word=>c_symbol_checkbox.
        ELSE.
          ls_data-f2-textline = cl_word=>c_symbol_checkbox_checked.
        ENDIF.
        ls_data-f2-style_effect-font = cl_word=>c_font_symbol.
        APPEND ls_data TO lt_data.

* Server Name
        CLEAR ls_data.
        ls_data-f1-textline = 'Server Name'.
        ls_data-f2-textline = ls_dest-btcsrvname.
        APPEND ls_data TO lt_data.

* Appl. Server File Name
        CLEAR ls_data.
        ls_data-f1-textline = 'Appl. Server File Name'.
        ls_data-f2-textline = ls_dest-file.
        APPEND ls_data TO lt_data.

* Type of Saved Data
        CLEAR ls_data.
        ls_data-f1-textline = 'Type of Saved Data'.
        PERFORM get_domain_value USING 'RSBRETURNTP'
                                       ls_dest-returntpf
                                 CHANGING lw_domval.
        ls_data-f2-textline = lw_domval.
        APPEND ls_data TO lt_data.

* Separator
        CLEAR ls_data.
        ls_data-f1-textline = 'Separator'.
        ls_data-f2-textline = ls_dest-separator.
        APPEND ls_data TO lt_data.

      WHEN OTHERS.
        "TODO
    ENDCASE.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_data
        style   = cs_custo-table_without_head.

    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Field Definition'
        line_style = cs_custo-style_title2.

    REFRESH lt_fieldtab.
    CLEAR ls_fieldtab.
    ls_fieldtab-f1-textline = 'Key'.
    ls_fieldtab-f2-textline = 'Field'.
    ls_fieldtab-f3-textline = 'Description'.
    ls_fieldtab-f4-textline = 'Iobj Tpl'.
    ls_fieldtab-f5-textline = 'Type'.
    ls_fieldtab-f6-textline = 'Length'.
    ls_fieldtab-f7-textline = 'Dec. Places'.
    ls_fieldtab-f8-textline = 'Conv.'.
*ls_fieldtab-f9-textline = 'Data Element'.
    APPEND ls_fieldtab TO lt_fieldtab.

    LOOP AT lt_field INTO ls_field.
      CLEAR ls_fieldtab.
      IF ls_field-keyflag IS INITIAL.
        ls_fieldtab-f1-textline = cl_word=>c_symbol_checkbox.
      ELSE.
        ls_fieldtab-f1-textline = cl_word=>c_symbol_checkbox_checked.
      ENDIF.
      ls_fieldtab-f1-style_effect-font = cl_word=>c_font_symbol.
      ls_fieldtab-f2-textline = ls_field-fieldnm.
      CLEAR ls_field_txt.
      READ TABLE lt_field_txt INTO ls_field_txt
                 WITH KEY fieldnm = ls_field-fieldnm.
      ls_fieldtab-f3-textline = ls_field_txt-txtlg.
      ls_fieldtab-f4-textline = ls_field-tempiobjnm.
      ls_fieldtab-f5-textline = ls_field-datatype.
      ls_fieldtab-f6-textline = ls_field-leng.
      ls_fieldtab-f7-textline = ls_field-decimals.
      ls_fieldtab-f8-textline = ls_field-convexit.
*ls_fieldtab-f9-textline = ls_field-dtelnm.
      APPEND ls_fieldtab TO lt_fieldtab.
    ENDLOOP.
    CALL METHOD o_doc->write_table
      EXPORTING
        content = lt_fieldtab
        style   = cs_custo-table_with_head.

  ENDIF.
*
** Update rules 3x
*  PERFORM updr_list USING fw_open
*                          c_oh.

* transformation 7x
  PERFORM trsf_list USING fw_open c_oh.

  IF w_skip = space.
    PERFORM get_used_pc USING fw_open c_oh.
  ENDIF.

ENDFORM.                    " openhub

*&---------------------------------------------------------------------*
*&      Form  SPECIAL_NOTE
*&---------------------------------------------------------------------*
*       Write Special note section if doc is attached to given object
*----------------------------------------------------------------------*
*      -->FW_TYPE  Object type
*      -->FW_OBJ   Object name
*      -->FW_STYLE Style to apply to the section
*----------------------------------------------------------------------*
FORM special_note USING fw_type TYPE rstlogo
                        fw_obj
                        fw_style TYPE string.
  DATA : lt_class   TYPE STANDARD TABLE OF sdokclass,
         ls_class   LIKE LINE OF lt_class,
         lt_query   TYPE STANDARD TABLE OF sdokquprop,
         ls_query   LIKE LINE OF lt_query,
         lt_obj     TYPE STANDARD TABLE OF skwf_io,
         ls_obj     LIKE LINE OF lt_obj,
         lt_objprop TYPE STANDARD TABLE OF sdokproptl,
         ls_objprop LIKE LINE OF lt_objprop,
         BEGIN OF ls_doc,
           objtype   LIKE ls_obj-objtype,
           class     LIKE ls_obj-class,
           objid     LIKE ls_obj-objid,
           filename  TYPE string,
           extension TYPE string,
           order     TYPE string,
         END OF ls_doc,
         lt_doc     LIKE TABLE OF ls_doc,
         lt_asc     TYPE STANDARD TABLE OF sdokcntasc,
         ls_asc     LIKE LINE OF lt_asc,
         lt_bin     TYPE STANDARD TABLE OF sdokcntbin,
         lw_message TYPE string,
         lw_xstring TYPE xstring,
         lt_detail  TYPE STANDARD TABLE OF sdokfilaci,
         ls_detail  LIKE LINE OF lt_detail,
         lw_size    TYPE i.

* Check TLOGO if admissible for Documents
  IF cl_rsod_meta=>tlogo_is_available_for_doc( fw_type ) = rs_c_false.
*    MESSAGE w148(rsod) WITH fw_type.
    RETURN.
  ENDIF.

  ls_class-class = 'BW_PH_META'.
  APPEND ls_class TO lt_class.

  ls_query-prop_name = 'BW_OBJNM'.
  ls_query-sign = 'I'.
  ls_query-option = 'EQ'.
  ls_query-low = fw_obj.
  APPEND ls_query TO lt_query.

  ls_query-prop_name = 'BW_TLOGO'.
  ls_query-sign = 'I'.
  ls_query-option = 'EQ'.
  ls_query-low = fw_type.
  APPEND ls_query TO lt_query.

  CALL FUNCTION 'SKWF_FIND_BY_QUERY'
    TABLES
      classes           = lt_class
      queries           = lt_query
      result_objects    = lt_obj
      properties_result = lt_objprop.

* Keep only valid document
  LOOP AT lt_obj INTO ls_obj.
    CLEAR ls_doc.
    ls_doc-objtype = ls_obj-objtype.
    ls_doc-class = ls_obj-class.
    ls_doc-objid = ls_obj-objid.

* Get document content
    CALL FUNCTION 'SKWF_PHIO_LOAD_CONTENT'
      EXPORTING
        phio             = ls_obj
      TABLES
        file_access_info = lt_detail.

    READ TABLE lt_detail INTO ls_detail INDEX 1.

    ls_doc-filename = ls_detail-file_name.

    FIND ALL OCCURRENCES OF '.' IN ls_doc-filename MATCH OFFSET sy-fdpos.
    IF sy-subrc = 0.
      sy-fdpos = sy-fdpos + 1.
      ls_doc-extension = ls_doc-filename+sy-fdpos.
      TRANSLATE ls_doc-extension TO LOWER CASE.
    ENDIF.

    IF ls_detail-mimetype(10) = 'text/plain'. "can be followed by encoding
      ls_doc-extension = 'txt'.
    ELSEIF ls_doc-extension = 'txt'.
      CLEAR ls_doc-extension.
    ENDIF.

    CLEAR ls_objprop.
    READ TABLE lt_objprop INTO ls_objprop
               WITH KEY class = ls_obj-class
                        objid = ls_obj-objid
                        name ='DESCRIPTION'.
    ls_doc-order = ls_objprop-value.

* Check allowed documents
    CASE ls_doc-extension.
      WHEN 'doc'
      OR 'docx'
      OR 'docm'
      OR 'ppt'
      OR 'pptx'
      OR 'xls'
      OR 'xlsx'

      OR 'jpg'
      OR 'jpeg'
      OR 'png'
      OR 'gif'
      OR 'bmp'

      OR 'txt'.
* Allowed
      WHEN OTHERS.
        CONCATENATE 'Cannot add document'
                    ls_doc-filename
                    'for object'
                    fw_type
                    fw_obj
                    INTO lw_message SEPARATED BY space.
        MESSAGE lw_message TYPE c_msg_info.
        CONTINUE.
    ENDCASE.

    APPEND ls_doc TO lt_doc.
  ENDLOOP.

* Write title if there is document to add
  IF NOT lt_doc IS INITIAL.
    CALL METHOD o_doc->write_text
      EXPORTING
        textline   = 'Special purpose'
        line_style = fw_style.
  ENDIF.

  SORT lt_doc STABLE BY order.

* Display documents
  LOOP AT lt_doc INTO ls_doc.

* Get document content
    CLEAR ls_obj.
    ls_obj-objtype = ls_doc-objtype.
    ls_obj-class = ls_doc-class.
    ls_obj-objid = ls_doc-objid.
    CALL FUNCTION 'SKWF_PHIO_LOAD_CONTENT'
      EXPORTING
        phio                = ls_obj
      TABLES
        file_access_info    = lt_detail
        file_content_ascii  = lt_asc
        file_content_binary = lt_bin.
    READ TABLE lt_detail INTO ls_detail INDEX 1.

* Search document type
    CASE ls_doc-extension.
* Plain text to display
      WHEN 'txt'.

* Add text content to document
        LOOP AT lt_asc INTO ls_asc.
          lw_message = ls_asc-line.
          CALL METHOD o_doc->write_text
            EXPORTING
              textline   = lw_message
              line_style = cl_word=>c_style_normal.
        ENDLOOP.

* Allowed documents to attach
      WHEN 'doc'
      OR 'docx'
      OR 'docm'
      OR 'ppt'
      OR 'pptx'
      OR 'xls'
      OR 'xlsx'.
* Convert xtable to xstring
        CLEAR lw_xstring.
        lw_size = ls_detail-file_size.
        CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
          EXPORTING
            input_length = lw_size
          IMPORTING
            buffer       = lw_xstring
          TABLES
            binary_tab   = lt_bin
          EXCEPTIONS
            OTHERS       = 2.

* Attach document
        CALL METHOD o_doc->insert_attachment
          EXPORTING
            url          = ls_doc-filename
            file_content = lw_xstring
            as_paragraph = cl_word=>c_false
            url_img      = cs_custo-attach_image.
        CALL METHOD o_doc->write_break.

        CALL METHOD o_doc->write_text
          EXPORTING
            textline   = ls_doc-filename
            line_style = cl_word=>c_style_normal.

* Allowed image to insert
      WHEN 'jpg' OR 'jpeg' OR 'png' OR 'gif' OR 'bmp'.
* Convert xtable to xstring
        CLEAR lw_xstring.
        lw_size = ls_detail-file_size.
        CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
          EXPORTING
            input_length = lw_size
          IMPORTING
            buffer       = lw_xstring
          TABLES
            binary_tab   = lt_bin
          EXCEPTIONS
            OTHERS       = 2.

* Insert image
        CALL METHOD o_doc->insert_image
          EXPORTING
            url          = ls_doc-filename
            file_content = lw_xstring.

* No allowed document > Skip
      WHEN OTHERS.
        CONTINUE.
    ENDCASE.
  ENDLOOP.
ENDFORM.

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)
                        '\@ &quot;dd/MM/yyyy&quot;'
                        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 '&amp;'.
    REPLACE ALL OCCURRENCES OF '<' IN out WITH '&lt;'.
    REPLACE ALL OCCURRENCES OF '>' IN out WITH '&gt;'.
    REPLACE ALL OCCURRENCES OF '"' IN out WITH '&quot;'.
  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