This is a test message to test the length of the message box.
Login
ABAP Quick External currency to internal
Created by Software-Heroes

ABAP Quick - External currency to internal

A little tip to convert data from an Excel or CSV file into the correct internal currency format. A simple conversion can quickly lead to errors.

Today a little tip to convert external numbers, for example from an Excel file, into the internal currency format. Here we mainly deal with numbers that are displayed and stored as currency.

Hint: The screenshots shown refer to the output of the german number format for the formatted numbers with currency.

 

Currency format

The problem here is the currency format and how SAP stores such numbers in the system. Here is a simple example to shed light on the "problem" in more detail.

DATA:
  ld_internal_number TYPE bseg-wrbtr,
  ld_output          TYPE char20.

ld_internal_number = CONV #( '123456' ).
out->write( |Number: { ld_internal_number }| ).

WRITE ld_internal_number TO ld_output CURRENCY 'EUR'.
out->write( |EUR: { ld_output }| ).

WRITE ld_internal_number TO ld_output CURRENCY 'JPY'.
out->write( |JPY: { ld_output }| ).

 

We get the following result:

 

You have to know that the EUR currency is defined with two decimal places and the JPY currency has no decimal places. Our external input of 123456 therefore behaves correctly in the number field and as an output in EUR, as we have no shift of the decimal places. If we prepare the same number as JPY, then this number is 100 times too large. This is due to the internal storage and the external processing.

 

Editing

If we work with currencies, we therefore need the correct formatting and preparation of the numbers. We can use the RS_CONV_EX_2_IN function block for this. With the corresponding additional information, he takes the currency into account and correctly fills the internal number field accordingly. The block requires the external format in the corresponding language (see hint).

For our example code, we create a method that wraps the module and use a field from the FI document to prepare the currency. In this case we have to transfer the currency so that the function block knows how to process the number.

METHOD convert_number_to_ext.
  CALL FUNCTION 'RS_CONV_EX_2_IN'
    EXPORTING
      input_external               = CONV char80( id_number )
      table_field                  = VALUE tabfield( tabname = 'BSEG' fieldname = 'WRBTR' )
      currency                     = id_currency
    IMPORTING
      output_internal              = rd_result
    EXCEPTIONS
      input_not_numerical          = 1
      too_many_decimals            = 2
      more_than_one_sign           = 3
      ill_thousand_separator_dist  = 4
      too_many_digits              = 5
      sign_for_unsigned            = 6
      too_large                    = 7
      too_small                    = 8
      invalid_date_format          = 9
      invalid_date                 = 10
      invalid_time_format          = 11
      invalid_time                 = 12
      invalid_hex_digit            = 13
      unexpected_error             = 14
      invalid_fieldname            = 15
      field_and_descr_incompatible = 16
      input_too_long               = 17
      no_decimals                  = 18
      invalid_float                = 19
      conversion_exit_error        = 20
      OTHERS                       = 21.
  IF sy-subrc <> 0.
    rd_result = sy-subrc.
  ENDIF.
ENDMETHOD.

 

To do this, we will use a few examples again and look at the finished preparation of the number. The examples look like this:

out->write( |EUR>123456.78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123456.78` ) }| ).
out->write( |EUR>123456,78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123456,78` ) }| ).
out->write( |EUR>123,456.78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123,456.78` ) }| ).
out->write( |EUR>123.456,78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123.456,78` ) }| ).

out->write( |JPY>123456: { convert_number_to_ext( id_currency = 'JPY' id_number = `123456` ) }| ).
out->write( |JPY>123,456: { convert_number_to_ext( id_currency = 'JPY' id_number = `123,456` ) }| ).
out->write( |JPY>123.456: { convert_number_to_ext( id_currency = 'JPY' id_number = `123.456` ) }| ).

 

We use the German and the English input format for numbers to see whether the logic can cope with different inputs. The output of the routine are now as follows:

 

The function module expects the German formats with commas and thousand points for our scenario. All outputs with a single-digit number are errors that the function block generated because the input format did not match. As you can see, the "real" number in JPY is much smaller in the field after the conversion, because it is saved internally without any decimal places.

 

Example

In addition, like the entire example as an executable class:

CLASS zcl_13bs_tst_convert_ext_num DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
    METHODS:
      convert_number_to_ext
        IMPORTING
                  id_number        TYPE string
                  id_currency      TYPE waers
        RETURNING VALUE(rd_result) TYPE bseg-wrbtr.
ENDCLASS.


CLASS zcl_13bs_tst_convert_ext_num IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    out->write( |EUR>123456.78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123456.78` ) }| ).
    out->write( |EUR>123456,78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123456,78` ) }| ).
    out->write( |EUR>123,456.78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123,456.78` ) }| ).
    out->write( |EUR>123.456,78: { convert_number_to_ext( id_currency = 'EUR' id_number = `123.456,78` ) }| ).

    out->write( |JPY>123456: { convert_number_to_ext( id_currency = 'JPY' id_number = `123456` ) }| ).
    out->write( |JPY>123,456: { convert_number_to_ext( id_currency = 'JPY' id_number = `123,456` ) }| ).
    out->write( |JPY>123.456: { convert_number_to_ext( id_currency = 'JPY' id_number = `123.456` ) }| ).
  ENDMETHOD.


  METHOD convert_number_to_ext.
    CALL FUNCTION 'RS_CONV_EX_2_IN'
      EXPORTING
        input_external               = CONV char80( id_number )
        table_field                  = VALUE tabfield( tabname = 'BSEG' fieldname = 'WRBTR' )
        currency                     = id_currency
      IMPORTING
        output_internal              = rd_result
      EXCEPTIONS
        input_not_numerical          = 1
        too_many_decimals            = 2
        more_than_one_sign           = 3
        ill_thousand_separator_dist  = 4
        too_many_digits              = 5
        sign_for_unsigned            = 6
        too_large                    = 7
        too_small                    = 8
        invalid_date_format          = 9
        invalid_date                 = 10
        invalid_time_format          = 11
        invalid_time                 = 12
        invalid_hex_digit            = 13
        unexpected_error             = 14
        invalid_fieldname            = 15
        field_and_descr_incompatible = 16
        input_too_long               = 17
        no_decimals                  = 18
        invalid_float                = 19
        conversion_exit_error        = 20
        OTHERS                       = 21.
    IF sy-subrc <> 0.
      rd_result = sy-subrc.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

 

Conclusion

The storage of currencies in SAP is very special and should be taken into account when working with internal and external numbers, especially when calculating in addition. With our little tip, the conversion should no longer be a problem.


Included topics:
QuickExternal currencyConversionRS_CONV_EX_2_IN
Comments (0)

ABAP Quick - CLEAR right

Category - ABAP

Delete correctly? In this article we want to take a look at when it makes sense to delete and how you can do it effectively.

05/12/2023

ABAP Quick - Performance chained statements

Category - ABAP

Let's take a look at the performance when creating chained statements with DATA and FIELD-SYMBOL. Which variant will be ahead in terms of performance?

04/28/2023

ABAP - ALV still relevant in 2022?

Category - ABAP

Today the joking question, do we still need reports that generate ALV outputs in 2022? In this article, we want to look into this question.

07/01/2022

ABAP in Change

Category - ABAP

The programming language ABAP has been changing for years and is being modernized in various concepts. In this article, we'll look at it in detail.

06/24/2022

ABAP Quick - Clean Core

Category - ABAP

In this article something about Clean Core, what does it mean for the developer, what are the requirements and what do you have to pay attention to.

06/17/2022