Skip to main content

SAP: Convert string to multiline table

Submitted by Stefan Barsuhn on

In case you have to deal with text in ERP, the text function modules do not usually allow you to pass a string value. Rather, you have to pass a table that contains your string, split up into multiple lines. The data element of those texts is usually TDLINE and you have to provide some additional information in the table, like object type and format.

Doing this split was actually not very straight-forward because you need to take into account that your (flat) source string may contain line breaks.

This is why I'm sharing my code, it takes a flat source string (type STRING) and returns a text table (based on structure BAPI2078_NOTFULLTXTI). As you will see, the first two characters of the text line include formatting instructions ("* " means new line, "  " means continue from previous line, new word, "= " means continue word from previous line). This example is specific to SAP QM Notifications, but you it can easily be applied to other scenarios using text tables.

The object type is specific to your application, the format may vary. It's best to use a read function module to read an existing text to see what formatting your scenario requires.

METHOD STRING_TO_TABLE.
    " takes import string IV_TEXT and adds it to the
    " result table ET_TEXT_TABLE (type table of BAPI2078_NOTFULLTXTI)

    CONSTANTS: lc_objtype      TYPE string VALUE 'QMEL',
               lc_format_col   TYPE string VALUE '>X',
               lc_length_limit TYPE i VALUE 130. " how long should one line in the result table be?

    DATA: lt_string              TYPE TABLE OF string,
          lv_string              TYPE string,
          lv_sub_length          TYPE i,
          lv_offset              TYPE i,
          lv_last_character_char TYPE bool VALUE abap_false.

    " empty text => nothing to do
    IF iv_text IS INITIAL.
      RETURN.
    ENDIF.

    " each line in the BAPI text table is max 132 characters long
    " a newline in the text table is signified by "* "
    SPLIT iv_text AT cl_abap_char_utilities=>newline INTO TABLE lt_string.

    " now each line in lt_string is a "newline"
    " loop over the lines and every 130 characters start a newline
    LOOP AT lt_string ASSIGNING FIELD-SYMBOL(<string>).
      " get string length
      DATA(lv_length) = strlen( <string> ).

      " get iterations
      " we add 1 to the iterations to take care of the remaining characters
      DATA(lv_iterations) = lv_length DIV lc_length_limit + 1.

      DO lv_iterations TIMES.
        " reset from last loop
        CLEAR lv_string.

        " first two characters are always control characters
        " for the rist line, add "* " to the beginning of the string, this represents newline
        IF sy-index EQ 1.
          lv_string = |* |.
        ELSEIF lv_length GT 0 AND " this line is not empty (if it is we're not splitting a word)
               lv_last_character_char EQ abap_true AND " last character of previous line ended with character
               <string>+0(1) NE space. " and this line begins with a proper character
          " both last character of last string and first character of this string
          " are NOT a space. This means we're splitting in the middle of a word
          " If we're splitting in the middle of a word, new line needs to start with "= "
          " otherwise there'll be a space in the middle of the word
          lv_string = |= |.
        ELSE.
          " for all other lines, add two spaces
          lv_string = |  |.
        ENDIF.

        " calculate the offset in the source string
        " in the first loop sy-index is 1 but the offset is 0
        " so subtract 1 from sy-index
        " in the second loop, offset is 130 etc.
        lv_offset = lc_length_limit * ( sy-index - 1 ).

        " add the lower of the string length and 130 as maximum line length
        lv_sub_length = nmin( val1 = strlen( <string>+lv_offset ) val2 = lc_length_limit ).

        lv_string = lv_string && <string>+lv_offset(lv_sub_length).

        " is last character of this string a proper character?
        " remember for next loop
        lv_offset = lv_offset + lv_sub_length - 1.

        " empty string does not count as character
        IF lv_sub_length GT 0 AND <string>+lv_offset(1) NE space.
          lv_last_character_char = abap_true.
        ELSE.
          " reset to false otherwise.
          lv_last_character_char = abap_false.
        ENDIF.

        " now we've got
        " the offset (how many characters from the beginning of the source string does our line begin?)
        " the sub length (how many characters from our offset do we want to add to our line?
        APPEND VALUE #( objtype = lc_objtype format_col = lc_format_col text_line = lv_string ) TO ET_TEXT_TABLE.
      ENDDO.
    ENDLOOP.
 

Tags