Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
BMEIJS
Active Participant
216,073


After my previous blog about the option of using Method Chaining (Using New ABAP stuff – Method Chaining and CL_SALV_TABLE) I thought it would be a good idea to write something about my experiences with new string options like String Templates, Chaining of strings, and built-in string functions. Just as with Method Chaining, using these string options allow for making ABAP code terser, which means that fewer statements are needed for the same functionality, without compromising readability of the code.

What’s it al about?


Several new options for the handling of characters strings were introduced to ABAP in WAS702:

  • String Templates: the option to create a character string out of literal texts, expressions, and control characters.

  • Chaining Operator: chain two character-like operands into one new character string.

  • Character String Functions: built-in functions for searching, processing and comparing strings.


I will first explain these options and give a few examples. The last paragraph explains how the use of string templates, combined with built-in functions and the use of functional methods, limits the number of needed ABAP statements.

Note that the ABAP Keyword documentation contains several built-in examples, related to old and new ABAP features. These examples can be executed and debugged and its code can be analysed. Moreover, the program DEMO_EXPRESSIONS offers 45 examples of character string and byte string processing.

 

String Templates


The purpose of a string template is to create a new character string out of literal texts and embedded expressions. It largely replaces the use of the WRITE TO statement, which will be explained later on.

A string template is defined by using the | (pipe) symbol at the beginning and end of a template.

DATA: character_string TYPE string.
character_string = |This is a literal text.|.


This example has in fact exactly the same result as:

character_string = `This is a literal text.`.

The added value of a string template becomes clear when combining literal texts with embedded expressions and control characters. Embedded expressions are defined within a string template with curly brackets { expression }.  Note that a space between bracket and expression is obligatory.

An expression can be a data object (variable), a functional method, a predefined function or a calculation expression. Some examples are:

character_string = |{ a_numeric_variable }|.

character_string = |This resulted in return code { sy-subrc }|.

character_string = |The length of text element 001 ({ text-001 }) is { strlen( text-001 ) }|.

 

Embedded expressions have a default output format, but also several formatting options, comparable to the format options of the WRITE statement. Some examples are:

DATA: amount_field   TYPE vbap-netwr VALUE '1234567.123',
currency_field TYPE vbap-waerk.
character_string = |{ amount_field CURRENCY = currency_field  NUMBER = USER }|.
character_string = |{ amount_field COUNTRY = 'GB ' }|.


 

Two limitations for which I haven’t found a solution yet are:

1) I could not find a formatting option for Conversion Exits. Consider the example below: the WRITE….TO… calls the conversion exit KONPD that converts an internal project number to an external project id. The string template inserts the internal project number into the string.

DATA: project_number TYPE proj-pspnr.
SELECT SINGLE pspnr FROM proj INTO project_number .
WRITE project_number TO character_string2.


character_string = |{ project_number }|.

 

2) The following option for text-elements is not supported in an embedded expression:

WRITE : 'This is a text'(001).

 

The only option to use a numbered text is in an embedded expression:

character_string = |{ text-001 }|.

 

However, using the Chaining Operator offers a simple solution for this as is demonstrated below.

Chaining Operator


The Chaining Operator && can be used to create one character string out of multiple other strings and string templates. The use of the chaining operator largely replaces the CONCATENATE statement.

In this example, a number text, a space, an existing character string and a new string template are concatenated into a new character string.

character_string  'Text literal'(002) && ` ` && character_string && |{ amount_field NUMBER = USER }|.

Built-in functions


SAP has added several new built-in functions for searching, comparing, and processing character strings.  A few of these functions already existed before release WAS702, like for example, CHARLEN( ) or STRLEN( ). Other statements like FIND, REPLACE or TRANSLATE can now be replaced by built-in functions Also new functions have been added.

Note that these built-in functions can be used as part of string templates or in operand positions. In the ABAP keyword documentation, the added value of these functions is described as followed:

The string functions enable many string processing tasks to be done in operand positions where previously separate statements and auxiliary variables were required.

 

A few examples of built-in functions are:

string_result = to_mixed( val = string_field sep = ` ` ).
string_result = reverse( string_field ).
distance_between_strings = distance( val1 = string_field val2 = string_result ).


 

