Purpose
Read and update texts (SAPscript long texts)

The SAP function modules READ_TEXT and SAVE_TEXT can be used to read and update texts such as customer order header texts, plant maintenance notification texts and so on. You can call up these functions via the GuiXT Open Call interface.

General suggestion:
We suggest you use an InputScript with CopyText ... toScreen for updating texts, or call up a suitable BAPI function. The reason is that the SAP applications often have special rules to build up parts of the texts or to format ithem in a special way, which you can violate with your own SAVE_TEXT call. Also, some applications (e.g. IW21/IW22) maintain an additional "long text indicator" in a database table so that your new text added with "SAVE_TEXT" will not become visible in the transaction.

Adding text lines to an existing text can be done, but even in this case it is better to use the BAPI based solution that we describe at the end of this article.


Example
We display the header long text of a plant maintenance notification and let the user add further text lines. Since we do not want the existing text to be changed we use two text boxes: one read-only text box for the existing text and one for the new additional text lines:

 

After saving the text, the transactions IW22/IW23 will show the added lines:

In order to implement the application we first need the key data of the text in the SAP long text database. The easiest way to obtain the text key is to navigate to the long text editor in the SAP transaction , e.g. in IW22, and to display the text header (click on Goto->Header):

The text name in our case is the full notification number, with leading zeros.  With this knowledge we can read the text via READ_TEXT in the following way:

// text key fields
Set
V[tdobject] "QMEL"
Set V[tdid] "LTXT"

// notification number, 12 digits
Clear V[tdname]
Set V[tdname](1-12) "000000000000&V[qmnum]" -alignRight

// language EN, FR, DE,...
Set V[tdspras] "&V[_language2]"

// structure for returning the text header and content
CreateStructure V[thead] tdobject tdname tdid tdspras
CreateTable V[textlines] tdformat tdline

// read the text
Call
"READ_TEXT" -try _
 
export.OBJECT="tdobject" _
 
export.NAME="tdname" _
 
export.ID="tdid" _
 
export.LANGUAGE="tdspras" _
 
import.HEADER="thead" _
 
import.LINES="textlines"

We use the -try option in the  Call statement in order to avoid an exception if the text does not exist. During the development it is better to work without  -try so that you obtain any other exceptions, e.g. a wrong text object.

Another way to find the text keys is to display table STXH:

Since table STXH normally has many entries, you will need to guess the TDNAME in order to find the right entry.

All possible text objects and text IDs can be found in the following tables:

TTXOB Definition of the text objects
TTXOT Description of the text objects
TTXID  Definition of the text IDs
TTXIT  Description of the text IDs

A third way to find the text key is the SAP trace (transaction ST01). Switch on the trace for the database calls, then display the long text. In the trace output search for "STXH":

The detail view (press F2) of the STXH trace entry will show the STXH keys:
QMEL, 000010001707, LTXT:

With the text keys we read the text into a GuiXT table variable (see the above coding) and now want to copy the text lines into our textbox.

We start with a test display of the text read via READ_TEXT, showing both the 2-character ITF format and the content for each line:

CopyText fromTable=V[textlines] toText="temp"
Message "&text[temp]"

You see that the ITF format of each line is ">X" which means "read-only text line" in SAPScript:

    >x Fixed line
      The line is not ready for input in the SAPscript editor. Also, it can not be deleted or separated. You can only create fixed lines with a program . You can therefore give a text a fixed structure, for example, which cannot be changed by the user.
      You can use any number or letter for the 'x'. You can therefore separate different sub-headings, for example. If several fixed lines occur consecutively with the same indicator, they are regarded as a unit by the SAPscript editor. It is not possible to insert anything between these lines in the editor.
      In the case of fixed lines, SAPscript print formatting interprets the first two characters of the line as a paragraph format for formatting. You therefore need to enter the required paragraph format or blank here.

Other common SAPscript line formats are:

/ New line
* Comment line

See the SAP documentation for a full list of possible line formats.

The formatting of the long text as "read-only" and the generation of the log header line (date, time and user name / id) can be configured in SAP. For example, for notification type M2:

 

So, when you work with SAVE_TEXT later on, you really have to know what you are doing in order to observe the formatting rules.

In this example, we copy the content into the GuiXT long text variable and assume that the whole text is read-only,  see InputScript "read_qmel_longtext.txt" below for the details.

Analogously, when we save the text, we add the ITF line format ">X"  to mark it as read-only and start each line with "* " (new paragraph),  see InputScript "save_qmel_longtext.txt" below for the details.

 

GuiXT script

InputField (2,1) "Notification" (2,12) size="12" name="qmnum" searchHelp="QMEG"

TextBox (4,1) (8,72) name="qmel_longtext" -readOnly
TextBox (9,1) (14,72) name="qmel_addtext"

