
ABAP Cloud - Eigene Einheit
In diesem Artikel schauen wir uns an, wie wir eigene Einheiten im System definieren können und diese dann in unserer RAP Anwendung anbinden.
Inhaltsverzeichnis
In diesem Artikel werden wir eine neue Maßeinheit im System anlegen. Dabei werden wir uns die API anschauen und später die Einheit in unserer Anwendung einbinden.
Einleitung
Der Standard liefert normalerweise genug Standardeinheiten aus, die du bereits Out-of-the-Box verwenden kannst. Es kann aber auch vorkommen, dass du selbst einmal eine Einheit anlegen musst, um einen speziellen Fall in deiner Anwendung abzudecken. Dazu legen wir in diesem Artikel eine eigene Einheit an und schauen uns die verschiedenen Optionen an.
Grundlage
In der Vergangenheit hättest du dir die Einheiten aus den verschiedenen Tabellen suchen müssen, wenn du mal die Einheit lesen wolltest. Benötigst du dann noch den Text, musst du schon wieder die nächste Tabelle einbinden. Für ISO Code, Dimensionen und andere Dinge greifst du direkt auf die nächsten Tabellen zu. Alle nicht wirklich beschrieben oder zusammenhängend. Da wir aber bereits in der Welt der Core Data Services leben, steht uns der View I_UnitOfMeasure zur Verfügung. Hast du dir den Namen einmal gemerkt, reicht das für den Rest an Informationen, da du über die Assoziationen nachlesen kannst.
SELECT FROM I_UnitOfMeasure
FIELDS UnitOfMeasure,
UnitOfMeasureISOCode,
\_Text[ Language = @sy-langu ]-UnitOfMeasureName,
\_Text[ Language = @sy-langu ]-UnitOfMeasureLongName,
\_Dimension-UnitOfMeasureDimension
INTO TABLE @DATA(result)
UP TO 10 ROWS.
Als Ergebnis erhalten wir nach unserem übersichtlichen Select alle Daten, die wir benötigen, ohne die Joins zwischen den Tabellen zu bilden. Allerdings müssen wir hier die Sprache berücksichtigen, da wir den sonst den Text in der falschen Sprache erhalten.
API
Wollen wir eigene Einheiten anlegen, dann steht uns die API CL_UOM_MAINTENANCE zur Verfügung. Damit können wir eigene Einheiten anlegen, ändern, löschen und mit Texten in verschiedenen Sprachen versorgen.
Anlage
In unserem ersten Beispiel wollen wir eine neue Einheit definieren. Noch vor einigen Releases gab es im ABAP Environment nur die Möglichkeit Z* Einheiten anzulegen. Diese Beschränkung wurde aufgehoben und wir können mittlerweile auch Standardeinheiten verändern oder Einheiten im Standard Namensraum anlegen. In diesem Fall legen wir eine Einheit FPR an, diese steht für "Full Percent" und soll eine Prozenteinheit ohne Komma darstellen. Im ersten Schritt instanziieren wir die API.
DATA(unit) = cl_uom_maintenance=>get_instance( ).
Im zweiten Schritt definieren wir die Werte für unsere neue Einheit. Die Dezimalstellen setzen wir auf null, da die Einheit keine Kommastellen haben soll. Ebenfalls geben wir hier einen ersten Text für die neue Einheit mit.
DATA(setting) = VALUE cl_uom_maintenance=>ty_uom_cre_ts(
commercial = 'FPR'
technical = 'FPR'
denominator = 100
numerator = 1
dec_disp = 0
dec_round = 0
iscommercial = abap_true
isocode = 'P1'
text = 'Percent'
long_text = 'Percent (Short)' ).
Über die Methode CREATE geben wir noch eine passende Dimension mit, diese haben wir aus dem Original (Prozent). Die API sollte nun die neue Einheit anlegen und der ERROR_STATUS leer bleiben. Ein Protokoll erhalten wir in diesem Fall nicht. Eine Fehlermeldung sollte aber in der Ausnahme stehen, wenn eine geworfen wird.
unit->create( EXPORTING unit_dimid = 'PROPOR'
unit_int = 'FPR'
unit_cre_ts = setting
IMPORTING error = DATA(error_status) ).
Texte
Schauen wir uns die Texte im Data Preview an, dann werden wir feststellen, dass wir aktuell nur die angelegten Grundtexte in Englisch haben. Hier wollen wir auch weitere Sprachen verfügbar machen.
Über die Methode MAINTAIN_TRANSLATION können wir neue Sprachen pflegen, allerdings müssen wir dafür Sprache für Sprache an die Methode übergeben. Auch hier wird das entsprechende Fehlerkennzeichen gesetzt bzw. eine Ausnahme ausgelöst, wenn die Pflege fehlschlägt.
unit->maintain_translation( EXPORTING language = 'D'
unit_int = 'FPR'
commercial = 'FPR'
technical = 'FPR'
text = 'Prozent'
long_text = 'Prozent (Kurz)'
IMPORTING error = DATA(error_status) ).
unit->maintain_translation( EXPORTING language = 'F'
unit_int = 'FPR'
commercial = 'FPR'
technical = 'FPR'
text = 'Pour cent'
long_text = 'Pourcentage (court)'
IMPORTING error = error_status ).
Prüfen wir nach Ausführung noch einmal unseren Core Data Service, dann finden wir die beiden zusätzlichen Sprachen in der Tabelle.
Löschen
Passt uns die Einheit nicht oder der Test ist zu Ende, dann kannst du über die Methode DELETE die Einheit aus dem System entfernen.
unit->delete( EXPORTING unit = 'ZPR'
IMPORTING error = DATA(error_status) ).
Hinweis: Denk beim Löschen von Einheiten vor allem an Nebeneffekte, die in Anwendungen entstehen können, wo die Einheit bereits verwendet wird. Also nur Einheiten bearbeiten, wo du dir über die Nutzung im Klaren bist.
Transport
Die Methode GET_INSTANCE gibt dir die Möglichkeit auch einen Transportauftrag mitzugeben. Hier kannst du alle Tabelleneinträge aufzeichnen und auf die Folgesysteme bringen.
Erweiterung
Erweitern wir nun unsere Sales App, um die neue Einheit einmal im UI zu testen. Dazu benötigen wir an unserem Feld eine Wertehilfe. Neben dem Standard gibt es auch den View I_UnitOfMeasureStdVH für die Wertehilfe. Dazu erweitern wir unseren Core Data Service ZBS_C_SASale um die Annotation und das Mapping des Elements.
@Consumption.valueHelpDefinition: [{ entity: { name: 'I_UnitOfMeasureStdVH', element : 'UnitOfMeasure' } }]
DifferenceUnit,
Zum Abschluss nehmen wir die Suchhilfe noch mit in die Service Definition auf, damit sie zusammen mit unserem Service ausgeliefert und berechtigt wird.
expose I_UnitOfMeasureStdVH;
Test wir zum Abschluss einmal unsere Anwendung mit der neuen Einheit. Dazu wählen wir in der Suchhilfe die neue Einheit und befüllen die erste Zahl. Im nächsten Schritt wollen wir eine Zahl mit Komma verwenden, was aber nicht funktioniert, da unsere neue Einheit kein Komma zulässt. Auch die Formatierung der Zahl stellt ohne Komma dar, wie nach der ersten Eingabe gezeigt.
Fehler
Löschen wir die Einheit aus dem System und rufen im Nachgang unsere Anwendung auf, funktioniert diese erst einmal weiter. Navigieren wir dann allerdings auf einen Eintrag, wo die Einheit gepflegt wurde, sehen wir den Nebeneffekt, da wir vorher nicht unsere Stammdaten bereinigt haben. Der Eintrag wird nicht mehr geladen und wir erhalten eine Fehlermeldung.
Vollständiges Beispiel
Die Erweiterung in der App findest du als Commit im GitHub Repository, da wo alle RAP Beispiele liegen. Die Klasse aus dem Artikel findest du hier, diese ist nicht Teil des Projektes.
CLASS zcl_bs_demo_custom_unit DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
METHODS select_units
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS create_unit
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS delete_unit
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS create_translation
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.
CLASS zcl_bs_demo_custom_unit IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
select_units( out ).
create_unit( out ).
create_translation( out ).
delete_unit( out ).
ENDMETHOD.
METHOD select_units.
SELECT FROM I_UnitOfMeasure
FIELDS UnitOfMeasure,
UnitOfMeasureISOCode,
\_Text[ Language = @sy-langu ]-UnitOfMeasureName,
\_Text[ Language = @sy-langu ]-UnitOfMeasureLongName,
\_Dimension-UnitOfMeasureDimension
INTO TABLE @DATA(result)
UP TO 10 ROWS.
out->write( result ).
ENDMETHOD.
METHOD create_unit.
DATA(unit) = cl_uom_maintenance=>get_instance( ).
TRY.
DATA(setting) = VALUE cl_uom_maintenance=>ty_uom_cre_ts( commercial = 'FPR'
technical = 'FPR'
denominator = 100
numerator = 1
dec_disp = 0
dec_round = 0
iscommercial = abap_true
isocode = 'P1'
text = 'Percent'
long_text = 'Percent (Short)' ).
unit->create( EXPORTING unit_dimid = 'PROPOR'
unit_int = 'FPR'
unit_cre_ts = setting
IMPORTING error = DATA(error_status) ).
out->write( error_status ).
CATCH cx_uom_error INTO DATA(error).
out->write( error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD create_translation.
DATA(unit) = cl_uom_maintenance=>get_instance( ).
TRY.
unit->maintain_translation( EXPORTING language = 'D'
unit_int = 'FPR'
commercial = 'FPR'
technical = 'FPR'
text = 'Prozent'
long_text = 'Prozent (Kurz)'
IMPORTING error = DATA(error_status) ).
out->write( error_status ).
unit->maintain_translation( EXPORTING language = 'F'
unit_int = 'FPR'
commercial = 'FPR'
technical = 'FPR'
text = 'Pour cent'
long_text = 'Pourcentage (court)'
IMPORTING error = error_status ).
out->write( error_status ).
CATCH cx_uom_error INTO DATA(error).
out->write( error->get_text( ) ).
ENDTRY.
ENDMETHOD.
METHOD delete_unit.
DATA(unit) = cl_uom_maintenance=>get_instance( ).
TRY.
unit->delete( EXPORTING unit = 'FPR'
IMPORTING error = DATA(error_status) ).
out->write( error_status ).
CATCH cx_uom_error INTO DATA(error).
out->write( error->get_text( ) ).
ENDTRY.
ENDMETHOD.
ENDCLASS.
Fazit
Mit der Standard API ist es möglich die Einheiten im System anzupassen oder eigene Einheiten zu definieren. In der Vergangenheit hatten einige Kunden den Wunsch eigene Einheiten zu definieren, da diese auch On-Prem verfügbar waren und in der BTP verarbeitet werden sollten. Wichtig ist aber auch, beachte die Hinweise in der Dokumentation zum Umgang mit eigenen Einheiten.
Quelle:
SAP Help - Maintaining Units of Measurement
SAP Help - Retrieving and Resetting Standard Units of Measurement





