Heute hat ein Gruppenmitglied in unserer Telegram Chatgruppe die Frage gestellt, wie man das Minuszeichen vor dem Wert anstatt hinter dem Wert im ALV anzeigen kann. Dabei soll aber die Möglichkeit der Summen- und Zwischensummenbildung erhalten bleiben.
Anforderung an den Test:
- Einen Weg finden das Minuszeichen vor den Wert zu bringen
- Sicherstellen, dass die Dezimaldarstellung des Benutzers erhalten bleibt
Fragestellung und Entscheidung zur Umsetzung:
- Kann es unter Berücksichtigung des Standards umgesetzt werden?
- Nein, denn weder der Feldkatalog noch das Layout des ALV bieten eine Möglichkeit.
- Muss hier entwickelt werden?
- Ja, wir benötigen eine Konvertierungsroutine. Das bedeutet, dass wir eine Funktionsgruppe und zwei Funktionsbausteine anlegen müssen.
Index der Umsetzungsschritte
- Gedanken über die Anforderung und die Probleme während der Implementierung machen.
- Konvertierungsroutine anlegen.
- Konvertierungsroutine implementieren
- Demo Report
- Ergebnis
Umsetzungsschritte
Info: Ich habe alle Popup mit Warnungen und Paketzuweisungen nicht in Artikel aufgenommen. Alle Warnungen, die in diesem Beispiel auftreten habe ignoriert und die Objekte habe ich in das lokale Paket $TMP aufgenommen.
-
- Gedanken über die Anforderung und die Probleme während der Implementierung machen.
Wenn wir eine Konvertierungsroutine für eine Zahl implementieren möchten, müssen wir auch daran denken, dass die Dezimaldarstellung des Benutzers aus seinen Einstellungen (TAC:SU01/SU3) erhalten bleibt. Das bedeutet, dass wir eine flexible EDIT MASK in die Konvertierungsroutine für die Anzeige einbauen müssen.
-
- Konvertierungsroutine anlegen.
Eine Konvertierungs-Routine wird über einen fünfstelligen Namen identifiziert und ist als Gruppe von zwei Funktionsbausteinen abgelegt. Die Funktionsbausteine haben dabei eine festgelegte Namenskonvention. Der Konvertierungs-Routine xxxxx sind folgende Funktionsbausteine zugeordnet:
-
-
-
- CONVERSION_EXIT_xxxxx_INPUT
- CONVERSION_EXIT_xxxxx_OUTPUT
- Funktionsgruppe anlegen
-
-
Um die benötigte Funktionsgruppe anzulegen, habe ich die Transaktion SE37 benutzt. Dafür sollte das Funktionsbaustein Feld leer bleiben und wir navigieren zu Menü->Springen->FGruppenverwaltung->Gruppe anlegen.
Gewünschten Name und Kurztext für die Gruppe eingeben und Sichern.
Navigiere zum Topinclude der Funktionsgruppe und füge den folgenden Code ein:
1 2 3 4 |
FUNCTION-POOL zstkoes_sign_conversion. "MESSAGE-ID.. DATA: gv_decimal_sign TYPE char1, gv_separator TYPE char1. |
-
-
- Funktionsbaustein Intern -> Anzeige anlegen
-
Im Einstiegsbild der SE37 einen Namen für den Funktionsbaustein eingeben „CONVERSION_EXIT_XXXXX_OUTPUT“ (XXXX durch den gewünschten Namen für die Routine ersetzen).
Den Funktionsbaustein der neuen Funktionsgruppe zuweisen, den Kurztext eingeben und Sichern.
Es ist erforderlich einen Importingparameter mit INPUT zubenennen.
Es ist erforderlich einen Exportingparameter mit OUTPUT zubenennen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
" Get the Decimal Format from the user settings (SU01/SU3) " Dezimaldarstellung aus den Benutzereinstellungen holen (SU01/SU3) IF gv_decimal_sign IS INITIAL. CALL FUNCTION 'CLSE_SELECT_USR01' EXPORTING username = sy-uname iv_delete_buffer = abap_true IMPORTING decimal_sign = gv_decimal_sign separator = gv_separator. ENDIF. DATA(lv_input) = CONV string( input ). DATA(lv_negativ_number) = boolc( lv_input CS '-' ). REPLACE ALL OCCURRENCES OF '-' IN lv_input WITH ''. SPLIT lv_input AT '.' INTO DATA(lv_number) DATA(lv_decimals). REPLACE ALL OCCURRENCES OF '.' IN lv_input WITH ''. DO strlen( lv_number ) TIMES. IF sy-index EQ 1. DATA(lv_mask) = |_|. CONTINUE. ENDIF. lv_mask = |_{ COND #( WHEN sy-index MOD 3 EQ 1 THEN gv_separator ) }{ lv_mask }|. ENDDO. DO strlen( lv_decimals ) TIMES. IF sy-index EQ 1. lv_mask = |{ lv_mask }{ gv_decimal_sign }_|. CONTINUE. ENDIF. lv_mask = |{ lv_mask }_|. ENDDO. lv_mask = |{ COND #( WHEN lv_negativ_number EQ abap_true THEN |-| ) }{ lv_mask }|. WRITE lv_input TO output USING EDIT MASK lv_mask. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
DATA: lv_input TYPE string, lv_negativ_number TYPE abap_bool, lv_number TYPE string, lv_decimals TYPE string, lv_mask TYPE string, lv_string_len TYPE i. " Get the Decimal Format from the user settings (SU01/SU3) " Dezimaldarstellung aus den Benutzereinstellungen holen (SU01/SU3) IF gv_decimal_sign IS INITIAL. CALL FUNCTION 'CLSE_SELECT_USR01' EXPORTING username = sy-uname iv_delete_buffer = abap_true IMPORTING decimal_sign = gv_decimal_sign separator = gv_separator. ENDIF. lv_input = input. IF lv_input CS '-'. lv_negativ_number = boolc( lv_input CS '-' ). ENDIF. REPLACE ALL OCCURRENCES OF '-' IN lv_input WITH ''. SPLIT lv_input AT '.' INTO lv_number lv_decimals. REPLACE ALL OCCURRENCES OF '.' IN lv_input WITH ''. DO strlen( lv_number ) TIMES. IF sy-index EQ 1. lv_mask = '_'. CONTINUE. ENDIF. IF sy-index MOD 3 EQ 1. CONCATENATE gv_separator lv_mask INTO lv_mask. ENDIF. CONCATENATE '_' lv_mask INTO lv_mask. ENDDO. lv_string_len = strlen( lv_decimals ). DO lv_string_len TIMES. IF sy-index EQ 1. CONCATENATE lv_mask gv_decimal_sign '_' INTO lv_mask. CONTINUE. ENDIF. CONCATENATE lv_mask '_' INTO lv_mask. ENDDO. IF lv_negativ_number EQ abap_true. CONCATENATE '-' lv_mask INTO lv_mask. ENDIF. WRITE lv_input TO output USING EDIT MASK lv_mask. |
-
-
- Funktionsbaustein Anzeige -> Intern anlegen
-
Im Einstiegsbild der SE37 einen Namen für den Funktionsbaustein eingeben „CONVERSION_EXIT_XXXXX_OUTPUT“ (XXXX durch den bereits für OUTPUT benutzen Namen für die Routine ersetzen).
Den Funktionsbaustein der neuen Funktionsgruppe zuweisen, den Kurztext eingeben und Sichern.
Es ist erforderlich einen Importingparameter mit INPUT zubenennen.
Es ist erforderlich einen Exportingparameter mit OUTPUT zubenennen.
Für die korrekte Fehlerbehandlung, falls der Benutzer eine ungültige Zahl eingibt, ist es erforderlich einen Exceptionparameter mit ERROR_MESSAGE zubenennen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
" Get the Decimal Format from the user settings (SU01/SU3) " Dezimaldarstellung aus den Benutzereinstellungen holen (SU01/SU3) IF gv_decimal_sign IS INITIAL. CALL FUNCTION 'CLSE_SELECT_USR01' EXPORTING username = sy-uname iv_delete_buffer = abap_true IMPORTING decimal_sign = gv_decimal_sign separator = gv_separator. ENDIF. DATA(lv_input) = CONV string( input ). REPLACE ALL OCCURRENCES OF gv_separator IN lv_input WITH ''. REPLACE gv_decimal_sign IN lv_input WITH '.'. CONDENSE lv_input NO-GAPS. TRY. output = lv_input. CATCH cx_sy_conversion_no_number. " Clear message fields of sy structure, so that 'Conversion error' will be raised " Alle Message Felder der sy Struktur löschen, damit 'Fehler bei der Konvertierung.' geworfen wird CLEAR: sy-msgty, sy-msgno, sy-msgv1, sy-msgv2, sy-msgv3, sy-msgv4. RAISE error_message. ENDTRY. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
DATA: lv_input TYPE string. " Get the Decimal Format from the user settings (SU01/SU3) " Dezimaldarstellung aus den Benutzereinstellungen holen (SU01/SU3) IF gv_decimal_sign IS INITIAL. CALL FUNCTION 'CLSE_SELECT_USR01' EXPORTING username = sy-uname iv_delete_buffer = abap_true IMPORTING decimal_sign = gv_decimal_sign separator = gv_separator. ENDIF. lv_input = input. REPLACE ALL OCCURRENCES OF gv_separator IN lv_input WITH ''. REPLACE gv_decimal_sign IN lv_input WITH '.'. CONDENSE lv_input NO-GAPS. TRY. output = lv_input. CATCH cx_sy_conversion_no_number. " Clear message fields of sy structure, so that 'Conversion error' will be raised " Alle Message Felder der sy Struktur löschen, damit 'Fehler bei der Konvertierung.' geworfen wird CLEAR: sy-msgty, sy-msgno, sy-msgv1, sy-msgv2, sy-msgv3, sy-msgv4. RAISE error_message. ENDTRY. |
-
-
- Aktivierung der neuen Funktionsgruppe und Funktionsbausteine
-
Jetzt müssen die Funktionsgruppe und die Funktionsbausteine noch aktiviert werden.
-
- Konvertierungsroutine implementieren
- Konvertierungsroutine in eine Domäne implementieren
- Konvertierungsroutine implementieren
Nun legen wir eine neue Domäne an oder kopieren eine vorhandene und weisen die neu angelegte Konvertierungsroutine der Domäne zu.
-
-
- Konvertierungsroutine zur Laufzeit in ein ALV implementieren
-
In dem Demo Report findest du, wie du die Konvertierungsroutine zur Laufzeit den Feldern des ALV zuweisen kannst.
-
- Demo Report
Hier ist ein kleiner Demo Report mit der Implementierung.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
REPORT zstkoes_alv_sort. TYPES: BEGIN OF gty_mard, matnr TYPE matnr, werks TYPE werks_d, lgort TYPE lgort_d, labst TYPE labst, zlabst TYPE zlabst, h_level TYPE h_level, END OF gty_mard, gtty_mard TYPE gty_mard. DATA: gt_mard TYPE TABLE OF gtty_mard. gt_mard = VALUE #( ( matnr = CONV numc4( 1 ) werks = '0001' lgort = '0001' labst = '-9.999' zlabst = '-9.999' h_level = -99999999 ) ( matnr = CONV numc4( 1 ) werks = '0001' lgort = '0002' labst = '-99.999' zlabst = '-99.999' h_level = -9999999 ) ( matnr = CONV numc4( 1 ) werks = '0002' lgort = '0001' labst = '-999.999' zlabst = '-999.999' h_level = -999999 ) ( matnr = CONV numc4( 1 ) werks = '0002' lgort = '0002' labst = '-9999.999' zlabst = '-9999.999' h_level = -99999 ) ( matnr = CONV numc4( 2 ) werks = '0001' lgort = '0001' labst = '-99999.999' zlabst = '-99999.999' h_level = -9999 ) ( matnr = CONV numc4( 2 ) werks = '0001' lgort = '0002' labst = '-999999.999' zlabst = '-999999.999' h_level = -999 ) ( matnr = CONV numc4( 2 ) werks = '0002' lgort = '0001' labst = '-9999999.999' zlabst = '-9999999.999' h_level = -99 ) ( matnr = CONV numc4( 2 ) werks = '0002' lgort = '0002' labst = '-99999999.999' zlabst = '-99999999.999' h_level = -9 ) ). cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lo_table) " Basisklasse einfache ALV Tabellen CHANGING t_table = gt_mard ). lo_table->get_functions( )->set_all( ). DATA(it_column_ref) = lo_table->get_columns( )->get( ). LOOP AT it_column_ref ASSIGNING FIELD-SYMBOL(<st_column_ref>). CASE <st_column_ref>-columnname. WHEN 'H_LEVEL'. <st_column_ref>-r_column->set_edit_mask( value = '==ZSIGN' ). ENDCASE. ENDLOOP. lo_table->display( ). |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
REPORT zstkoes_alv_sort. TYPES: BEGIN OF gty_mard, matnr TYPE matnr, werks TYPE werks_d, lgort TYPE lgort_d, labst TYPE labst, zlabst TYPE zlabst, h_level TYPE h_level, END OF gty_mard, gtty_mard TYPE gty_mard. DATA: gt_mard TYPE TABLE OF gtty_mard, gt_column_ref TYPE SALV_T_COLUMN_REF, go_salv TYPE REF TO cl_salv_table. FIELD-SYMBOLS: <gs_mard> TYPE gty_mard, <gs_column_ref> TYPE salv_s_column_ref. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0001'. <gs_mard>-werks = '0001'. <gs_mard>-lgort = '0001'. <gs_mard>-labst = '-9.999'. <gs_mard>-zlabst = '-9.999'. <gs_mard>-h_level = -99999999. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0001'. <gs_mard>-werks = '0001'. <gs_mard>-lgort = '0002'. <gs_mard>-labst = '-99.999'. <gs_mard>-zlabst = '-99.999'. <gs_mard>-h_level = -9999999. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0001'. <gs_mard>-werks = '0002'. <gs_mard>-lgort = '0001'. <gs_mard>-labst = '-999.999'. <gs_mard>-zlabst = '-999.999'. <gs_mard>-h_level = -999999. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0001'. <gs_mard>-werks = '0002'. <gs_mard>-lgort = '0002'. <gs_mard>-labst = '-9999.999'. <gs_mard>-zlabst = '-9999.999'. <gs_mard>-h_level = -99999. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0002'. <gs_mard>-werks = '0001'. <gs_mard>-lgort = '0001'. <gs_mard>-labst = '-99999.999'. <gs_mard>-zlabst = '-99999.999'. <gs_mard>-h_level = -9999. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0002'. <gs_mard>-werks = '0001'. <gs_mard>-lgort = '0002'. <gs_mard>-labst = '-999999.999'. <gs_mard>-zlabst = '-999999.999'. <gs_mard>-h_level = -999. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0002'. <gs_mard>-werks = '0002'. <gs_mard>-lgort = '0001'. <gs_mard>-labst = '-9999999.999'. <gs_mard>-zlabst = '-9999999.999'. <gs_mard>-h_level = -99. APPEND INITIAL LINE TO gt_mard ASSIGNING <gs_mard>. <gs_mard>-matnr = '0002'. <gs_mard>-werks = '0002'. <gs_mard>-lgort = '0002'. <gs_mard>-labst = '-99999999.999'. <gs_mard>-zlabst = '-99999999.999'. <gs_mard>-h_level = -9. cl_salv_table=>factory( IMPORTING r_salv_table = go_salv CHANGING t_table = gt_mard ). go_salv->get_functions( )->set_all( ). gt_column_ref = go_salv->get_columns( )->get( ). LOOP AT gt_column_ref ASSIGNING <gs_column_ref>. CASE <gs_column_ref>-columnname. WHEN 'H_LEVEL'. <gs_column_ref>-r_column->set_edit_mask( value = '==ZSIGN' ). ENDCASE. ENDLOOP. go_salv->display( ). |
-
- Ergebnis
So sieht das Ergebnis der Entwicklung aus.
-
- Die vierte Spalte „Frei verwendbar“ benutzt die neue Konvertierungsroutine nicht und zeigt das Minuszeichen somit hinter dem Wert an.
- Die fünfte Spalte „Frei verwendbar“ benutzt die neue Konvertierungsroutine und zeigt das Minuszeichen, wie erwartet, somit vor dem Wert an.
- Die sechste Spalte „Baugruppenstufe“ ist vom Typ Integer, benutzt die neue Konvertierungsroutine und zeigt das Minuszeichen, wie erwartet, somit vor dem Wert an.