The functions to_mixed and reverse speak for themselves. The function distance is a similarity function that calculates the minimum number of steps needed to change one string into another string, the so called Levenshtein distance. I’m still looking for an opportunity to use it in one of my customer assignments :wink:

 

Compacting ABAP code by using new string options


Imagine that you have to create a tab-delimited file from an internal table with a line type, consisting of character and numeric type fields. Furthermore, you want the date and amount fields to be converted into a specific output format in the file.

The definition of the internal table could look like this:

TYPES: BEGIN OF ty_struct,
change_date   TYPE d,
amount        TYPE bf_dmbtr,"numeric type
currency_key  TYPE waers,
text_field    TYPE string,
END OF ty_struct.


Let us focus on the creation of one tab-delimited file entry. Pre-WAS702, this would look like this:

DATA: date_as_a_string TYPE c LENGTH 10,
amount_as_a_string TYPE c LENGTH 20.


WRITE <input_line>-change_date TO date_as_a_string .
WRITE <input_line>-amount      TO amount_as_a_string CURRENCY input_line>-currency_key.
CONCATENATE date_as_a_string
amount_as_a_string
<input_line>-currency_key
<input_line>-text_field INTO download_line
SEPARATED BY cl_abap_char_utilities=>horizontal_tab.


Note that you need two variables and two WRITE TO statements to convert the date and amount field to a suitable output format. Using the amount field, which is a numeric field, directly in the CONCATENATE statement will lead to a syntax error.

Using a string template, chaining operator and control characters, these 5 statements can be reduced to only one statement:

download_line =
|{ <input_line>-change_date DATE = USER }\t| &&
|{ <input_line>-amount NUMBER = USER CURRENCY = <input_line>-currency_key }\t| &&
|{ <input_line>-currency_key }\t{ <input_line>-text_field } |.


The tab delimiter is inserted by using the control character \t.

This is just one of many examples that I can think of.  Just consider the following snippets of code and consider the number of intermediate steps your would need to implement this functionality without string templates.

* Include a built-in function

log_information = |Number of entries in download: { lines( download_file ) } |.

* Include a functional method call

log_information = |My IP address = { cl_gui_frontend_services=>get_ip_address( ) }|.

Conclusion


In my daily life as an ABAP programmer, I’m working on customer SAP systems with basis versions ranging from R/3 4.6C up to WAS731 based systems. Not being able to use new string options on several older customer systems can be quite frustrating after having used them on other systems. I once fell into the trap of writing a program using string templates and method chaining. I then tried to install this program on another ECC60 system, but this failed because this system was based on WAS701. I had to rewrite parts of the program: define new intermediate variables, call intermediate methods to get values, and use the WRITE TO statement to get the proper date and amount values in my download.

So, if you’re working on a WAS702vv-based system, I would advice you to start using new ABAP possibilities because they will improve your speed of development and make your programs better maintainable. For me, I just enjoy discovering and trying new options and share my experiences with other programmers.

21 Comments
narin_nandivada3
Active Contributor
0 Kudos

Very informative. Thanks.

BMEIJS
Active Participant
0 Kudos

Thanks for that.

Former Member
0 Kudos

Hi,

Thanks to provide the document with your example codes...

Perfect.... All The best... :smile:

Regards,

Ragav

Former Member
0 Kudos

Thanks for giving code with good examples

Former Member
0 Kudos

Good blog.

To get around the limitation of the lack of conversion exits, you could do the following:

Create a static functional method that wraps up the required conversion exit.

Embed this new method into the expression.

For example, outputing a Sales Order number formatted by the ALPHA routine:

character_string = |Your Order Number is { zcl_myclass=>alpha( pv_vbeln ) }|.

The only thing I don't like about this is that the Returning parameter of the method cannot have a generic type (such as C), so in order to make it usable for VBELN, MATNR etc. with different lengths, you have to type the parameter as something explicit like CHAR20.

Regards,

Pete

ChristianGünter
Contributor
0 Kudos

The only thing I don't like about this is that the Returning parameter of the method cannot have a generic type (such as C), so in order to make it usable for VBELN, MATNR etc. with different lengths, you have to type the parameter as something explicit like CHAR20.


