Conversion Exit to format Amounts for Specific Currency in ALV

By | October 23, 2013 | Tricks | 25,774 | 2

Conversion Exit to Format the Amount with using the respective currency in ALV created by SALV Model.

Preface

In the last article Conversion Exit to format Amounts in ALV, I have demonstrated on how you can achieve the Amount formatting. That formatting was only for one currency $ dollars. I didn’t consider the Currency along with the Amount. So, I knew one of you might ask how, you can achieve it for multiple currencies. Vijay Dudla asked that question on last article.

How this can be done for different currency, suppose if i have a report with different currency and i want different functionality based on currency, how can you find which currency you are doing the conversion in the routine.

Challenges

Conversion Exit accepts the value and convert it to the desired format. Since we can only pass a single Value to the conversion routine, it posed a first challenge to make the solution work.

There is no easy way to identify the currency only from the Amount. I thought of using the DESCRIBE on amount to find out if I can get the associated currency. I also checked the system fields, I can leverage to get the Currency from.

You might think that – Pass the currency to a memory before ALV is generated, access that in the Conversion routine and use it to formulate. But this doesn’t work as you need the currency from corresponding row.

Workable solution

So here is how I kind of solved this:

  • Create a Dummy Conversion routine. Assign it to Currency Column. The dummy conversion routine FM needs to be created in the Same FG where the Amount conversion FM is created. In this Dummy Conversion FM, save the currency value to Global Variable.
  • Access this global variable in the Amount Conversion Exit to derive the symbol. Use the Symbol to concatenate and make the output

Sounds great, huh? Not that simple. There are few more things to consider

  • The Conversion Routine for Currency needs to be executed before the Amount Conversion routine in order to save currency in the global variable. That means the Currency column needs to be before the Amount currency always.
  • To make sure, the currency column stays in front of Amount column, I need to implement the event AFTER_SALV_FUNCTION of SALV model. In the event handler, I added logic to renumber the currency and Amount Column.
  • You also can’t make the Currency column as currency column for the amount. Doing this, doesn’t trigger the Amount conversion routine at all.
  • For Fullscreen, the function “Hide” doesn’t trigger the After SALV event. Thus it renders the ALV incorrect Currency when you hide the Currency column

Conversion Exit for Currency

I created the ZCURR conversion exit for currency. Here is the dummy Conversion for Currency.

CONVERSION_EXIT_ZCURR_OUTPUT

 
FUNCTION CONVERSION_EXIT_ZCURR_OUTPUT.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(INPUT) TYPE  CLIKE
*"  EXPORTING
*"     REFERENCE(OUTPUT) TYPE  CLIKE
*"----------------------------------------------------------------------
*
  output = input.
*
  v_waers_buffer = input.        " Global variable
*
ENDFUNCTION.
 

Redefined Amount Conversion Exit

After adding this new conversion exit FM, here is the redefined version of CONVERSION_EXIT_ZSIGN_OUTPUT

I have hardcoded the currency and Symbols here for demo. But you can create a custom table to store the currency and symbol as suggested by Mohinder in his comment.

CONVERSION_EXIT_ZSIGN_OUTPUT with Currency

 
FUNCTION conversion_exit_zsign_output.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(INPUT) TYPE  DMBTR
*"  EXPORTING
*"     REFERENCE(OUTPUT) TYPE  CLIKE
*"----------------------------------------------------------------------
 
  DATA: lv_dmbtr TYPE bseg-dmbtr.
  DATA: lv_output TYPE char20.
  DATA: lv_dmbtr_c TYPE char17.
  DATA: lv_symbol TYPE char1.
 
 
  TRY.
      lv_dmbtr = input.
      WRITE lv_dmbtr TO lv_dmbtr_c NO-SIGN.
      CONDENSE lv_dmbtr_c.
      IF lv_dmbtr LT 0.
        CONCATENATE '(' lv_dmbtr_c ')' INTO lv_dmbtr_c.
      ENDIF.
*      WRITE lv_dmbtr_c TO lv_output RIGHT-JUSTIFIED.
*      lv_output+0(1) = '$'.
*
* This can be saved in Config
      CASE v_waers_buffer.
        WHEN 'EUR'.
          lv_symbol = '€'.
        WHEN 'USD'.
          lv_symbol = '$'.
        WHEN OTHERS.
          lv_symbol = '$'.
      ENDCASE.
      CONCATENATE lv_dmbtr_c lv_symbol INTO lv_output SEPARATED BY `   `.
      output = lv_output.
    CATCH cx_root.
  ENDTRY.
ENDFUNCTION.
 

Demo Program

Program needs to be adjusted to include the event to reset the Currency and Amount columns. Here is the code lines with Event handler

Format Amount in ALV for specific Currency

 
REPORT  ZTEST_NP_SALV_FORMAT_AMOUNT2.
*
CLASS lcl_main DEFINITION.
  PUBLIC SECTION.
    DATA o_salv TYPE REF TO cl_salv_table .
    TYPES:
      BEGIN OF ty_output,
        status TYPE char10,
        waers  TYPE bkpf-waers,
        dmbtr  TYPE bseg-dmbtr,
      END   OF ty_output.
    DATA: t_output TYPE STANDARD TABLE OF ty_output.
    METHODS:
      select_data,
      generate_alv.
  PRIVATE SECTION.
    METHODS:
      set_after_events            " After Event
        FOR EVENT after_salv_function OF cl_salv_events_table
          IMPORTING
            e_salv_function.