Pushbutton (15,3)  "Read text" process="read_qmel_longtext.txt" size=(2,16)
Pushbutton (15,30) "Save text" process="save_qmel_longtext.txt" size=(2,16)

 

InputScript "read_qmel_longtext.txt"

// text type (object and id)
Set V[tdobject] "QMEL"
Set V[tdid] "LTXT"

// text key: notification number, 12 digits
Clear V[tdname]
Set V[tdname](1-12) "000000000000&V[qmnum]" -alignRight

// language EN, FR, DE,...
Set V[tdspras] "&V[_language2]"

// structure for returning the text header and content
CreateStructure V[thead] tdobject tdname tdid tdspras
CreateTable V[textlines] tdformat tdline

Call "READ_TEXT" -try _
 
export.OBJECT="tdobject" _
 
export.NAME="tdname" _
 
export.ID="tdid" _
 
export.LANGUAGE="tdspras" _
 
import.HEADER="thead" _
 
import.LINES="textlines"

Clear text[qmel_longtext]
Clear text[qmel_addtext]

// copy text lines
Set V[k] 0

label next_line
 
if V[k<&V[textlines.rowcount]]
       Set V[k] &V[k] + 1

   
// skip the first two characters, they contain the format
       // since the lines are read-only (format >X )
      Set V[line] "&V[textlines.tdline.&V[k]](3-200)"

    CopyText fromString="line" toText="qmel_longtext" -appendLine

  goto next_line

endif

 

InputScript "save_qmel_longtext.txt"

// anything to add ? else return
if not text[qmel_addtext]
  return
endif

// add textbox content
Set V[k] 0
Set V[n] &V[textlines.rowcount] + 1

// add a line with date, time and author
Set V[s] "&V[today_d.m.y h:m:s] (&V[_user])"

// set format: no change
Set V[textlines.tdformat.&V[n]] ">X"

// set text line
Set V[textlines.tdline.&V[n]] "* &V[s]"

// add text
label next_textline
Set V[k] &V[k] + 1
Set V[n] &V[n] + 1

CopyText fromText="qmel_addtext" toString="s" line="&V[k]"

if Q[ok]

  // set format: no change
  Set V[textlines.tdformat.&V[n]] ">X"

 
// set text line
  Set V[textlines.tdline.&V[n]] "* &V[s]"
 
goto next_textline

endif

// save text
Set V[TRUE] "X"

Call "SAVE_TEXT" _
 
export.HEADER="thead" _
 
export.SAVEMODE_DIRECT="TRUE" _
 
export.LINES="textlines"

// read text again
include "read_qmel_longtext.txt"

 

BAPI based soulution
For notifications there exist BAPI solutions to read and add text. They automatically take care of the read-only format and of the log linecreation according to the customized rules for the notificatiopn type. If possible, implement such BAPI based solutions.
Here are the scripts:


InputScript "read_qmel_longtext_bapi.txt"

// table for returning the text content
CreateTable V[texttab] text_line

Call "BAPI_ALM_NOTIF_GET_DETAIL" _
 
export.NUMBER="qmnum" _
 
import.NOTLONGTXT="texttab"

// copy text into our textbox
CopyText fromTable=V[texttab] toText="qmel_longtext"

// clear text box for user input
Clear
text[qmel_addtext]

Return


InputScript "save_qmel_longtext_bapi.txt"

// anything to add ? else return
if not text[qmel_addtext]
  return
endif

// text table for BAPI call
CreateTable
V[bapilongtext] objtype objkey format_col text_line

// fill text table
Set
V[k] 1

label copy_add_line
CopyText fromText="qmel_addtext" toString=s line=&V[k]
if q[ok]
  Set V[bapilongtext.objtype.&V[k]] "QMEL"
  Set V[bapilongtext.format_col.&V[k]] "/"
  Set V[bapilongtext.text_line.&V[k]] "&V[s]"
  Set V[k] &V[k] + 1
 
goto copy_add_line
endif

CreateStructure V[bapireturn] type message
CreateTable V[bapireturntab] include=V[bapireturn]

Call "BAPI_ALM_NOTIF_DATA_ADD" _
 
export.NUMBER="qmnum" _
 
export.NOTFULLTXT="bapilongtext" _
 
import.RETURN="bapireturntab"

// Any error message?
ReadRow V[bapireturn] table=V[bapireturntab] key="E"

if Q[ok]
  Call "BAPI_TRANSACTION_ROLLBACK"
  Return "E: &V[bapireturn.message]" -statusline
endif

// Save to database
Call "BAPI_ALM_NOTIF_SAVE" _
 
export.NUMBER="qmnum"

Call "BAPI_TRANSACTION_COMMIT"

// read text again
include "read_qmel_longtext.txt"

Components InputAssistant