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

2534

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)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ABAP in Practice - String Processing

Category - ABAP

In this practical example we look at the string processing to determine the CDS names in CamelCase and how you can implement this with ABAP.

10/15/2024

ABAP in Practice - Test Driven Development

Category - ABAP

How does TDD actually work in practice and are there simple examples for learning in ABAP? In this exercise we will look at the practical part.

09/24/2024

ABAP in Practice - Merge data sets

Category - ABAP

How do we merge two different data sets in ABAP, especially with regard to Modern ABAP? A practical task for this topic.

09/17/2024

ABAP in Practice - Modern ABAP

Category - ABAP

In this small task we look at existing classic ABAP source code and try to optimize it according to Modern ABAP.

08/27/2024

ABAP Quick - Performance Data Filtering

Category - ABAP

Which statement do you use in ABAP to filter internal tables and is it performant? Read more in this article.

08/13/2024