ENDCLASS.                    "lcl_main DEFINITION
*
START-OF-SELECTION.
  DATA: o_main TYPE REF TO lcl_main.
  CREATE OBJECT o_main.
  o_main->select_data( ).
  o_main->generate_alv( ).
*
CLASS lcl_main IMPLEMENTATION.
  METHOD select_data.
    INCLUDE: <icon>.
    DATA: ls_output LIKE LINE OF t_output.
    DO 3 TIMES.
      ls_output-status = icon_green_light.
      ls_output-waers  =  'USD'.
      ls_output-dmbtr  = '10000'.
      APPEND ls_output TO t_output.
      ls_output-status = icon_yellow_light.
      ls_output-waers  =  'USD'.
      ls_output-dmbtr  = '-200.00'.
      APPEND ls_output TO t_output.
      ls_output-status = icon_red_light.
      ls_output-waers  =  'EUR'.
      ls_output-dmbtr  = '-212.45'.
      APPEND ls_output TO t_output.
    ENDDO.
 
  ENDMETHOD.                    "select_Data
  METHOD generate_alv.
    DATA: lo_functions            TYPE REF TO cl_salv_functions_list.
    DATA: lo_functional_settings  TYPE REF TO cl_salv_functional_settings.
    DATA: lo_tooltips             TYPE REF TO cl_salv_tooltips,
          lv_value                TYPE lvc_value.
    DATA: lo_columns              TYPE REF TO cl_salv_columns.
    DATA: lo_column               TYPE REF TO cl_salv_column_table.
    INCLUDE: <icon>.
*
* ALV Object
    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table = o_salv
          CHANGING
            t_table      = t_output ).
      CATCH cx_salv_msg.                                "#EC NO_HANDLER
    ENDTRY.
* Functions
    lo_functions = o_salv->get_functions( ).
    lo_functions->set_all( abap_true ).
*... set the columns
    lo_columns = o_salv->get_columns( ).
    TRY.
        lo_column ?= lo_columns->get_column( 'STATUS' ).
        lo_column->set_icon( if_salv_c_bool_sap=>true ).
        lo_column->set_alignment( if_salv_c_alignment=>centered ).
        lo_column->set_output_length( 20 ).
      CATCH cx_salv_not_found.                          "#EC NO_HANDLER
    ENDTRY.
    TRY.
        lo_column ?= lo_columns->get_column( 'DMBTR' ).
        "lo_column->SET_CURRENCY_COLUMN( 'WAERS' ).
        lo_column->set_edit_mask( '==ZSIGN' ).
      CATCH cx_salv_not_found.                          "#EC NO_HANDLER
    ENDTRY.
    TRY.
        lo_column ?= lo_columns->get_column( 'WAERS' ).
        lo_column->set_edit_mask( '==ZCURR' ).
      CATCH cx_salv_not_found.                          "#EC NO_HANDLER
    ENDTRY.
 
*...Events
    DATA: lo_events TYPE REF TO cl_salv_events_table.
    lo_events = o_salv->get_event( ).
    SET HANDLER me->set_after_events FOR lo_events.
 
*... display the table
    o_salv->display( ).
  ENDMETHOD.                    "generate_alv
*
  METHOD set_after_events.
 
    DATA: lo_columns              TYPE REF TO cl_salv_columns.
    DATA: lo_column               TYPE REF TO cl_salv_column_table.
    DATA: lv_amt_col_pos TYPE i.
*
    lo_columns = o_salv->get_columns( ).
    IF lo_columns->get_column( 'DMBTR' )->is_visible( ) = 'X'.
      TRY.
          lo_column ?= lo_columns->get_column( 'WAERS' ).
          lo_column->SET_VISIBLE( 'X' ).
        CATCH cx_salv_not_found.                          "#EC NO_HANDLER
      ENDTRY.
 
      lv_amt_col_pos = lo_columns->get_column_position( 'DMBTR' ).
      lo_columns->set_column_position(
          columnname =  'WAERS'
          position   =  lv_amt_col_pos
      ).
      lo_columns->set_column_position(
          columnname =  'DMBTR'
          position   =  lv_amt_col_pos + 1
      ).
 
      o_salv->refresh( refresh_mode = if_salv_c_refresh=>full ).
    ENDIF.
 
  ENDMETHOD.                    "set_after_events
ENDCLASS.                    "lcl_main IMPLEMENTATION
 

Output

This is how it looks now:

Your thoughts?

Like It? Share!!

Don't miss an Update

Get notified of the new post, right into your inbox

Naimesh Patel{274 articles}

I'm SAP ABAP Consultant for more than a decade. I like to experiment with ABAP especially OO. I have been SDN Top Contributor.
Follow :

Explore all of his 274 articles.

Load comments

2 Comments

  • Vijay Dudla

    Hi Niamesh,

    Great blog, It will be definitely useful to someone for sure. I like the way you present it. Much appreciated.

    Thanks
    Vijay

  • Hello Vijay,

    Glad that you like and appreciate my research.

    Regards,

Comments on this Post are now closed. If you have something important to share, you can always contact me.

You seem to be new here. Subscribe to stay connected.