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?
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,