In diesem Blogbeitrag beschreibe ich, wie man eine SE11 Standard Suchhilfe in eine SAP Fiori Elements Anwendung auf Basis von Custom Entitys einbinden kann. SE11 Suchhilfen gibt es schon ewig und sind aus einem SAP-System nicht wegzudenken. In einem aktuellen S/4 System sind nach wie vor über 30.000 SE11 Suchhilfen vorhanden. Zudem wurden im Laufe der Jahre durch die SAP-Kunden viele Suchhilfen dazu entwickelt. Und daher macht es durchaus Sinn, diese auch in SAP Fiori Elements oder UI5 Anwendungen zu verwenden.
Zum Zeitpunkt dieses Blogs ist mir keine Möglichkeit im SAP Standard bekannt (abgesehen vom Ansatz mit dem SAP Gateway), die SE11 Original-Suchhilfen einfach und schnell in vorhandene SAP Fiori Elements Anwendungen zu integrieren. Aber ehrlich gesagt rechne ich damit, dass dies irgendwann in Zukunft durch spezielle Annotations möglich sein wird. Sollte sich daran was ändern, werde ich diesen Blog natürlich erweitern. Aber bis es so weit ist, müssen wir uns mit ein paar Workarounds helfen.
Wie gesagt, ich beschreibe eine Lösungsmöglichkeit via Custom Entitys. Diese sind erst ab einem S/4 1909 System verfügbar. Es gibt, wie oben erwähnt, auch den Ansatz die Suchhilfe mit Hilfe von SAP Gateway zu implementieren. Lutz Rosenpflanzer beschreibt dies in seinem Blog Custom data selection for a Fiori list report application using DDIC Search help sehr gut.
Allgemeines
Prinzipiell müssen wir einmal Sammelsuchhilfen und elementare Suchhilfen unterschieden. Sammelsuchhilfen bestehen aus einer oder mehreren elementaren Suchhilfen. Der hier gezeigte Ansatz verfolgt nur die Integration von elementaren Suchhilfen. Aber natürlich können einzelne Suchhilfen wieder über Annotations zu Sammelsuchhilfen zusammengefügt werden. An dieser Stelle verweise ich auf den Blog Fiori Element: Collective / Multiple value help on selection field von Mohit Bansal. Er zeigt in seinem Blog, wie man mehrere CDS Views als Suchhilfen einbinden kann.
Elementare Suchhilfen welche als Selektionsmethode eine Datenbanktabelle oder einen DB-View verwenden und keinen speziellen Suchhilfe-Exit implementiert haben, können auch mit Hilfe eines klassischen CDS View nachgebildet werden. Dann erspart man sich die zusätzliche ABAP Implementierung. Eine gute Beschreibung dazu findet man in in diesem Blog Fiori Elements-Value help on a selection field within a value help dialog ebenfalls von Mohit Bansal.
Elementare Suchhilfen verwenden jedoch sehr oft Suchhilfe-Exits, dann reicht der Ansatz über klassische CDS Views nicht aus. Mit Hilfe der Custom Entitys können wir unser Vorhaben umsetzen. In dem nachfolgenden Beispiel wird die Suchilfe BUPAP des SAP Business Partners verwendet. Die Suchhilfe besteht lediglich aus einem Suchhilfe Exit.
Step 1 – ABAP Klasse
Zuerst brauchen wir eine ABAP Klasse, welche dann später in der Custom Entity verwendet wird. Die ABAP Klasse muss das Interface if_rap_query_provider implementieren.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
CLASS zcl_cq_value_help_bupap DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_rap_query_provider. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_cq_value_help_bupap IMPLEMENTATION. METHOD if_rap_query_provider~select. ENDMETHOD. ENDCLASS. |
Step 2 – Custom Entity
Nun legen wir noch die Custom Entity ZCE_VALUE_HELP_BUPAP an.
1 2 3 4 5 6 7 8 9 10 11 |
@EndUserText.label: 'Value Help for BUPAP' @ObjectModel: { query: { implementedBy: 'ABAP:zcl_cq_value_help_bupap' } } define root custom entity zce_value_help_bupap { } |
Mit der Annotation ObjectModel.Query.implementedBy wird die zuvor angelegte ABAP Klasse hinterlegt. Nun müssen wir noch auf Basis der Parameter der Suchhilfe, die Custom Entity aufbauen. Die SE11 Suchhilfe sieht wie folgt aus:
Exakt diesen Aufbau bilden wir nun auch in der Custom Entity ab.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@EndUserText.label: 'Value Help for BUPAP' @ObjectModel: { query: { implementedBy: 'ABAP:zcl_cq_value_help_bupap' } } define root custom entity zce_value_help_bupap { key partner : bu_partner; mc_name1 : bu_mcname1; mc_name2 : bu_mcname2; bu_sort1 : bu_sort1; bu_sort2 : bu_sort2; type : bu_type; valdt : bu_valdt_s; } |
Eine Custom Entity benötigt zwingend ein KEY-Feld. In dem Fall verwenden wir natürlich PARTNER welches auch der Value ist, welcher durch die Suchhilfe zurückgeliefert wird.
Step 3 – Implementierung der Query-Methode
Jetzt wird es spannend, wir implementieren die Suche in der ABAP Query Methode. Glücklicherweise gibt es die Klasse cl_dsh_type_ahead_processor, die uns hier enorm weiterhilft und vieles abnimmt. Mit Hilfe der Klasse prozessieren wir die Suchhilfe.
1 2 3 4 5 6 7 8 |
dsh = cl_dsh_type_ahead_processor=>create_instance_for_shlp( i_search_help_name = 'BUPAP' i_referenced_field_name = 'PARTNER' i_additional_parameters = lt_additional_parameters i_use_extended_select_options = lv_extnd_so i_force_type_ahead = abap_true ). table_ref = dsh->get_result_descriptor( ). |
Alle restlichen Entwicklungen (Sort, Skip, Top, … ) haben nichts mehr speziell mit der Suchhilfe zu tun, sind aber notwendig damit die Custom Entity korrekt funktioniert und SADL keine Fehler liefert. Andre Fischer beschreibt in seinem Blog How to implement a custom entity in the ABAP RESTful Programming Model using remote function modules, wie die Search Methode einer Custom Entity zu implementieren ist.
Am Ende sollte die Query Implementierung in etwa wie folgt aussehen:
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 |
METHOD if_rap_query_provider~select. DATA lv_extnd_so TYPE abap_bool VALUE abap_true. DATA lt_additional_parameters TYPE if_dsh_type_ahead_processor=>ty_s_additional_parameters. DATA table_ref TYPE REF TO cl_abap_tabledescr. DATA result_ref TYPE REF TO data. DATA lv_req TYPE if_dsh_type_ahead_processor=>ty_type_ahead_request. DATA max_rows TYPE i. DATA dsh TYPE REF TO if_dsh_type_ahead_processor. DATA lt_sort_local TYPE abap_sortorder_tab. FIELD-SYMBOLS <result> TYPE STANDARD TABLE. IF io_request->is_data_requested( ). DATA(lv_top) = io_request->get_paging( )->get_page_size( ). DATA(lv_skip) = io_request->get_paging( )->get_offset( ). DATA(lt_fields) = io_request->get_requested_elements( ). DATA(lt_sort) = io_request->get_sort_elements( ). DATA(lt_filter_cond) = io_request->get_filter( )->get_as_ranges( ). lt_additional_parameters-field_values = CORRESPONDING #( lt_filter_cond MAPPING name = name params = range ). dsh = cl_dsh_type_ahead_processor=>create_instance_for_shlp( i_search_help_name = 'BUPAP' i_referenced_field_name = 'PARTNER' i_additional_parameters = lt_additional_parameters i_use_extended_select_options = lv_extnd_so i_force_type_ahead = abap_true ). table_ref = dsh->get_result_descriptor( ). CREATE DATA result_ref TYPE HANDLE table_ref. ASSIGN result_ref->* TO <result>. dsh->get_type_ahead_values( EXPORTING i_type_ahead_request = lv_req i_max_results = max_rows IMPORTING e_type_ahead_values = <result> ). lt_sort_local = CORRESPONDING #( lt_sort MAPPING name = element_name ). IF lt_sort_local IS NOT INITIAL. SORT <result> BY (lt_sort_local). ENDIF. io_response->set_total_number_of_records( lines( <result> ) ). IF lv_skip > 0. DELETE <result> FROM 1 TO lv_skip. ENDIF. IF lv_top > 0. DELETE <result> FROM lv_top + 1. ENDIF. io_response->set_data( <result> ). ENDIF. ENDMETHOD. |
Step 4 – Service Definition & Service Bindung
Dieser Schritt ist jetzt nicht zwingend notwendig. Hier geht es nur darum, dass wir die neue Custom Entity testen wollen.
Service Definition
1 2 3 4 |
@EndUserText.label: 'SD für Value Help BUPAP' define service ZSD_VALUE_HELP_BUPAP { expose zce_value_help_bupap; } |
Service Bindung
Sobald die Service Bindung angelegt ist, können wir die Custom Entity und die Implementierung der Suche mit der Preview-Funktion testen.
Die Filter- und Result-Felder müssen vorerst noch manuell ausgewählt werden, aber dann sollte bereits ein Ergebnis sichtbar sein.
Wenn alles korrekt implementiert wurde, sollten auch die Filter und die Sortierung funktionieren.
Step 5 – Verwendung der Custom Entity in einem CDS View
Jetzt verknüpfen wir die neue Custom Entity Value Help mit einer bestehenden SAP Fiori Elements Anwendung. Angenommen wir haben eine auf RAP basierende Anwendung zur Darstellung von Business Partner.
Folgende Annotation ist nun beim Feld mit der Partnernummer anzugeben.
1 2 3 4 5 6 |
... @Consumption.valueHelpDefinition: [{ entity: { name: 'ZCE_VALUE_HELP_BUPAP', element: 'partner' }, label: 'Partners, General' } ] key ZFOE_I_PARTNER.partner as PartnerID, .. |
Danach sollte bei der Anwendung für das Feld PartnerID folgende Suchhilfe zur Verfügung stehen.
Fazit
Es ist vielleicht keine perfekte Lösung, wie gesagt, ich warte auf eine Lösung im SAP Standard. Aber mit Hilfe der Custom Entitys kann man SE11 Suchhilfen einfach und rasch in Fiori Elements oder UI5 Smart Controls verwenden.