Skip to Content
Technical Articles

Common Watermark on All Adobe Forms

Inspired by: Watermark on all Smartforms

Requirement: Watermark should be included on all Adobe form printouts, without having to individually include them in each form design. This is to identify when the printout is generated from a test/development system, it carries a warning to indicate that it is for non-productive use only.

I haven’t tried to use this on interactive Adobe forms, but I believe the same concept should work there too.

First, let’s create a test Adobe form with just the Watermark. Few considerations while creating this form:

  1. It can either contain just Text or Image or both. I prefer just Text and I will explain why later.
  2. Justify the content to Top-Left corner. This is to make sure that, the watermark is printed at the same position, whether the actual Adobe form is designed in Portrait or Landscape mode.

Here is my Form. You don’t have to activate and transport this Form. It can be deleted after completing all necessary adjustments.

 

Next, download the Form Layout

Open this layout file in a Text processing software – like Notepad++

It should look something like this:

If you had included an image in the form, then the XML file will have the Image data also. This makes the file a little bigger and that’s why I suggested to avoid it. But, if you definitely need the Image on the Watermark, then go ahead.

Now, clean-up time, for my ‘Text Only’ Watermark, this is the portion of the XML that I am interested in. I have deleted other unnecessary elements also below.

After the required cleanup, the final result should look something like this:

<subform h="6.35mm" name="watermark" w="215.9mm">
  <bind match="none"/>
  <draw h="6.35mm" name="Text1" w="215.9mm">
    <ui>
      <textEdit/>
    </ui>
    <value>
      <text>This is a watermark text</text>
    </value>
    <font typeface="Arial"/>
    <margin bottomInset="0.5mm" leftInset="0.5mm" rightInset="0.5mm" topInset="0.5mm"/>
  </draw>
</subform>

If you wish to, you can skip all of the Form creation/manipulation steps above and just use the XML I have pasted here.

Now, create a Class with the following code. I have modified the Watermark text below directly in the code, just to show that text can be dynamically modified. The constants declared below starting from LC_101… LC_107 is the data from above XML. If you had included an image in the form definition, then the XML code becomes bigger. Here, I am simply checking whether the system is not Production system – you may include any other checks as per your requirements.

The code loads the Form Layout XML document, then traverses through each page, and adds the extra Watermark code in it.

CLASS zclb_adobe_watermark DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    CLASS-METHODS add_watermark
      IMPORTING
        VALUE(im_fpname)     TYPE fpname
        VALUE(im_langu)      TYPE sy-langu
      CHANGING
        VALUE(ch_xftcontent) TYPE fpcontent OPTIONAL
        VALUE(ch_xftfile)    TYPE fpfile OPTIONAL .

  PROTECTED SECTION.

  PRIVATE SECTION.
    CONSTANTS:
      c_001 TYPE c LENGTH 1 VALUE `E` ##NO_TEXT.

    CLASS-METHODS find_pagearea
      IMPORTING
        VALUE(im_page) TYPE REF TO if_ixml_node
      RETURNING
        VALUE(re_area) TYPE REF TO if_ixml_node_list .
    CLASS-METHODS get_form_layout
      IMPORTING
        VALUE(im_fpname)     TYPE fpname
        VALUE(im_langu)      TYPE sy-langu DEFAULT c_001
      RETURNING
        VALUE(re_xftcontent) TYPE fpcontent .
ENDCLASS.

