Enterprise Resource Planning Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Akshay_Anil1
Explorer
1,609

While working in ABAP, especially when preparing data for file downloads or exporting internal tables, you might notice that some lines seem to end with a " # " symbol. But here's the catch  that " # " is not always a real hash symbol. Naturally, you might think it’s a hashtag — but often, it’s not. These characters don’t display visually, but depending on how the file is opened or downloaded, they may appear as strange or misleading symbols.

What’s Actually Happening?

Sometimes, that " # " is just how non-printable characters like carriage return (CR) or newline (LF) appear when viewed in SAP ALV, Excel, or when downloading.
These hidden characters:

  • Can break the line unexpectedly in the downloaded file
  • May cause the data to appear in a new row or line
  • Often sneak in from copied text, manual input, or external systems

What Didn't Work (Tried & Failed)

We initially tried the following common approaches:

REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_text WITH ''.
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr IN lv_text WITH ''.
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN lv_text WITH ''.

We also looped through the internal table to clean each field:

LOOP AT it_data INTO DATA(ls_data).
  REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN ls_data-field WITH ''.
  MODIFY it_data FROM ls_data.
ENDLOOP.

However, none of these worked. The problem persisted.

 

How to Fix It? - Solution (with hex check) 

Here’s a reliable way to check the last character’s hex code, and remove it only if it matches the actual ASCII of " # " (hex 23).

DATA: lv_value    TYPE string VALUE 'AKSHAY ANIL#',  " Input string (may have unwanted char at end)" replace this variable with yours*
      lv_len      TYPE i,                      " Length of the string
      lv_lastval  TYPE string,             " Last character of the string
      lv_hex      TYPE xstring,                 " Hex value of the last character
      lv_newval   TYPE string.                 " Final cleaned value

" Step 1: Find the length of the string
lv_len = strlen( lv_value ).
SUBTRACT 1 FROM lv_len.  " Adjust to point to last character (0-based index)

" Step 2: Get the last character
lv_lastval = lv_value+lv_len(1).

" Step 3: Convert last character to hex using built-in function module
CALL FUNCTION 'NLS_STRING_CONVERT_FROM_SYS'
  EXPORTING
    lang_used = sy-langu       " Use system language
    source    = lv_lastval     " Character to convert
    to_fe     = 'MS '          " Target frontend encoding (Microsoft)
  IMPORTING
    result    = lv_hex         " Hex value of the character
  EXCEPTIONS
    OTHERS    = 1.             " Simple error catch

" Step 4: Check if the character is '#' (hex 23)
IF lv_hex = '23'.  " ASCII hex for '#'
  lv_newval = lv_value+0(lv_len).  " Remove last character
ELSE.
  lv_newval = lv_value.            " Keep original if not '#'
ENDIF.

Here’s another method to check the each character’s hex code, and remove it only if it matches the actual ASCII of " # " (hex 23). Eg : If Value  = " ABC#DEF#" it becomes " ABC DEF" , as the code given below.

DATA: p_value    TYPE string VALUE 'AKSHAY#ANIL#',
      lv_hex     TYPE xstring,   " Hex value of the current character
      lv_char    TYPE string,    " Character selected in the loop
      lv_cleaned TYPE string.    " Final cleaned string after replacing '#' with space

CLEAR: lv_char, lv_hex, lv_cleaned.

" Step 1: Add a space in front of the original string
" This is required to avoid issues with 1-based index in DO loop + 0-based string offset
p_value = | { ' ' }{ p_value } |.  " Now p_value = ' AGS#JSAKS#AS'

" Step 2: Loop through each character in the string
DO strlen( p_value ) TIMES.

  " Get the character at the current position (sy-index is 1-based, so +sy-index(1) works)
  lv_char = p_value+sy-index(1).

  " Step 3: Convert the character to its HEX representation
  CALL FUNCTION 'NLS_STRING_CONVERT_FROM_SYS'
    EXPORTING
      lang_used = sy-langu          " Use current logon language
      source    = lv_char           " Character to convert
      to_fe     = 'MS '             " Target encoding: Microsoft frontend
    IMPORTING
      result    = lv_hex            " Get the result in HEX
    EXCEPTIONS
      OTHERS    = 1.

  " Step 4: Check if the character is '#' (HEX value 23)
  " If it is, replace with a space
  IF lv_hex IS INITIAL OR lv_hex EQ '23'.
    lv_cleaned = |{ lv_cleaned }{ ' ' } |.  " Append a space
  ELSE.
    " Otherwise, keep the original character
    CONCATENATE lv_cleaned lv_char INTO lv_cleaned.
  ENDIF.

  " Step 5: Clear temporary variables for next loop
  CLEAR: lv_char, lv_hex.

ENDDO.

" Step 6: Copy cleaned result back to input variable
CLEAR p_value.
p_value = lv_cleaned.
  • NLS_STRING_CONVERT_FROM_SYS helps get the true hex value of a character.

Benefits of This Approach

  • Accurate detection – Doesn't rely on visual symbols, it checks the actual byte value.
  • Works for encoded or special characters – Reliable even with unusual frontend encodings.
  • Avoids false removals – Only removes the character if it's truly the hex for " # ".
  • Ideal for downloads, reports, or ALV exports – Ensures clean, consistent output.

Conclusion

Sometimes, a character that looks like a hashtag is not really a " # ". It's important to analyse the hex value of what you're seeing, especially when it causes unexpected behaviour like line breaks or data corruption during export. This method of checking the character at the byte level has saved us hours of debugging — and can save yours too!

What looks like a hashtag might just be a hidden character in disguise!

I hope this helps! Let me know your thoughts or if you have any questions.
Thanks,

Akshay Anil   Linkedin Profile
Technical Consultant, SAP ABAP | BTP | Fiori | Ui5

#ABAP #SAP #DataClean #FileDownload #SAPTips #HexCheck #InvisibleCharacters