Why not using String as type of the returning parameter?

Former Member
0 Kudos

Yes that would do the job too

Former Member
0 Kudos

very useful!

Thanks!

h3n
Participant
0 Kudos

Be careful with different datatypes. You can use string chaning on numeric Textfield together with a string. During runtime the string will be ignored and you do not get a runtimeerror.

Example:

"build in datatype n --> Numeric text field
DATA: numeric TYPE n LENGTH 6 VALUE '201607'.

         numeric = numeric+4(2) && '.' && numeric(4).
         "Result: 072016
         WRITE: numeric.

aasim_khan
Participant
0 Kudos

Wow, that's plethoric! But how would you concatenate two variables keeping blanks?

Old school way would be ->

CONCATENATE lv_string1 lv_string2 INTO lv_string3 RESPECTING BLANKS.

Former Member
0 Kudos
For short: they are always respecting blanks. Taking your example the result could look like this:

lv_string3 = |{ lv_string1 } { lv_string2 }|.

Importand is only the space between the closing bracket of our first field and the opening bracket of the next.
franois_henrotte
Active Contributor
0 Kudos
Now you can use a format to convert your value to internal or external formatting :
character_string = |Your Material Number is { pv_matnr ALPHA = IN }|.    "Adds leading zeros
character_string = |Your Material Number is { pv_matnr ALPHA = OUT }|. "Removes leading zeros

 
denis_skuridin
Explorer
0 Kudos
And what if we have fields like char20? See no formatting option  or smth similar to achieve this without CONCATENATE.
Nigel_James
Active Contributor
0 Kudos
Thanks for a great blog. I sent some colleagues this way to see all your cool examples.

The word distance is interesting - I have seen soundex used as a proxy for searching and getting hitrs on words thet approximage whet ehty are meening.

https://stackoverflow.com/a/473554/2434654
Sandra_Rossi
Active Contributor
0 Kudos
You indicate that the following statement is not accepted but it is (at least it works in 7.52) :

DATA(var) = |{ 'this is a text'(001) }|.
BMEIJS
Active Participant
Thank you for your reply. You are absolutely true. After having posted this blog (2013) I have used the option you describe very often.
BaerbelWinkler
Active Contributor
0 Kudos

b.meijs

A rather belated thanks for this neat summary which I only happened upon today – but I guess, better late than never ?! I found your blog post while searching for a solution of how to best create a concatenated string.

I wanted to use the CleanCode way to assemble a text string in order to initialize the content for a selection-screen value containing ‘*’ for a pattern search:

s_agrn[] = VALUE #( ( option = 'EQ' sign = 'I' low = |* { usergroup } *| ) ).

If USERGROUP contains ‘XXXX’ the resulting value for LOW is ‘* XXXX *’, so spaces are automatically introduced which I obviously don’t want to have in this case and wouldn’t get if I simply used the tried and trusted CONCATENATE statement (without ‘separted by space’).

I also don’t get spaces when I use what is shown as the “anti-pattern” in CleanCode, namely the chaining via &&:

s_agrn[] = VALUE #( ( option = 'CP' sign = 'I' low = '*' && usergroup && '*' ) ).

I read through the documentation but nothing really jumped out how I could suppress the unwanted spaces when I do it the “CleanCode way”. Is there one which I missed / didn’t recognize?

I’m working in a NW 750 SP16 EHP8 system.

Thanks much & Cheers

Bärbel

pokrakam
Active Contributor
Just leave out the spaces.
string = |* { foo } *|.  "your example
string = |*{ foo }*|. "no spaces
BaerbelWinkler
Active Contributor
0 Kudos
Thanks, Mike! Wish I could remember when a space is needed and when not with the various syntax elements!

Cheers

Bärbel
pokrakam
Active Contributor
0 Kudos
Yes, it's all in the name of backwards compatibility, much of it due to to that ancient substring syntax to write string(5)+4

So the space was introduced to distinguish substrings from parameters.
0 Kudos
Does it make any difference when using accute accents ´ or apostrophes ' for strings?
Labels in this area