CLASS ZCLB_ADOBE_WATERMARK IMPLEMENTATION.
  METHOD add_watermark.
    CONSTANTS: lc_003 TYPE c LENGTH 3 VALUE `PS1`,
               lc_001 TYPE string VALUE 'pageSet',
               lc_101 TYPE string VALUE '<subform h="6.35mm" name="WATERMARK" w="215.9mm">',
               lc_102 TYPE string VALUE '<bind match="none"/><draw h="6.35mm" name="WatermarkText" w="215.9mm">',
               lc_103 TYPE string VALUE '<ui><textEdit/></ui><value>',
               lc_104 TYPE string VALUE '<text>DEMO ONLY: This output was generated from a non-productive system (',
               lc_105 TYPE string VALUE ')</text></value><font typeface="Arial"/>',
               lc_106 TYPE string VALUE '<margin bottomInset="0.5mm" leftInset="0.5mm" rightInset="0.5mm" topInset="0.5mm"/>',
               lc_107 TYPE string VALUE '<para hAlign="left"/></draw></subform>'.
    DATA: lo_wdocument TYPE REF TO cl_xml_document,
          lo_wnodes    TYPE REF TO if_ixml_node,
          lo_fdocument TYPE REF TO cl_xml_document.
    CHECK sy-sysid NE lc_003.

    TRY.
        CREATE OBJECT: lo_wdocument, lo_fdocument.
        lo_fdocument->parse_xstring( get_form_layout( im_fpname = im_fpname im_langu = im_langu ) ).
        lo_wdocument->parse_string(
          lc_101 && lc_102 && lc_103 && lc_104 && sy-sysid && sy-mandt && lc_105 && lc_106 && lc_107 ).

        DATA(lo_pagenode) = lo_fdocument->find_node( lc_001  ).
        DATA(lo_pages)    = find_pagearea( lo_pagenode ).

        DO lo_pages->get_length( ) TIMES.
          DATA(lo_page) = lo_pages->get_item( sy-index - 1 ).
          lo_page->append_child( lo_wdocument->get_first_node( )->clone( ) ).
        ENDDO.

        lo_fdocument->render_2_xstring( IMPORTING stream = ch_xftcontent ).
        IF ch_xftcontent IS NOT INITIAL.
          CLEAR: ch_xftfile.
        ENDIF.
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.

  METHOD find_pagearea.
    CONSTANTS: lc_002 TYPE string VALUE 'pageArea'.
    CHECK im_page->num_children( ) > 0.
    TRY.
        DATA(lo_children) = im_page->get_children( ).
        DO lo_children->get_length( ) TIMES.
          DATA(lo_child) = lo_children->get_item( sy-index - 1 ).
          IF lo_child->get_name( ) = lc_002 .
            re_area = lo_children.
          ELSE.
            re_area = find_pagearea( lo_child ).
          ENDIF.
          IF re_area IS NOT INITIAL.
            EXIT.
          ENDIF.
        ENDDO.
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.

  METHOD get_form_layout.
    CONSTANTS: lc_005 TYPE c LENGTH 1 VALUE `D`.
    DATA: lo_wb_form        TYPE REF TO if_fp_wb_form,
          lo_form           TYPE REF TO if_fp_form,
          lo_layout         TYPE REF TO if_fp_layout,
          lv_layout_xml     TYPE xstring,
          lo_ixml           TYPE REF TO if_ixml,
          lo_stream_factory TYPE REF TO if_ixml_stream_factory,
          lo_stream         TYPE REF TO if_ixml_istream,
          lo_parser         TYPE REF TO if_ixml_parser.

    lo_ixml = cl_ixml=>create( ).
    TRY.
        lo_wb_form = cl_fp_wb_form=>load(
                        i_name = im_fpname
                        i_mode = if_fp_wb_object=>c_mode_read
                        i_language = im_langu
                        i_suppress_language_check = abap_true ).
      CATCH cx_fp_api.
        RETURN.
    ENDTRY.
    lo_form ?= lo_wb_form->get_object( ).
    lo_layout = lo_form->get_layout( ).
    lv_layout_xml = lo_layout->get_layout_data( ).

    IF lv_layout_xml IS INITIAL.
      TRY.
          lo_wb_form = cl_fp_wb_form=>load(
                          i_name = im_fpname
                          i_mode = if_fp_wb_object=>c_mode_read
                          i_language = lc_005
                          i_suppress_language_check = abap_true ).
        CATCH cx_fp_api.
          RETURN.
      ENDTRY.
      lo_form ?= lo_wb_form->get_object( ).
      lo_layout = lo_form->get_layout( ).
      lv_layout_xml = lo_layout->get_layout_data( ).
    ENDIF.

    IF lv_layout_xml IS NOT INITIAL.
      re_xftcontent = lv_layout_xml.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

Now, create 3 Implicit Enhancement implementations at the following locations

Program SAPLFPCOMP -> Subroutine SET_DOCUMENT_PARAMETERS -> End of Subroutine

  zclb_adobe_watermark=>add_watermark( exporting im_fpname     = p_docpar-formname
                                                 im_langu      = p_document-spoolprev-reqlangu
                                       changing  ch_xftcontent = p_document-xft
                                                 ch_xftfile    = p_document-xftfile ).

Program SAPLFPCOMP -> Subroutine LOAD_TEMPLATE -> End of Subroutine

  zclb_adobe_watermark=>add_watermark( exporting im_fpname     = p_formname
                                                 im_langu      = p_langu
                                       changing  ch_xftcontent = p_xft ).

Program SAPLFPCOMP -> Subroutine BIN_GET_SPOOL_PREVIEW -> End of Subroutine

  zclb_adobe_watermark=>add_watermark( exporting im_fpname     = p_spoolprev-formname
                                                 im_langu      = p_spoolprev-langu
                                       changing  ch_xftfile    = p_spoolprev-formurl ).

After activating this, when you create a new Adobe form print-preview/ printout or view any spool request, it should show you a Watermark message on the output as per your design.

Preview:

Spool output:

 

1 Comment
You must be Logged on to comment or reply to a post.
  • Forms created in LC Designer are XFA forms in a PDF wrapper (best way I can think of describing it). A native PDF (like a document) and an XFA Form are completely different animals.

    While you can open an XFA form in Acrobat, a lot of the common Acrobat tasks like adding watermarks are not available.

    So I would recommend that you go back to LC Designer and on the Master Page you place a text object with a very light grey font. This will act like a watermark.