https://raw.githubusercontent.com/ajmaradiaga/feeds/main/scmt/topics/ABAP-Development-blog-posts.xmlSAP Community - ABAP Development2026-02-15T09:00:03.051941+00:00python-feedgenABAP Development blog posts in SAP Communityhttps://community.sap.com/t5/technology-blog-posts-by-sap/how-to-enable-bc-set-support-for-bc-app/ba-p/14313371How to enable BC Set support for BC app2026-01-23T11:06:48.347000+01:00patrick_winklerhttps://community.sap.com/t5/user/viewprofilepage/user-id/729521<H1 id="toc-hId-887480474" id="toc-hId-1659546876">Introduction</H1><P><SPAN>In order to use the "import from transport" function in the <A href="https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/creating-business-configuration-sets" target="_blank" rel="noopener noreferrer">BC Set editor</A>, the data must be recorded in the context of a transport object (TOBJ) and the business configuration maintenance object (SMBC) must maintain the corresponding transport object attribute.</SPAN></P><P><SPAN>This blog explains the necessary steps to enable existing SMBC objects for the "import from transport" functionality. Newly generated SMBC objects are automatically enabled.<BR /><BR /></SPAN>This blog is relevant for</P><UL><LI><a href="https://community.sap.com/t5/c-khhcw49343/SAP+S%25252F4HANA+Cloud+Public+Edition/pd-p/08e2a51b-1ce5-4367-8b33-4ae7e8b702e0" class="lia-product-mention" data-product="1199-1">SAP S/4HANA Cloud Public Edition</a></LI><LI><a href="https://community.sap.com/t5/c-khhcw49343/SAP+BTP+ABAP+environment/pd-p/73555000100800001164" class="lia-product-mention" data-product="11-1">SAP BTP ABAP environment</a></LI></UL><P>Further reading:</P><UL><LI><A href="https://community.sap.com/t5/tag/business%20configuration%20maintenance%20object/tg-p/board-id/technology-blog-sap" target="_blank">Related blog posts</A></LI><LI>Learn how you can use<SPAN> </SPAN><A href="https://learning.sap.com/products/business-technology-platform/development/abap?url_id=text-sapcommunity-prdteng-ABAP" target="_blank" rel="noopener noreferrer">ABAP technology</A><SPAN> </SPAN>to develop innovative applications and business solutions across SAP’s portfolio on<SPAN> </SPAN><A href="https://learning.sap.com/products/business-technology-platform/development/abap" target="_blank" rel="noopener noreferrer">SAP Learning Site</A>.</LI></UL><H2 id="toc-hId-1592116090">Case 1: Transport object is already used in the BC app</H2><P><SPAN>As of release 2302, when you use the </SPAN><A href="https://help.sap.com/docs/btp/sap-business-technology-platform/generating-business-configuration-maintenance-object-with-generate-abap-repository-objects-wizard" target="_self" rel="noopener noreferrer">ADT wizard</A><SPAN> to generate a business configuration maintenance object (SMBC), a transport object (TOBJ) is generated by default and used in the behavior implementation. In this case you only need to maintain the new "Transport Object" attribute of the SMBC object.</SPAN></P><P>You can do this manually in the ADT editor of the SMBC object or programmatically. First you need to find out the name of the transport object. In most cases the name is equal to the name of the SMBC object. You can open the behavior implementation class and check the first couple of rows to verify the name of the transport object ( depending on the release the object was created: CO_TRANSPORT_OBJECT or TDAT_NAME )</P><pre class="lia-code-sample language-abap"><code>CLASS LHC_COMPANYCODEALL DEFINITION FINAL INHERITING FROM CL_ABAP_BEHAVIOR_HANDLER.
PUBLIC SECTION.
CONSTANTS:
CO_ENTITY TYPE abp_entity_name VALUE `ZI_COMPANYCODE_S`,
CO_TRANSPORT_OBJECT TYPE mbc_cp_api=>indiv_transaction_obj_name VALUE `ZCOMPANYCODE`,
CO_AUTHORIZATION_ENTITY TYPE abp_entity_name VALUE `ZI_COMPANYCODE`.</code></pre><pre class="lia-code-sample language-abap"><code>CLASS LHC_RAP_TDAT_CTS DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS:
GET
RETURNING
VALUE(RESULT) TYPE REF TO IF_MBC_CP_RAP_TDAT_CTS.
ENDCLASS.
CLASS LHC_RAP_TDAT_CTS IMPLEMENTATION.
METHOD GET.
result = mbc_cp_api=>rap_tdat_cts( tdat_name = 'ZTAB6'</code></pre><P>You can maintain the attribute "Transport Object" in the "Service Configuration" section of the SMBC object in the ADT editor. Save and activate.</P><P>You can update this attribute also programmatically:</P><pre class="lia-code-sample language-abap"><code>CLASS zset_tobj DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zset_tobj IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA smbc_id TYPE TABLE OF if_mbc_cp_api_business_config=>ty_technical_id WITH EMPTY KEY.
SELECT ABAPObject FROM I_CustABAPObjDirectoryEntry
WHERE ABAPObjectType = 'SMBC' AND ABAPObject LIKE '<NAMESPACE>%'
INTO TABLE @smbc_id .
LOOP AT smbc_id ASSIGNING FIELD-SYMBOL(<smbc_id>).
out->write( |SMBC object: { <smbc_id> }| ).
TRY.
DATA(tobj) = mbc_cp_api=>business_configuration_api( <smbc_id> )->read( )-transport_object.
IF tobj IS NOT INITIAL.
out->write( |TOBJ already set: { tobj }| ).
ELSE.
mbc_cp_api=>business_configuration_api( <smbc_id> )->update_transport_object(
transport_object = <smbc_id> "if the table list of the transport object does not match the table list of the behavior definition an exception is raised
transport = '<Workbench Request>' ). "transport=space for local objects
out->write( |TOBJ set: { mbc_cp_api=>business_configuration_api( <smbc_id> )->read( )-transport_object }| ).
ENDIF.
CATCH cx_root INTO DATA(exc).
out->write( |Error: { exc->get_text( ) }| ).
ENDTRY.
ENDLOOP.
ENDMETHOD.
ENDCLASS.</code></pre><H2 id="toc-hId-1395602585">Use Case 2: The BC app does not use a transport object</H2><P>Delete the existing BC app and create it again using the ADT wizard.</P><P>If you cannot do that, you can also use the ADT wizard to generate a new BC app for the table(s) with different object names. Move the generated transport object to the package of the old BC app and maintain the transport object attribute of the old SMBC object.<BR />If necessary, adjust the generated TOBJ by changing the table piece list.<BR />Adjust the old behavior implementation class by by replacing the existing method implementation with the equivalent method implementation of the new behavior implementation class. Adjust the constants to match the old object names.<BR />You can now delete the newly generated objects.</P><H2 id="toc-hId-1199089080">Transport object names</H2><P>The last character of the technical name of a transport object is its type. In the SMBC and TOBJ ADT editor, the technical name of the transport object is used. Use the input help to select a transport object.<BR />In the API calls in the behavior implementation class, the type of a transport object is either a separate parameter or T (Individual Transaction Object) by default. That is, remove the last character for the name of the transport object.<BR />Example: <BR />In ADT, the name of the transport object is "ZTOBJ1 T" or "ZCOMPANYCODET". In the behavior implementation class, use "ZTOBJ1" or "ZCOMPANYCODE".</P><P> </P>2026-01-23T11:06:48.347000+01:00https://community.sap.com/t5/enterprise-architecture-blog-posts/creating-an-interactive-editable-alv-in-abap-with-header-item-crud/ba-p/14116499Creating an Interactive Editable ALV in ABAP with Header-Item CRUD Functionality2026-01-24T04:59:44.641000+01:00Naveennani8523https://community.sap.com/t5/user/viewprofilepage/user-id/1800750<pre class="lia-code-sample language-abap"><code></code></pre><P>In this blog post, we will explore a powerful ABAP implementation of an editable ALV using CL_GUI_ALV_GRID. This solution provides:</P><UL><LI>Interactive two-screen design (Header & Item)</LI><LI>Double-click to drill down from header to item</LI><LI>Row-based editing using LVC_ROWMARK</LI><LI>Field-level edit control via CELLTAB</LI><LI>Full CRUD operations (Create, Read, Update, Delete) for both header and item data</LI></UL><H2 id="toc-hId-1731461697"><span class="lia-unicode-emoji" title=":house:">🏠</span> Scenario</H2><P>We use two custom database tables:</P><UL><LI>Custom Table → Delivery Header Data (VBELN, ERNAM, ERDAT, VSTEL, VKORG)</LI><LI>Custom Table → Delivery Item Data (VBELN, POSNR, MATNR, WERKS)</LI></UL><P>The goal is to allow users to edit only selected rows, protect primary key fields, and manage entries interactively.</P><H3 id="toc-hId-1664030911">1. <STRONG>Table Declarations</STRONG></H3><P>TABLES?</P><UL><LI> Custom transparent table containing delivery header data.</LI><LI>Custom transparent table for delivery item data.</LI><LI>These tables are used to fetch and store ALV grid data.</LI></UL><H3 id="toc-hId-1467517406"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>2. Class Forward Declaration</STRONG></H3><P>CLASS DELIVERY DEFINITION DEFERRED.</P><UL><LI>Forward declares a class named DELIVERY used later to handle double-click events.</LI><LI>This is necessary to register event handlers before the class is fully implemented.</LI></UL><H3 id="toc-hId-1271003901"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>3. Type Declarations</STRONG></H3><P> TYPES: BEGIN OF T_ZDB_EDIT_ALV, VBELN TYPE ZDB_EDIT_ALV-VBELN, ERNAM TYPE ZDB_EDIT_ALV-ERNAM, ERDAT TYPE ZDB_EDIT_ALV-ERDAT, VSTEL TYPE ZDB_EDIT_ALV-VSTEL, VKORG TYPE ZDB_EDIT_ALV-VKORG, CELLTAB TYPE LVC_T_STYL, END OF T_ZDB_EDIT_ALV.</P><UL><LI>Defines a structure T_ZDB_EDIT_ALV to hold header data and editable styles.</LI><LI>CELLTAB: Stores editable style info for ALV cell-level control.</LI></UL><P>Similarly, for item data:</P><P>TYPES: BEGIN OF T_ZDB_EDIT_ALV1, VBELN TYPE ZDB_EDIT_ALV1-VBELN, POSNR TYPE ZDB_EDIT_ALV1-POSNR, MATNR TYPE ZDB_EDIT_ALV1-MATNR, WERKS TYPE ZDB_EDIT_ALV1-WERKS, CELLTAB TYPE LVC_T_STYL, END OF T_ZDB_EDIT_ALV1.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_0-1749191172558.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270514i3B62808E6E33196E/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_0-1749191172558.png" alt="Naveennani8523_0-1749191172558.png" /></span></P><H3 id="toc-hId-1074490396"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>4. Data Definitions</STRONG></H3><P>DATA: LT_LIKP TYPE TABLE OF T_ZDB_EDIT_ALV, LS_LIKP TYPE T_ZDB_EDIT_ALV, LT_LIPS TYPE TABLE OF T_ZDB_EDIT_ALV1, LS_LIPS TYPE T_ZDB_EDIT_ALV1,</P><UL><LI>Internal tables and work areas for header (LT_LIKP, LS_LIKP) and item (LT_LIPS, LS_LIPS) records.</LI></UL><P> LT_FCAT TYPE LVC_T_FCAT, LS_FCAT TYPE LVC_S_FCAT, LT_FCAT1 TYPE LVC_T_FCAT, LS_FCAT1 TYPE LVC_S_FCAT,</P><UL><LI>Field catalog tables for header (LT_FCAT) and item (LT_FCAT1) ALVs.</LI></UL><P> LS_LAYO TYPE LVC_S_LAYO, LS_LAYO1 TYPE LVC_S_LAYO,</P><UL><LI>Layout configurations for header and item grids.</LI></UL><P> O_CONTAINER1 TYPE REF TO CL_GUI_CUSTOM_CONTAINER, O_GRID1 TYPE REF TO CL_GUI_ALV_GRID, O_CONTAINER2 TYPE REF TO CL_GUI_CUSTOM_CONTAINER, O_GRID2 TYPE REF TO CL_GUI_ALV_GRID,</P><UL><LI>Containers and ALV grid objects for screen 200 (header) and screen 100 (item).</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_1-1749191172560.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270515iF61284AE07665BB2/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_1-1749191172560.png" alt="Naveennani8523_1-1749191172560.png" /></span></P><H2 id="toc-hId-748894172"><STRONG>5. Selection Screen Definition</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_2-1749191172561.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270513i2396566F1D61F909/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_2-1749191172561.png" alt="Naveennani8523_2-1749191172561.png" /></span> </LI><LI><STRONG>Purpose</STRONG>: Creates a selection screen block with delivery number as the input filter.</LI><LI><STRONG>S_VBELN</STRONG>: Allows users to input multiple values or ranges for VBELN.</LI><LI><STRONG>TEXT-000</STRONG>: Refers to a text element (defined in SE32 or SE38) for the frame title.</LI></UL><H2 id="toc-hId-552380667"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>6. Field Catalog for Item ALV</STRONG></H2><UL><LI>Uses VALUE #( ) constructor to populate the field catalog for the item-level ALV (LT_LIPS).</LI><LI>COL_POS: Column order in the ALV.</LI><LI>FIELDNAME: Field to display.</LI><LI>COLTEXT: Header text.</LI><LI>TABNAME: Reference table used for dynamic assignment (not required in OO ALV, but used for clarity here).</LI></UL><H2 id="toc-hId-355867162"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>7. Layout Configuration for Item ALV</STRONG></H2><UL><LI>GRID_TITLE: Title of the ALV.</LI><LI>SEL_MODE = 'A': Allows multiple row selection.</LI><LI>NO_TOOLBAR = 'X': Hides the standard ALV toolbar.</LI><LI>STYLEFNAME = 'CELLTAB': Tells ALV to use the CELLTAB column to control editable styles per cell.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_3-1749191172563.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270521i4DB91C2A1CF5C37B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_3-1749191172563.png" alt="Naveennani8523_3-1749191172563.png" /></span></P><H2 id="toc-hId-159353657"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>8. Start-of-Selection</STRONG></H2><P>START-OF-SELECTION. CALL SCREEN 200.</P><UL><LI><STRONG>Trigger point of the report</STRONG> after user input.</LI><LI>It navigates to screen <STRONG>200</STRONG>, which displays the <STRONG>header-level ALV</STRONG>.</LI></UL><H2 id="toc-hId--37159848"><STRONG>9. Event Handler Class Definition</STRONG></H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_4-1749191172564.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270519i43AFED4F7130D985/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_4-1749191172564.png" alt="Naveennani8523_4-1749191172564.png" /></span></P><UL><LI>Defines a <STRONG>local class</STRONG> DELIVERY with method GET_DATA.</LI><LI>The method is registered as an event handler for the <STRONG>double-click</STRONG> event of the ALV.</LI></UL><H2 id="toc-hId-113581004"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>10. Class Implementation</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_5-1749191172565.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270520i51CDC5398263A048/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_5-1749191172565.png" alt="Naveennani8523_5-1749191172565.png" /></span> </LI><LI><STRONG>GET_DATA</STRONG> is triggered when the user double-clicks on a row in header ALV.</LI><LI>It reads the delivery number (VBELN) of the clicked row.</LI><LI>Then fetches all matching item-level records from ZDB_EDIT_ALV1 into LT_LIPS.</LI><LI>Opens <STRONG>Screen 100</STRONG>, which shows the item ALV.</LI></UL><H2 id="toc-hId--82932501"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>11. Screen 100 (Item ALV) - OUTPUT Module</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_6-1749191172565.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270525iD5C9E93162F9FC9F/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_6-1749191172565.png" alt="Naveennani8523_6-1749191172565.png" /></span> </LI><LI>SET PF-STATUS 'ZITEMS': Sets the GUI status (button functions) for item screen.</LI><LI>PERFORM CREATE_OBJECT_LIPS: Initializes the ALV Grid for item records.</LI></UL><H2 id="toc-hId--279446006"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>12. Screen 100 - INPUT Module</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_7-1749191172566.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270526i16C6390E23BE8EA2/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_7-1749191172566.png" alt="Naveennani8523_7-1749191172566.png" /></span> </LI><LI>Handles user actions on screen 100:<UL><LI>BACK: Return to header ALV.</LI><LI>CREATE: Add a new item row.</LI><LI>EDIT: Enable selected row for editing.</LI><LI>UPDATE: Update modified item data.</LI><LI>DELETE: Remove selected rows.</LI><LI>SAVE: Insert/update item data into DB.</LI></UL></LI></UL><OL><LI>FORM CREATE_OBJECT_LIPS – Initializes ALV on Screen 100 (Item).</LI><LI>MODULE STATUS_0200 OUTPUT – Prepares header ALV on Screen 200.</LI><LI>MODULE USER_COMMAND_0200 INPUT – Handles toolbar actions for header ALV.</LI><LI>Then we’ll go deeper into the CRUD FORMs (CREATE/EDIT/UPDATE/DELETE/SAVE) for both header and item ALVs.</LI><LI>FORM CREATE_OBJECT_LIPS<STRONG> – Create ALV Grid for Items</STRONG></LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_8-1749191172568.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270527i734C2BC0C54B2623/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_8-1749191172568.png" alt="Naveennani8523_8-1749191172568.png" /></span></P><H3 id="toc-hId--769362518"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span></H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_9-1749191172569.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270531i4CB17536C154A57F/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_9-1749191172569.png" alt="Naveennani8523_9-1749191172569.png" /></span></P><H3 id="toc-hId--965876023">Explanation:</H3><UL><LI><STRONG>CLEAR O_CONTAINER2</STRONG>: Reset reference before ALV creation (safety check).</LI><LI><STRONG>CREATE OBJECT O_CONTAINER2</STRONG>: Creates a custom container placed on the screen (SCREEN 100) using element CONTAINER2.</LI><LI><STRONG>CREATE OBJECT O_GRID2</STRONG>: Binds an ALV Grid (CL_GUI_ALV_GRID) to the container.</LI><LI><STRONG>SET_TABLE_FOR_FIRST_DISPLAY</STRONG>:<UL><LI>IS_LAYOUT = LS_LAYO1: Applies previously configured layout for item ALV.</LI><LI>IT_OUTTAB = LT_LIPS: Data source for the ALV.</LI><LI>IT_FIELDCATALOG = LT_FCAT1: Column settings for the ALV.</LI></UL></LI></UL><H2 id="toc-hId--868986521"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>13. </STRONG>MODULE STATUS_0200 OUTPUT<STRONG> – Setup Header Screen (Screen 200)</STRONG></H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_10-1749191172570.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270532i83CF7510823FDB5B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_10-1749191172570.png" alt="Naveennani8523_10-1749191172570.png" /></span></P><H3 id="toc-hId--1358903033">Explanation:</H3><UL><LI>SET PF-STATUS 'ZHEADER': Sets GUI status for header toolbar (buttons: CREATE, EDIT, SAVE, etc.).</LI><LI>The SELECT pulls header records from ZDB_EDIT_ALV based on delivery numbers entered on the selection screen.</LI></UL><H3 id="toc-hId--1555416538">ALV Grid Initialization:</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_11-1749191172571.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270533i265DBA4C13AC9AB3/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_11-1749191172571.png" alt="Naveennani8523_11-1749191172571.png" /></span></P><P>Creates the custom container and grid for header-level display.</P><H3 id="toc-hId--1751930043">Field Catalog (LT_FCAT):</H3><P>Each field is appended individually to LT_FCAT with attributes:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_12-1749191172572.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270538iE759BD09E2E00333/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_12-1749191172572.png" alt="Naveennani8523_12-1749191172572.png" /></span></P><H3 id="toc-hId--1948443548"> Layout for Header ALV:</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_13-1749191172572.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270537iD5CA4EA8002C1EF9/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_13-1749191172572.png" alt="Naveennani8523_13-1749191172572.png" /></span></P><P> Final ALV Setup:</P><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_14-1749191172573.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270539iB7074AD502A45837/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_14-1749191172573.png" alt="Naveennani8523_14-1749191172573.png" /></span> </LI><LI>Initializes header ALV with all settings and data.</LI></UL><H3 id="toc-hId--1976773362">Event Handler Registration:</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_15-1749191172574.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270543iE0337B8F0B95246F/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_15-1749191172574.png" alt="Naveennani8523_15-1749191172574.png" /></span></P><P> Double-click on any row in header ALV triggers GET_DATA, which fetches corresponding items.</P><H2 id="toc-hId--1879883860"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>14. </STRONG>MODULE USER_COMMAND_0200 INPUT<STRONG> – Header Screen Toolbar Actions</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_16-1749191172575.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270544i2F64A0BDCBC1BBD4/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_16-1749191172575.png" alt="Naveennani8523_16-1749191172575.png" /></span> </LI><LI>Executes the relevant FORM based on user action on toolbar buttons:<UL><LI>CREATE: Adds a new editable row.</LI><LI>EDIT: Enables selected row for editing.</LI><LI>SAVE: Inserts or updates data in DB.</LI><LI>DELETE: Removes selected rows from ALV and DB.</LI><LI>UPDATE: Commits modified data to DB.</LI></UL></LI></UL><H2 id="toc-hId--2076397365"><STRONG>15. </STRONG>FORM CHANGE_MODE<STRONG> – Enable Edit Mode for Selected Header Row</STRONG></H2><UL><LI><STRONG>Purpose</STRONG>: Only the selected row becomes editable. All others stay read-only.</LI><LI>LVC_T_ROID, LVC_S_STYL: Types for editable styles.</LI><LI>CELLTAB is used for cell-level control.</LI><LI>Gets the row(s) selected in the <STRONG>header ALV</STRONG> using LVC_ROWMARK.</LI></UL><P> Loop over each header entry to determine which row to enable. </P><UL><LI>Compares the current loop index with selected rows.</LI><LI>If it’s selected, enable its editable fields.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_17-1749191172578.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270545i8D5AB73879134397/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_17-1749191172578.png" alt="Naveennani8523_17-1749191172578.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_18-1749191172580.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270551iBF3BED421B2410A7/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_18-1749191172580.png" alt="Naveennani8523_18-1749191172580.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_19-1749191172582.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270550iFD30EDFC3278D02D/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_19-1749191172582.png" alt="Naveennani8523_19-1749191172582.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_20-1749191172583.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270549i2A6012EFF7A85B47/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_20-1749191172583.png" alt="Naveennani8523_20-1749191172583.png" /></span></P><H3 id="toc-hId-1728653419"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> If Selected Row → Enable ditable Fields</H3><P> IF SY-SUBRC = 0. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VBELN'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.</P><UL><LI>VBELN is a primary key → disabled.</LI><LI>Similarly disables ERNAM.</LI></UL><P> LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'ERDAT'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.</P><UL><LI>Enables only non-primary key fields for editing: ERDAT, VSTEL, VKORG.</LI></UL><H3 id="toc-hId-1532139914"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Assign Cell Styles to Entry</H3><P> CLEAR: LS_LIKP-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIKP-CELLTAB. MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW.</P><UL><LI>Applies the style to the current line.</LI></UL><H3 id="toc-hId-1335626409"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Else – Row not selected → Make it fully non-editable</H3><P> ELSE. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED. ... INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. ... MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB.</P><H3 id="toc-hId-1139112904"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Toggle Grid Ready for Input</H3><P> IF O_GRID1->IS_READY_FOR_INPUT( ) EQ 0. CALL METHOD O_GRID1->SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. ELSE. CALL METHOD O_GRID1->SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. ENDIF.</P><UL><LI>Activates input mode if not already.</LI></UL><P> O_GRID1->REFRESH_TABLE_DISPLAY( ).ENDFORM.</P><UL><LI>Refreshes the ALV to reflect the updated editable state.</LI><LI> </LI></UL><H2 id="toc-hId-1236002406"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>16. </STRONG>FORM CREATE_HEADER_DATA<STRONG> – Add New Editable Header Row</STRONG></H2><P>FORM CREATE_HEADER_DATA . DATA: LS_NEW TYPE T_ZDB_EDIT_ALV, LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY, LS_STYLEROW TYPE LVC_S_STYL.</P><UL><LI>Prepares a new structure and editable field style list.</LI></UL><H3 id="toc-hId-746085894"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Set Editable Fields</H3><P> LS_STYLEROW-FIELDNAME = 'VBELN'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW.</P><UL><LI>All fields are enabled since it’s a <STRONG>new row</STRONG>. Even primary keys like VBELN, ERNAM.</LI><LI>Repeats for: ERNAM, ERDAT, VSTEL, VKORG.</LI></UL><H3 id="toc-hId-549572389"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Assign Styles and Add New Entry</H3><P> LS_NEW-CELLTAB = LT_STYLEROW. APPEND LS_NEW TO LT_LIKP.</P><UL><LI>Assigns the editable CELLTAB and appends the new row to the internal table.</LI></UL><P> CALL METHOD O_GRID1->SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY.ENDFORM.</P><UL><LI>Turns on editable mode and refreshes ALV.</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_21-1749191172584.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270556i7AB39BA0215081E0/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_21-1749191172584.png" alt="Naveennani8523_21-1749191172584.png" /></span></LI></UL><H2 id="toc-hId-814645582"><STRONG>17. </STRONG>FORM DELETE_HEADER_DATA<STRONG> – Delete Selected Header Rows</STRONG></H2><P>FORM DELETE_HEADER_DATA . DATA: LT_ROWS TYPE LVC_T_ROW, LS_ROW TYPE LVC_S_ROW, LV_IDX TYPE SY-TABIX.</P><UL><LI><STRONG>LT_ROWS</STRONG>: Holds the list of selected row indexes.</LI><LI><STRONG>LS_ROW</STRONG>: Work area for current row index.</LI><LI><STRONG>LV_IDX</STRONG>: Integer used to track which row index is being processed.</LI></UL><H3 id="toc-hId-324729070"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Get Selected Rows</H3><P> CALL METHOD O_GRID1->GET_SELECTED_ROWS IMPORTING ET_INDEX_ROWS = LT_ROWS.</P><UL><LI>Fetches the selected row indexes in the header ALV grid.</LI></UL><H3 id="toc-hId-128215565"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop and Delete from DB & Internal Table</H3><P> LOOP AT LT_ROWS INTO LS_ROW. LV_IDX = LS_ROW-INDEX. READ TABLE LT_LIKP INDEX LV_IDX INTO LS_LIKP. IF SY-SUBRC = 0. DELETE FROM ZDB_EDIT_ALV WHERE VBELN = LS_LIKP-VBELN. DELETE LT_LIKP INDEX LV_IDX. ENDIF. ENDLOOP.</P><UL><LI>For each selected row:<UL><LI>Reads that entry from LT_LIKP.</LI><LI>Deletes corresponding record from DB table ZDB_EDIT_ALV.</LI><LI>Deletes it from internal table LT_LIKP.</LI></UL></LI></UL><H3 id="toc-hId--68297940"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Refresh ALV & Commit</H3><P> CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY. COMMIT WORK. MESSAGE 'Selected header(s) deleted' TYPE 'S'.ENDFORM.</P><UL><LI>Refreshes the ALV display.</LI><LI>Saves DB changes using COMMIT WORK.</LI><LI>Displays success message.</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_22-1749191172585.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270555i52DD83DEFB59E248/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_22-1749191172585.png" alt="Naveennani8523_22-1749191172585.png" /></span></LI></UL><H2 id="toc-hId-28591562"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>18. </STRONG>FORM SAVE_HEADER_DATA<STRONG> – Insert or Update Header Records</STRONG></H2><P>FORM SAVE_HEADER_DATA .</P><H3 id="toc-hId--461324950"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Flat Structure Definition</H3><P>TYPES: BEGIN OF TY_ZDB_EDIT_ALV_FLAT, VBELN TYPE ZDB_EDIT_ALV-VBELN, ERNAM TYPE ZDB_EDIT_ALV-ERNAM, ERDAT TYPE ZDB_EDIT_ALV-ERDAT, VSTEL TYPE ZDB_EDIT_ALV-VSTEL, VKORG TYPE ZDB_EDIT_ALV-VKORG, END OF TY_ZDB_EDIT_ALV_FLAT. DATA: LS_DB_ALV_FLAT TYPE TY_ZDB_EDIT_ALV_FLAT.</P><UL><LI>This structure <STRONG>excludes CELLTAB</STRONG> and is used to write data into the DB.</LI><LI> </LI></UL><H3 id="toc-hId--657838455"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Ensure User Changes Are Captured</H3><P> CALL METHOD O_GRID1->CHECK_CHANGED_DATA.</P><UL><LI>Updates the internal table (LT_LIKP) with user input from the ALV grid.</LI></UL><H3 id="toc-hId--854351960"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop Through Header Table and Save to DB</H3><P> LOOP AT LT_LIKP INTO LS_LIKP. LS_DB_ALV_FLAT-VBELN = LS_LIKP-VBELN. LS_DB_ALV_FLAT-ERNAM = LS_LIKP-ERNAM. LS_DB_ALV_FLAT-ERDAT = LS_LIKP-ERDAT. LS_DB_ALV_FLAT-VSTEL = LS_LIKP-VSTEL. LS_DB_ALV_FLAT-VKORG = LS_LIKP-VKORG.</P><UL><LI>Copies the values to a flat version to avoid CELLTAB structure issues.</LI></UL><H3 id="toc-hId--1050865465"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Insert or Update Logic</H3><P> SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(LV_VBELN) FROM ZDB_EDIT_ALV WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM. IF SY-SUBRC = 0. UPDATE ZDB_EDIT_ALV SET ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT, VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL, VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM. ELSE. INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT. ENDIF. ENDLOOP.</P><UL><LI>If record exists (same VBELN & ERNAM) → UPDATE.</LI><LI>Else → INSERT as new record.</LI></UL><P> COMMIT WORK. MESSAGE 'Header data saved successfully' TYPE 'S'.ENDFORM.</P><UL><LI>Final commit and success message.</LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_23-1749191172586.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270557iFF0F6628B23C836F/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_23-1749191172586.png" alt="Naveennani8523_23-1749191172586.png" /></span></LI><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_24-1749191172587.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270564i48AA7AE99A09641A/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_24-1749191172587.png" alt="Naveennani8523_24-1749191172587.png" /></span></LI></UL><H2 id="toc-hId--953975963"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>19. </STRONG>FORM UPDATE_HEADER_DATA<STRONG> – Update Header Records</STRONG></H2><P>FORM UPDATE_HEADER_DATA . CALL METHOD O_GRID1->CHECK_CHANGED_DATA.</P><UL><LI>Reads current ALV data into LT_LIKP.</LI></UL><H3 id="toc-hId--1275708784"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop and Upsert to DB</H3><P> LOOP AT LT_LIKP INTO LS_LIKP. LS_DB_ALV_FLAT-VBELN = LS_LIKP-VBELN. LS_DB_ALV_FLAT-ERNAM = LS_LIKP-ERNAM. LS_DB_ALV_FLAT-ERDAT = LS_LIKP-ERDAT. LS_DB_ALV_FLAT-VSTEL = LS_LIKP-VSTEL. LS_DB_ALV_FLAT-VKORG = LS_LIKP-VKORG.</P><UL><LI>Maps data into a flat structure.</LI></UL><P> SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(LV_VBELN) FROM ZDB_EDIT_ALV WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM. IF SY-SUBRC = 0. UPDATE ZDB_EDIT_ALV SET ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT, VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL, VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM. ELSE. INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT. ENDIF. ENDLOOP.</P><UL><LI>Same insert/update logic as SAVE</LI></UL><P> COMMIT WORK. MESSAGE 'Header data Updated successfully' TYPE 'S'.ENDFORM.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_25-1749191172589.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270558iC67E9D92035DC1A8/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_25-1749191172589.png" alt="Naveennani8523_25-1749191172589.png" /></span></P><P> </P><P><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> That completes the full documentation of <STRONG>header-level editable ALV with CRUD</STRONG>.</P><P>Next, I’ll begin the <STRONG>item-level ALV explanation</STRONG> starting with:</P><OL><LI>FORM CHANGE_ITEMS_MODE</LI><LI>FORM CREATE_ITEMS_DATA</LI><LI>FORM DELETE_ITEMS_DATA</LI><LI>FORM SAVE_ITEMS_DATA</LI><LI>FORM UPDATE_ITEMS_DATA</LI></OL><H2 id="toc-hId--1178819282"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>20. </STRONG>FORM CHANGE_ITEMS_MODE<STRONG> – Make Only Selected Item Row Editable</STRONG></H2><P>FORM CHANGE_ITEMS_MODE . DATA: LT_INDEX_ROWS TYPE LVC_T_ROW, LT_ROW_NO TYPE LVC_T_ROID, LS_ROW_NO TYPE LVC_S_ROID, LS_STYLEROW TYPE LVC_S_STYL, LT_STYLEROW TYPE TABLE OF LVC_S_STYL.</P><UL><LI>Similar to header edit logic.</LI><LI>Used to control which <STRONG>single row</STRONG> in the item ALV becomes editable.</LI></UL><P> CALL METHOD O_GRID2->GET_SELECTED_ROWS IMPORTING ET_ROW_NO = LT_ROW_NO.</P><UL><LI>Retrieves the selected item rows using LVC_ROWMARK.</LI></UL><H3 id="toc-hId--1668735794"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop Over All Rows and Toggle Editable Mode</H3><P> IF NOT LT_ROW_NO IS INITIAL. LOOP AT LT_LIPS INTO LS_LIPS. READ TABLE LT_ROW_NO INTO LS_ROW_NO WITH KEY ROW_ID = SY-TABIX.</P><UL><LI>For each item row in LT_LIPS, check if it’s selected.</LI></UL><H3 id="toc-hId--1865249299"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> If Selected: Enable Editable Fields</H3><P> IF SY-SUBRC = 0. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED. LS_STYLEROW-FIELDNAME = 'VBELN'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'POSNR'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED. LS_STYLEROW-FIELDNAME = 'MATNR'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. LS_STYLEROW-FIELDNAME = 'WERKS'. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.</P><UL><LI>VBELN and POSNR are primary keys → disabled.</LI><LI>Only MATNR, WERKS are editable.</LI></UL><P> CLEAR: LS_LIPS-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB. MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW.</P><UL><LI>Applies the cell-style configuration to the current row.</LI></UL><H3 id="toc-hId--2061762804"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Else: Disable All Fields for Non-Selected Rows</H3><P> ELSE. LOOP AT FIELDS: 'VBELN', 'POSNR', 'MATNR', 'WERKS'. LS_STYLEROW-FIELDNAME = FIELD. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED. INSERT LS_STYLEROW INTO TABLE LT_STYLEROW. ENDLOOP. CLEAR: LS_LIPS-CELLTAB. INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB. MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB. CLEAR: LT_STYLEROW.</P><H3 id="toc-hId-2036690987"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Toggle Edit Mode and Refresh ALV</H3><P> IF O_GRID2->IS_READY_FOR_INPUT( ) EQ 0. CALL METHOD O_GRID2->SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. ELSE. CALL METHOD O_GRID2->SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 0. ENDIF. O_GRID2->REFRESH_TABLE_DISPLAY( ).ENDFORM.</P><H2 id="toc-hId-2133580489"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>21. </STRONG>FORM CREATE_ITEMS_DATA<STRONG> – Add New Editable Row in Item ALV</STRONG></H2><P>FORM CREATE_ITEMS_DATA . DATA: LS_NEW TYPE T_ZDB_EDIT_ALV1, LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY, LS_STYLEROW TYPE LVC_S_STYL. CLEAR: LS_NEW, LT_STYLEROW.</P><UL><LI>Creates a blank work area and editable style table.</LI></UL><H3 id="toc-hId-1643663977"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Enable All Fields (for Create)</H3><P> LS_STYLEROW-FIELDNAME = 'VBELN'. LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED. APPEND LS_STYLEROW TO LT_STYLEROW. ... (Repeat for POSNR, MATNR, WERKS)</P><UL><LI>All fields are enabled so user can create new record from scratch.</LI></UL><P> LS_NEW-CELLTAB = LT_STYLEROW. APPEND LS_NEW TO LT_LIPS. CALL METHOD O_GRID2->SET_READY_FOR_INPUT EXPORTING I_READY_FOR_INPUT = 1. CALL METHOD O_GRID2->REFRESH_TABLE_DISPLAY.ENDFORM.</P><UL><LI>Appends the new row to ALV and switches to input mode.</LI></UL><H2 id="toc-hId-1740553479"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>22. </STRONG>FORM DELETE_ITEMS_DATA<STRONG> – Delete Selected Item Rows</STRONG></H2><P>FORM DELETE_ITEMS_DATA . DATA: LT_ROWS TYPE LVC_T_ROW, LS_ROW TYPE LVC_S_ROW, LV_IDX TYPE SY-TABIX. CALL METHOD O_GRID2->GET_SELECTED_ROWS IMPORTING ET_INDEX_ROWS = LT_ROWS.</P><UL><LI>Gets the selected item row indexes from ALV.</LI></UL><P> LOOP AT LT_ROWS INTO LS_ROW. LV_IDX = LS_ROW-INDEX. READ TABLE LT_LIPS INDEX LV_IDX INTO LS_LIPS. IF SY-SUBRC = 0. DELETE FROM ZDB_EDIT_ALV1 WHERE VBELN = LS_LIPS-VBELN. DELETE LT_LIPS INDEX LV_IDX. ENDIF. ENDLOOP. CALL METHOD O_GRID2->REFRESH_TABLE_DISPLAY. COMMIT WORK. MESSAGE 'Selected header(s) deleted' TYPE 'S'.ENDFORM.</P><UL><LI>Deletes item records from both DB and internal table.</LI></UL><H2 id="toc-hId-1544039974"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>23. </STRONG>FORM SAVE_ITEMS_DATA<STRONG> – Insert or Update Item Rows</STRONG></H2><P>FORM SAVE_ITEMS_DATA . DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT, LS_DB_FULL TYPE ZDB_EDIT_ALV1, LV_VBELN TYPE ZDB_EDIT_ALV1-VBELN. CALL METHOD O_GRID2->CHECK_CHANGED_DATA.</P><UL><LI>Converts ALV changes to internal table.</LI><LI>Flat structure is used to exclude CELLTAB.</LI></UL><H3 id="toc-hId-1222307153"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> Loop Through Item Table</H3><P> LOOP AT LT_LIPS INTO LS_LIPS. LS_DB_ALV1-VBELN = LS_LIPS-VBELN. LS_DB_ALV1-POSNR = LS_LIPS-POSNR. LS_DB_ALV1-MATNR = LS_LIPS-MATNR. LS_DB_ALV1-WERKS = LS_LIPS-WERKS.</P><UL><LI>Transfer values from ALV row to flat structure.</LI></UL><H3 id="toc-hId-1025793648"><span class="lia-unicode-emoji" title=":small_blue_diamond:">🔹</span> DB Insert/Update Logic</H3><P> SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_VBELN FROM ZDB_EDIT_ALV1 WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR. IF SY-SUBRC = 0. UPDATE ZDB_EDIT_ALV1 SET MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR, WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR. ELSE. CLEAR LS_DB_FULL. MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL. INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL. ENDIF. ENDLOOP. COMMIT WORK. MESSAGE 'Item data saved successfully' TYPE 'S'.ENDFORM.</P><H2 id="toc-hId-1122683150"><span class="lia-unicode-emoji" title=":large_blue_diamond:">🔷</span> <STRONG>24. </STRONG>FORM UPDATE_ITEMS_DATA<STRONG> – Update Existing Item Records</STRONG></H2><P>FORM UPDATE_ITEMS_DATA . DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT, LS_DB_FULL TYPE ZDB_EDIT_ALV1, LV_VBELN TYPE ZDB_EDIT_ALV1-VBELN. CALL METHOD O_GRID2->CHECK_CHANGED_DATA.</P><UL><LI>Same structure and update logic as SAVE.</LI></UL><P> LOOP AT LT_LIPS INTO LS_LIPS. LS_DB_ALV1-VBELN = LS_LIPS-VBELN. LS_DB_ALV1-POSNR = LS_LIPS-POSNR. LS_DB_ALV1-MATNR = LS_LIPS-MATNR. LS_DB_ALV1-WERKS = LS_LIPS-WERKS. SELECT SINGLE VBELN INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(S_VBELN) FROM ZDB_EDIT_ALV1 WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR. IF SY-SUBRC = 0. UPDATE ZDB_EDIT_ALV1 SET MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR, WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR. ELSE. CLEAR LS_DB_FULL. MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL. INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL. ENDIF. ENDLOOP. COMMIT WORK. MESSAGE 'Item data Updated successfully' TYPE 'S'.ENDFORM.<STRONG>Output:</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_26-1749191172589.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270560iBEE936E82F368032/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_26-1749191172589.png" alt="Naveennani8523_26-1749191172589.png" /></span></P><P> Header Output</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_27-1749191172591.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270566i3CE4A6D89D67F78B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_27-1749191172591.png" alt="Naveennani8523_27-1749191172591.png" /></span></P><P> When I was click on edit button</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_28-1749191172595.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270567i057B849479B6AC8F/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_28-1749191172595.png" alt="Naveennani8523_28-1749191172595.png" /></span></P><P> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_29-1749191172596.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270565iDC47F60D1A00314B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_29-1749191172596.png" alt="Naveennani8523_29-1749191172596.png" /></span></P><P>When I was click on create button</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_30-1749191172598.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270571iEE61E24AE577EB58/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_30-1749191172598.png" alt="Naveennani8523_30-1749191172598.png" /></span></P><P>When I was create a new row delete button</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_31-1749191172599.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270572iEAE815660983589B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_31-1749191172599.png" alt="Naveennani8523_31-1749191172599.png" /></span></P><P>When I was click on create buttom multiple append rows also created in both header and item also</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_32-1749191172600.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270573iFA3C2CDDC454A5D3/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_32-1749191172600.png" alt="Naveennani8523_32-1749191172600.png" /></span></P><P>If I was save on empty row Its shows as</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_33-1749191172601.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270579iE50DABA8FE3E4BA6/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_33-1749191172601.png" alt="Naveennani8523_33-1749191172601.png" /></span></P><P>If was double click on empty on no items was displayed and Header empty row it will not created on items details</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_34-1749191172601.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270578i5D35C2D7AA981E94/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_34-1749191172601.png" alt="Naveennani8523_34-1749191172601.png" /></span></P><P> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_35-1749191172602.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270580i95316A0929BE635C/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_35-1749191172602.png" alt="Naveennani8523_35-1749191172602.png" /></span></P><P> </P><P>Same actions performs in CURD operations in item level also:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_36-1749191172603.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/270583i87EFC691220BBDC0/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_36-1749191172603.png" alt="Naveennani8523_36-1749191172603.png" /></span></P><P> </P><P><SPAN><STRONG>Program :</STRONG></SPAN></P><pre class="lia-code-sample language-abap"><code>REPORT ZEDITABLE_ALV_INT.
************************************************************************
* Program Name :
* Description : Editable ALV using CL_GUI_ALV_GRID with row-based edit
* control using LVC_ROWMARK. Only selected row becomes
* editable, primary keys remain non-editable and to perfrom a crud operations.
* Created by : <NRAJU>
*************************************************************************
*---------------------------------------------------------------------*
* Table Declarations
*---------------------------------------------------------------------*
TABLES:ZDB_EDIT_ALV,ZDB_EDIT_ALV1.
CLASS DELIVERY DEFINITION DEFERRED.
*---------------------------------------------------------------------*
* Type Declarations
*---------------------------------------------------------------------*
TYPES: BEGIN OF T_ZDB_EDIT_ALV,
VBELN TYPE ZDB_EDIT_ALV-VBELN, "Delivery Number
ERNAM TYPE ZDB_EDIT_ALV-ERNAM, "Name of Person who Created the Object
ERDAT TYPE ZDB_EDIT_ALV-ERDAT, "Date on Which Record Was Created
VSTEL TYPE ZDB_EDIT_ALV-VSTEL, "Shipping Point/Receiving Point
VKORG TYPE ZDB_EDIT_ALV-VKORG, "Sales Organization
CELLTAB TYPE LVC_T_STYL, "Editable style table
END OF T_ZDB_EDIT_ALV.
TYPES: BEGIN OF T_ZDB_EDIT_ALV1,
VBELN TYPE ZDB_EDIT_ALV1-VBELN, "Delivery Number
POSNR TYPE ZDB_EDIT_ALV1-POSNR, "Sales Document Item
ERNAM TYPE ZDB_EDIT_ALV1-ERNAM,
MATNR TYPE ZDB_EDIT_ALV1-MATNR, "Material Number
WERKS TYPE ZDB_EDIT_ALV1-WERKS, "Plant
CELLTAB TYPE LVC_T_STYL, "Editable style table
END OF T_ZDB_EDIT_ALV1.
DATA:LT_LIKP TYPE TABLE OF T_ZDB_EDIT_ALV, "Internal table for header
LS_LIKP TYPE T_ZDB_EDIT_ALV, "workarea for header
LT_LIPS TYPE TABLE OF T_ZDB_EDIT_ALV1, "Internal table for Item
LS_LIPS TYPE T_ZDB_EDIT_ALV1, "Workarea for item
LT_FCAT TYPE LVC_T_FCAT, "Filedcat
LS_FCAT TYPE LVC_S_FCAT,
LT_FCAT1 TYPE LVC_T_FCAT, "filedcatlog
LS_FCAT1 TYPE LVC_S_FCAT,
LS_LAYO TYPE LVC_S_LAYO, "Layout
LS_LAYO1 TYPE LVC_S_LAYO,
O_CONTAINER1 TYPE REF TO CL_GUI_CUSTOM_CONTAINER, "Container for Header
O_GRID1 TYPE REF TO CL_GUI_ALV_GRID, "Grid for Header
O_CONTAINER2 TYPE REF TO CL_GUI_CUSTOM_CONTAINER, "Container for item
O_GRID2 TYPE REF TO CL_GUI_ALV_GRID. "Grid for It
*---------------------------------------------------------------------*
* Selection Screen
*---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK B1 WITH FRAME TITLE TEXT-000.
SELECT-OPTIONS:S_VBELN FOR ZDB_EDIT_ALV-VBELN.
SELECTION-SCREEN END OF BLOCK B1.
*************fieldcatalog creation creation for item
LT_FCAT1 = VALUE #(
( COL_POS = 1 FIELDNAME = 'VBELN' COLTEXT = 'Delivery Number' )
( COL_POS = 2 FIELDNAME = 'POSNR' COLTEXT = 'Item Number' )
( COL_POS = 3 FIELDNAME = 'ERNAM' COLTEXT = 'NAME' )
( COL_POS = 4 FIELDNAME = 'MATNR' COLTEXT = 'Material Number' )
( COL_POS = 5 FIELDNAME = 'WERKS' COLTEXT = 'Plant' )
).
*************Layout creation for item
LS_LAYO1-GRID_TITLE = 'Custom Table for Items'.
LS_LAYO1-SEL_MODE = 'A'.
LS_LAYO1-NO_TOOLBAR = 'X'.
LS_LAYO1-STYLEFNAME = 'CELLTAB'.
"*************fieldcatalog creation creation
LS_FCAT-ROW_POS = 1.
LS_FCAT-COL_POS = 1.
LS_FCAT-FIELDNAME = 'VBELN'.
LS_FCAT-COLTEXT = 'Delivery Number'.
LS_FCAT-OUTPUTLEN = 20.
APPEND LS_FCAT TO LT_FCAT.
CLEAR LS_FCAT.
LS_FCAT-ROW_POS = 1.
LS_FCAT-COL_POS = 1.
LS_FCAT-FIELDNAME = 'ERNAM'.
LS_FCAT-COLTEXT = 'Name'.
LS_FCAT-OUTPUTLEN = 20.
APPEND LS_FCAT TO LT_FCAT.
CLEAR LS_FCAT.
LS_FCAT-ROW_POS = 1.
LS_FCAT-COL_POS = 1.
LS_FCAT-FIELDNAME = 'ERDAT'.
LS_FCAT-COLTEXT = 'Date'.
LS_FCAT-OUTPUTLEN = 20.
APPEND LS_FCAT TO LT_FCAT.
CLEAR LS_FCAT.
LS_FCAT-ROW_POS = 1.
LS_FCAT-COL_POS = 1.
LS_FCAT-FIELDNAME = 'VSTEL'.
LS_FCAT-COLTEXT = 'SALES'.
LS_FCAT-OUTPUTLEN = 20.
APPEND LS_FCAT TO LT_FCAT.
CLEAR LS_FCAT.
LS_FCAT-ROW_POS = 1.
LS_FCAT-COL_POS = 1.
LS_FCAT-FIELDNAME = 'VKORG'.
LS_FCAT-COLTEXT = 'Delivery Number'.
LS_FCAT-OUTPUTLEN = 20.
APPEND LS_FCAT TO LT_FCAT.
CLEAR LS_FCAT.
***********layout of fieldcat
LS_LAYO-GRID_TITLE = 'Custom Table for Header'.
LS_LAYO-SEL_MODE = 'A'.
LS_LAYO-NO_TOOLBAR = 'X'.
LS_LAYO-STYLEFNAME = 'CELLTAB'.
START-OF-SELECTION. "start-of-selection
CALL SCREEN 200. "Screen for Header
CLASS Delivery DEFINITION.
PUBLIC SECTION.
METHODS: GET_DATA FOR EVENT DOUBLE_CLICK OF CL_GUI_ALV_GRID
IMPORTING E_ROW.
ENDCLASS.
*&---------------------------------------------------------------------*
*& Class (Implementation) Delivery
*&---------------------------------------------------------------------*
* Text
*----------------------------------------------------------------------*
CLASS DELIVERY IMPLEMENTATION.
METHOD: GET_DATA.
READ TABLE LT_LIKP INTO LS_LIKP INDEX E_ROW-INDEX.
SELECT VBELN
POSNR
ERNAM
MATNR
WERKS
FROM ZDB_EDIT_ALV1
INTO CORRESPONDING FIELDS OF TABLE LT_LIPS
WHERE VBELN = LS_LIKP-VBELN and ernam = ls_likp-ernam.
** Check if items exist
* IF lt_lips IS INITIAL.
* MESSAGE 'No items exist for this header.' TYPE 'I'.
* RETURN.
* ENDIF.
CALL SCREEN 100.
* " Refresh ALV to reflect changes
* CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY.
ENDMETHOD.
ENDCLASS. "Delivery
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
SET PF-STATUS 'ZITEMS'. "Creating buttons for items
PERFORM CREATE_OBJECT_LIPS. "perform for create item
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
CASE SY-UCOMM.
WHEN 'BACK'.
LEAVE TO SCREEN 200.
WHEN 'CREATE'. "Createing new record for items
PERFORM CREATE_ITEMS_DATA.
WHEN 'EDIT'. "Editable alv for items
PERFORM CHANGE_ITEMS_MODE.
WHEN 'UPDATE'. "Updateing the records for items
PERFORM UPDATE_ITEMS_DATA.
WHEN 'DELETE'. "Deleting the records for item tables
PERFORM DELETE_ITEMS_DATA.
WHEN 'SAVE'. "Saveing the recording from db table in item records
PERFORM SAVE_ITEMS_DATA.
ENDCASE.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Form CREATE_OBJECT_LIPS
FORM CREATE_OBJECT_LIPS .
CLEAR O_CONTAINER2.
IF O_CONTAINER2 IS INITIAL AND O_GRID2 IS INITIAL.
CREATE OBJECT O_CONTAINER2
EXPORTING
CONTAINER_NAME = 'CONTAINER2'
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5
OTHERS = 6
.
CREATE OBJECT O_GRID2
EXPORTING
I_PARENT = O_CONTAINER2
EXCEPTIONS
ERROR_CNTL_CREATE = 1
ERROR_CNTL_INIT = 2
ERROR_CNTL_LINK = 3
ERROR_DP_CREATE = 4
OTHERS = 5
.
ENDIF.
CALL METHOD O_GRID2->SET_TABLE_FOR_FIRST_DISPLAY
EXPORTING
IS_LAYOUT = LS_LAYO1
CHANGING
IT_OUTTAB = LT_LIPS
IT_FIELDCATALOG = LT_FCAT1
EXCEPTIONS
INVALID_PARAMETER_COMBINATION = 1
PROGRAM_ERROR = 2
TOO_MANY_LINES = 3
OTHERS = 4
.
call method O_GRID2->REFRESH_TABLE_DISPLAY( ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Module STATUS_0200 OUTPUT
*&---------------------------------------------------------------------*
MODULE STATUS_0200 OUTPUT.
SET PF-STATUS 'ZHEADER'.
" Only load header data from DB once
IF lt_likp IS INITIAL.
SELECT vbeln
ernam
erdat
vstel
vkorg
FROM zdb_edit_alv
INTO CORRESPONDING FIELDS OF TABLE lt_likp
WHERE vbeln IN s_vbeln.
ENDIF.
" Only create container and grid once
IF o_container1 IS INITIAL AND o_grid1 IS INITIAL.
" Create custom container
CREATE OBJECT o_container1
EXPORTING
container_name = 'CONTAINER1'.
" Create ALV grid object
CREATE OBJECT o_grid1
EXPORTING
i_parent = o_container1.
" Set up field catalog and layout if needed (assuming lt_fcat and ls_layo are ready)
CALL METHOD o_grid1->set_table_for_first_display
EXPORTING
i_structure_name = 'ZDB_EDIT_ALV'
is_layout = ls_layo
CHANGING
it_outtab = lt_likp
it_fieldcatalog = lt_fcat
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 4.
" Set event handler for item-level data retrieval
DATA(o_delivery) = NEW delivery( ).
SET HANDLER o_delivery->get_data FOR o_grid1.
ENDIF.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0200 INPUT
MODULE USER_COMMAND_0200 INPUT.
CASE SY-UCOMM.
WHEN 'BACK'.
LEAVE PROGRAM. "Back to the program
WHEN 'CREATE'. "Creating new record for header data
PERFORM CREATE_HEADER_DATA.
WHEN 'EDIT'. "Editable alv for header data
PERFORM CHANGE_MODE.
WHEN 'UPDATE'. "Updateing the record for header data
PERFORM UPDATE_HEADER_DATA.
WHEN 'DELETE'. "deleteing for a record for header data
PERFORM DELETE_HEADER_DATA.
WHEN 'SAVE'. "saveing the db table for header data
PERFORM SAVE_HEADER_DATA.
ENDCASE.
ENDMODULE.
*&---------------------------------------------------------------------*
*& Form CHANGE_MODE
*&---------------------------------------------------------------------*
FORM CHANGE_MODE .
DATA : LT_INDEX_ROWS TYPE LVC_T_ROW,
LT_ROW_NO TYPE LVC_T_ROID,
LS_ROW_NO TYPE LVC_S_ROID,
LS_STYLEROW TYPE LVC_S_STYL,
LT_STYLEROW TYPE TABLE OF LVC_S_STYL.
CALL METHOD O_GRID1->GET_SELECTED_ROWS
IMPORTING
* et_index_rows = lt_index_rows
ET_ROW_NO = LT_ROW_NO.
IF NOT LT_ROW_NO IS INITIAL.
LOOP AT LT_LIKP INTO LS_LIKP.
READ TABLE LT_ROW_NO INTO LS_ROW_NO WITH KEY ROW_ID = SY-TABIX.
IF SY-SUBRC = 0.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'VBELN'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
LS_STYLEROW-FIELDNAME = 'ERDAT'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
LS_STYLEROW-FIELDNAME = 'VSTEL'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
LS_STYLEROW-FIELDNAME = 'VKORG'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
CLEAR: LS_LIKP-CELLTAB.
INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIKP-CELLTAB.
MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB.
CLEAR: LT_STYLEROW.
ELSE.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'VBELN'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'ERDAT'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'VSTEL'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'VKORG'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
CLEAR: LS_LIKP-CELLTAB.
INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIKP-CELLTAB.
MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB.
CLEAR: LT_STYLEROW.
ENDIF.
ENDLOOP.
ENDIF.
CLEAR LT_ROW_NO.
CLEAR LS_ROW_NO.
IF O_GRID1->IS_READY_FOR_INPUT( ) EQ 0.
CALL METHOD O_GRID1->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
ELSE.
CALL METHOD O_GRID1->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 0.
ENDIF.
CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY( ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CREATE_HEADER_DATA
*&---------------------------------------------------------------------*
FORM CREATE_HEADER_DATA .
DATA: LS_NEW TYPE T_ZDB_EDIT_ALV,
LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY,
LS_STYLEROW TYPE LVC_S_STYL.
CLEAR: LS_NEW, LT_STYLEROW.
" Define editable fields
LS_STYLEROW-FIELDNAME = 'VBELN'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'ERDAT'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'VSTEL'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'VKORG'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
" Assign celltab to new row
LS_NEW-CELLTAB = LT_STYLEROW.
" Insert new row at the beginning
APPEND LS_NEW TO LT_LIKP.
" Set grid to editable mode
CALL METHOD O_GRID1->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
" Refresh ALV to reflect changes
CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DELETE_HEADER_DATA
*&---------------------------------------------------------------------
FORM DELETE_HEADER_DATA .
DATA: LT_ROWS TYPE LVC_T_ROW,
LS_ROW TYPE LVC_S_ROW,
LV_IDX TYPE SY-TABIX.
CALL METHOD O_GRID1->GET_SELECTED_ROWS
IMPORTING ET_INDEX_ROWS = LT_ROWS.
LOOP AT LT_ROWS INTO LS_ROW.
LV_IDX = LS_ROW-INDEX.
READ TABLE LT_LIKP INDEX LV_IDX INTO LS_LIKP.
IF SY-SUBRC = 0.
DELETE FROM ZDB_EDIT_ALV WHERE VBELN = LS_LIKP-VBELN and ERNAM = LS_LIKP-ERNAM.
DELETE LT_LIKP INDEX LV_IDX.
ENDIF.
ENDLOOP.
CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY.
COMMIT WORK.
MESSAGE 'Selected header(s) deleted' TYPE 'S'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form SAVE_HEADER_DATA
*&---------------------------------------------------------------------*
TYPES: BEGIN OF TY_ZDB_EDIT_ALV_FLAT,
VBELN TYPE ZDB_EDIT_ALV-VBELN,
ERNAM TYPE ZDB_EDIT_ALV-ERNAM,
ERDAT TYPE ZDB_EDIT_ALV-ERDAT,
VSTEL TYPE ZDB_EDIT_ALV-VSTEL,
VKORG TYPE ZDB_EDIT_ALV-VKORG,
END OF TY_ZDB_EDIT_ALV_FLAT.
DATA: LS_DB_ALV_FLAT TYPE TY_ZDB_EDIT_ALV_FLAT.
FORM SAVE_HEADER_DATA .
DATA: LS_DB_ALV_FLAT TYPE TY_ZDB_EDIT_ALV_FLAT,
LV_VBELN TYPE ZDB_EDIT_ALV-VBELN,
LV_SKIPPED TYPE I VALUE 0,
LT_LIKP_CLEAN TYPE TABLE OF T_ZDB_EDIT_ALV,
LS_LIKP_CLEAN TYPE T_ZDB_EDIT_ALV,
LV_SAVED_ROWS TYPE I VALUE 0.
" Capture ALV changes
CALL METHOD O_GRID1->CHECK_CHANGED_DATA.
LOOP AT LT_LIKP INTO LS_LIKP.
" Skip empty header rows
IF LS_LIKP-VBELN IS INITIAL
AND LS_LIKP-ERNAM IS INITIAL
AND LS_LIKP-ERDAT IS INITIAL
AND LS_LIKP-VSTEL IS INITIAL
AND LS_LIKP-VKORG IS INITIAL.
LV_SKIPPED = LV_SKIPPED + 1.
CONTINUE.
ENDIF.
" Keep non-empty row for redisplay
LS_LIKP_CLEAN = LS_LIKP.
APPEND LS_LIKP_CLEAN TO LT_LIKP_CLEAN.
" Prepare structure for DB insert/update
CLEAR LS_DB_ALV_FLAT.
MOVE-CORRESPONDING LS_LIKP TO LS_DB_ALV_FLAT.
" Check if record exists
SELECT SINGLE VBELN
INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_VBELN
FROM ZDB_EDIT_ALV
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN.
IF SY-SUBRC = 0.
" Record exists -> UPDATE
UPDATE ZDB_EDIT_ALV SET
ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM,
ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT,
VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL,
VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN.
ELSE.
" Record does not exist -> INSERT
INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT.
ENDIF.
LV_SAVED_ROWS = LV_SAVED_ROWS + 1.
ENDLOOP.
" Replace the old internal table with the cleaned one (remove empty rows)
LT_LIKP = LT_LIKP_CLEAN.
COMMIT WORK.
*ENDIF.
" Message after save
IF LV_SKIPPED > 0.
MESSAGE |{ LV_SKIPPED } empty header record(s) were not saved and removed.| TYPE 'I'.
ELSEIF LV_SAVED_ROWS < 0.
MESSAGE | { LV_SAVED_ROWS } without editing or creating anything were data not saved.| TYPE 'I'.
ELSE.
MESSAGE 'Header data saved successfully' TYPE 'S'.
ENDIF.
" Lock the grid after save
PERFORM DISABLE_ALL_CELLS_IN_HEADER.
CALL METHOD O_GRID1->SET_READY_FOR_INPUT
EXPORTING I_READY_FOR_INPUT = 0.
CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form UPDATE_HEADER_DATA
*&---------------------------------------------------------------------*
FORM UPDATE_HEADER_DATA .
CALL METHOD O_GRID1->CHECK_CHANGED_DATA.
LOOP AT LT_LIKP INTO LS_LIKP.
" Map to flat structure (exclude CELLTAB)
LS_DB_ALV_FLAT-VBELN = LS_LIKP-VBELN.
LS_DB_ALV_FLAT-ERNAM = LS_LIKP-ERNAM.
LS_DB_ALV_FLAT-ERDAT = LS_LIKP-ERDAT.
LS_DB_ALV_FLAT-VSTEL = LS_LIKP-VSTEL.
LS_DB_ALV_FLAT-VKORG = LS_LIKP-VKORG.
" Check if record exists
SELECT SINGLE VBELN
INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1407137">@DATA</a>(LV_VBELN)
FROM ZDB_EDIT_ALV
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN
AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM.
IF SY-SUBRC = 0.
" Record exists -> UPDATE
UPDATE ZDB_EDIT_ALV SET
ERDAT = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERDAT,
VSTEL = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VSTEL,
VKORG = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VKORG
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV_FLAT-ERNAM.
ELSE.
" Record does not exist -> INSERT
INSERT ZDB_EDIT_ALV FROM LS_DB_ALV_FLAT.
ENDIF.
ENDLOOP.
COMMIT WORK.
MESSAGE 'Header data Updated successfully' TYPE 'S'.
" <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Make all fields non-editable after save
PERFORM DISABLE_ALL_CELLS_IN_HEADER.
" <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Set ALV to non-edit mode
CALL METHOD O_GRID1->SET_READY_FOR_INPUT
EXPORTING I_READY_FOR_INPUT = 0.
" <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Refresh ALV display
CALL METHOD O_GRID1->REFRESH_TABLE_DISPLAY.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CHANGE_ITEMS_MODE
*&---------------------------------------------------------------------*
FORM CHANGE_ITEMS_MODE .
DATA : LT_INDEX_ROWS TYPE LVC_T_ROW,
LT_ROW_NO TYPE LVC_T_ROID,
LS_ROW_NO TYPE LVC_S_ROID,
LS_STYLEROW TYPE LVC_S_STYL,
LT_STYLEROW TYPE TABLE OF LVC_S_STYL.
CALL METHOD O_GRID2->GET_SELECTED_ROWS
IMPORTING
* et_index_rows = lt_index_rows
ET_ROW_NO = LT_ROW_NO.
IF NOT LT_ROW_NO IS INITIAL.
LOOP AT LT_LIPS INTO LS_LIPS.
READ TABLE LT_ROW_NO INTO LS_ROW_NO WITH KEY ROW_ID = SY-TABIX.
IF SY-SUBRC = 0.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'VBELN'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'POSNR'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
LS_STYLEROW-FIELDNAME = 'MATNR'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
LS_STYLEROW-FIELDNAME = 'WERKS'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
CLEAR: LS_LIPS-CELLTAB.
INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB.
MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB.
CLEAR: LT_STYLEROW.
ELSE.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'VBELN'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'POSNR'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'MATNR'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
LS_STYLEROW-FIELDNAME = 'WERKS'.
INSERT LS_STYLEROW INTO TABLE LT_STYLEROW.
CLEAR: LS_LIPS-CELLTAB.
INSERT LINES OF LT_STYLEROW INTO TABLE LS_LIPS-CELLTAB.
MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB.
CLEAR: LT_STYLEROW.
ENDIF.
ENDLOOP.
ENDIF.
CLEAR LT_ROW_NO.
CLEAR LS_ROW_NO.
IF O_GRID2->IS_READY_FOR_INPUT( ) EQ 0.
CALL METHOD O_GRID2->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
ELSE.
CALL METHOD O_GRID2->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 0.
ENDIF.
O_GRID2->REFRESH_TABLE_DISPLAY( ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CREATE_ITEMS_DATA
*&---------------------------------------------------------------------
FORM CREATE_ITEMS_DATA .
DATA: LS_NEW TYPE T_ZDB_EDIT_ALV1,
LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY,
LS_STYLEROW TYPE LVC_S_STYL.
CLEAR: LS_NEW, LT_STYLEROW.
" Define editable fields
LS_STYLEROW-FIELDNAME = 'VBELN'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'POSNR'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'MATNR'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'WERKS'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_ENABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
" Assign celltab to new row
LS_NEW-CELLTAB = LT_STYLEROW.
" Insert new row at the beginning
APPEND LS_NEW TO LT_LIPS.
" Set grid to editable mode
CALL METHOD O_GRID2->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
" Refresh ALV to reflect changes
CALL METHOD O_GRID2->REFRESH_TABLE_DISPLAY.
ENDFORM.
TYPES: BEGIN OF TY_ZDB_EDIT_ALV1_FLAT,
VBELN TYPE ZDB_EDIT_ALV1-VBELN,
POSNR TYPE ZDB_EDIT_ALV1-POSNR,
ERNAM TYPE ZDB_EDIT_ALV1-ERNAM,
MATNR TYPE ZDB_EDIT_ALV1-MATNR,
WERKS TYPE ZDB_EDIT_ALV1-WERKS,
END OF TY_ZDB_EDIT_ALV1_FLAT.
DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT.
*&---------------------------------------------------------------------*
*& Form SAVE_ITEMS_DATA
*&---------------------------------------------------------------------
FORM SAVE_ITEMS_DATA .
DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT,
LS_DB_FULL TYPE ZDB_EDIT_ALV1,
LV_VBELN TYPE ZDB_EDIT_ALV1-VBELN,
LV_SKIPPED TYPE I VALUE 0,
LT_LIPS_CLEAN TYPE TABLE OF T_ZDB_EDIT_ALV1,
LS_LIPS_CLEAN TYPE T_ZDB_EDIT_ALV1,
LV_SAVED_ROWS TYPE I VALUE 0,
LV_HEADER_CHECK TYPE ZDB_EDIT_ALV-VBELN.
CALL METHOD O_GRID2->CHECK_CHANGED_DATA.
LOOP AT LT_LIPS INTO LS_LIPS.
" Skip empty item rows
IF LS_LIPS-VBELN IS INITIAL
AND LS_LIPS-POSNR IS INITIAL
AND LS_LIPS-ERNAM IS INITIAL
AND LS_LIPS-MATNR IS INITIAL
AND LS_LIPS-WERKS IS INITIAL.
LV_SKIPPED = LV_SKIPPED + 1.
CONTINUE.
ENDIF.
" # Check if header exists
SELECT SINGLE VBELN
INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_HEADER_CHECK
FROM ZDB_EDIT_ALV
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_LIPS-VBELN AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_LIPS-ERNAM.
IF SY-SUBRC <> 0.
LV_SKIPPED = LV_SKIPPED + 1.
CONTINUE. " Don't allow saving item without header
ENDIF.
" Keep non-empty row
LS_LIPS_CLEAN = LS_LIPS.
APPEND LS_LIPS_CLEAN TO LT_LIPS_CLEAN.
" Prepare flat structure
CLEAR LS_DB_ALV1.
MOVE-CORRESPONDING LS_LIPS TO LS_DB_ALV1.
" Check if item record exists
SELECT SINGLE VBELN
INTO <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1419942">@LV</a>_VBELN
FROM ZDB_EDIT_ALV1
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN
AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR
AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM.
IF SY-SUBRC = 0.
" UPDATE
UPDATE ZDB_EDIT_ALV1 SET
MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR,
WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN
AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR
AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM.
ELSE.
" INSERT
CLEAR LS_DB_FULL.
MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL.
INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL.
ENDIF.
LV_SAVED_ROWS = LV_SAVED_ROWS + 1.
ENDLOOP.
LT_LIPS = LT_LIPS_CLEAN.
COMMIT WORK.
" <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Final messaging
IF LV_SAVED_ROWS > 0.
MESSAGE 'Item data saved successfully' TYPE 'S'.
ELSEIF LV_SKIPPED > 0.
MESSAGE |{ LV_SKIPPED } item row(s) were skipped – empty or missing header.| TYPE 'I'.
ELSE.
MESSAGE 'No item data saved.' TYPE 'I'.
ENDIF.
" Make all fields non-editable after save
PERFORM DISABLE_ALL_CELLS_IN_ITEMS.
" Set ALV to non-edit mode
CALL METHOD O_GRID2->SET_READY_FOR_INPUT
EXPORTING I_READY_FOR_INPUT = 0.
" Refresh ALV display
CALL METHOD O_GRID2->REFRESH_TABLE_DISPLAY.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form UPDATE_ITEMS_DATA
*&---------------------------------------------------------------------*
FORM UPDATE_ITEMS_DATA .
DATA: LS_DB_ALV1 TYPE TY_ZDB_EDIT_ALV1_FLAT,
LS_DB_FULL TYPE ZDB_EDIT_ALV1,
LV_VBELN TYPE ZDB_EDIT_ALV1-VBELN.
" Ensure ALV changes are captured
CALL METHOD O_GRID2->CHECK_CHANGED_DATA.
LOOP AT LT_LIPS INTO LS_LIPS.
" Map to flat structure (exclude CELLTAB)
CLEAR LS_DB_ALV1.
LS_DB_ALV1-VBELN = LS_LIPS-VBELN.
LS_DB_ALV1-POSNR = LS_LIPS-POSNR.
LS_DB_ALV1-ERNAM = LS_LIPS-ERNAM.
LS_DB_ALV1-MATNR = LS_LIPS-MATNR.
LS_DB_ALV1-WERKS = LS_LIPS-WERKS.
" Check if record exists in DB
SELECT SINGLE VBELN
INTO @S_VBELN
FROM ZDB_EDIT_ALV1
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN
AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM.
IF SY-SUBRC = 0.
" Record exists -> UPDATE
UPDATE ZDB_EDIT_ALV1 SET
MATNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-MATNR,
WERKS = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-WERKS
WHERE VBELN = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-VBELN
AND POSNR = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-POSNR AND ERNAM = <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1450925">@LS</a>_DB_ALV1-ERNAM.
ELSE.
" Record does not exist -> INSERT
CLEAR LS_DB_FULL.
MOVE-CORRESPONDING LS_DB_ALV1 TO LS_DB_FULL.
INSERT ZDB_EDIT_ALV1 FROM LS_DB_FULL.
ENDIF.
ENDLOOP.
COMMIT WORK.
IF SY-SUBRC <> 0.
MESSAGE 'Item data saved successfully' TYPE 'S'.
ELSE.
MESSAGE 'Created new row but empty record not saved' type 'I'.
ENDIF.
" <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Make all fields non-editable after save
PERFORM DISABLE_ALL_CELLS_IN_ITEMS.
" <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Set ALV to non-edit mode
CALL METHOD O_GRID2->SET_READY_FOR_INPUT
EXPORTING I_READY_FOR_INPUT = 0.
" <span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span> Refresh ALV display
CALL METHOD O_GRID2->REFRESH_TABLE_DISPLAY.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DELETE_ITEMS_DATA
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM DELETE_ITEMS_DATA .
DATA: LT_ROWS TYPE LVC_T_ROW,
LS_ROW TYPE LVC_S_ROW,
LV_IDX TYPE SY-TABIX.
CALL METHOD O_GRID2->GET_SELECTED_ROWS
IMPORTING ET_INDEX_ROWS = LT_ROWS.
LOOP AT LT_ROWS INTO LS_ROW.
LV_IDX = LS_ROW-INDEX.
READ TABLE LT_LIPS INDEX LV_IDX INTO LS_LIPS.
IF SY-SUBRC = 0.
" Corrected DELETE to use both VBELN and POSNR
DELETE FROM ZDB_EDIT_ALV1 WHERE VBELN = LS_LIPS-VBELN AND POSNR = LS_LIPS-POSNR AND ERNAM = LS_LIPS-ERNAM.
DELETE LT_LIPS INDEX LV_IDX.
ENDIF.
ENDLOOP.
CALL METHOD O_GRID2->REFRESH_TABLE_DISPLAY.
COMMIT WORK.
MESSAGE 'Selected item(s) deleted' TYPE 'S'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DISABLE_ALL_CELLS_IN_HEADER
*&---------------------------------------------------------------------*
FORM DISABLE_ALL_CELLS_IN_HEADER .
DATA: LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY,
LS_STYLEROW TYPE LVC_S_STYL.
LOOP AT LT_LIKP INTO LS_LIKP.
CLEAR LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'VBELN'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'ERDAT'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'VSTEL'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'VKORG'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
" Apply to current row
LS_LIKP-CELLTAB = LT_STYLEROW.
MODIFY LT_LIKP FROM LS_LIKP TRANSPORTING CELLTAB.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DISABLE_ALL_CELLS_IN_ITEMS
*&---------------------------------------------------------------------*
FORM DISABLE_ALL_CELLS_IN_ITEMS .
DATA: LT_STYLEROW TYPE STANDARD TABLE OF LVC_S_STYL WITH DEFAULT KEY,
LS_STYLEROW TYPE LVC_S_STYL.
LOOP AT LT_LIPS INTO LS_LIPS.
CLEAR LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'VBELN'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'POSNR'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'ERNAM'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'MATNR'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
LS_STYLEROW-FIELDNAME = 'WERKS'.
LS_STYLEROW-STYLE = CL_GUI_ALV_GRID=>MC_STYLE_DISABLED.
APPEND LS_STYLEROW TO LT_STYLEROW.
" Apply to current row
LS_LIKP-CELLTAB = LT_STYLEROW.
MODIFY LT_LIPS FROM LS_LIPS TRANSPORTING CELLTAB.
ENDLOOP.
ENDFORM.</code></pre><P> </P>2026-01-24T04:59:44.641000+01:00https://community.sap.com/t5/technology-blog-posts-by-sap/my-home-in-sap-btp-abap-environment/ba-p/14314918My Home in SAP BTP ABAP Environment2026-01-28T10:41:54.700000+01:00LauraEiraEliashttps://community.sap.com/t5/user/viewprofilepage/user-id/793763<P>Good news – My Home is finally available with SAP BTP ABAP environment!</P><P>My Home is your personalized entry page that provides you with easy access to the business insights and applications you need to do your job with greater speed and agility. My Home for SAP BTP ABAP Environment lets you access and manage your favorite pages, your favorite apps, and your insights on any device. It follows a modular approach to meet the needs of different roles and builds on the functionality of the SAP Fiori launchpad using <SPAN><A href="https://help.sap.com/docs/btp/sap-fiori-launchpad-for-sap-btp-abap-environment/spaces-and-pages" target="_self" rel="noopener noreferrer">spaces and pages</A></SPAN>.</P><H3 id="toc-hId-1917747692"> </H3><H3 id="toc-hId-1721234187">New Look and Feel</H3><P><STRONG>My Home will be set as default for newly provisioned and existing systems as of SAP BTP ABAP Environment 2602.</STRONG> Accordingly, this soon changes the appearance of the SAP Fiori launchpad for every user. So, look forward to the new look and feel!</P><P><STRONG>However, the setting to disable My Home will still be available for administrators until the release upgrade SAP BTP ABAP environment 2608. Then, My Home will be the one and only entry page within SAP BTP ABAP environment.</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="My Home in SAP BTP ABAP environment" style="width: 873px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/365264iFA42766B899B2563/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="My Home.png" alt="My Home in SAP BTP ABAP environment" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">My Home in SAP BTP ABAP environment</span></span></STRONG></P><P> </P><H4 id="toc-hId-1653803401"> </H4><H4 id="toc-hId-1457289896">My Home Sections</H4><P>My Home is divided into different sections. You can view your <STRONG>News</STRONG>, <STRONG>Pages</STRONG>, <STRONG>Apps</STRONG>, <STRONG>Insights Tiles</STRONG>, and <STRONG>Insights Cards</STRONG> on this page.</P><H4 id="toc-hId-1260776391"> </H4><H4 id="toc-hId-1064262886">News</H4><P>The News section keeps you updated on your company's latest news, or SAP BTP ABAP environment system news.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="News section on My Home entry page" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/365266i1894F76DC213F66E/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="News.png" alt="News section on My Home entry page" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">News section on My Home entry page</span></span></P><P> </P><H4 id="toc-hId-867749381">Pages</H4><P>The Pages section provides you with quick access to your favorite or most used pages. You can manage the visibility of your pages and order them in a way that enhances your productivity. </P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Pages section on My Home entry page" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/365267i4B9ECD9C88714D2B/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Pages.png" alt="Pages section on My Home entry page" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Pages section on My Home entry page</span></span></P><H4 id="toc-hId-671235876"> </H4><H4 id="toc-hId-474722371">Apps</H4><P>The Apps section provides easy access to your favorite, most used, recently used, and recommended applications. The Apps section improves the discoverability of your applications. The <STRONG>Recommended</STRONG> tab offers app suggestions using SAP Business AI, based on your user-specific role assignment. You can add apps to the <STRONG>Favorites</STRONG> tab from your most used, recently used, and recommended applications. You can organize and categorize your favorite applications by using the grouping, ordering and color-coding functionality so you can access them even more efficiently. </P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Apps section on My Home entry page" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/365268i87787047F533C3AA/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Apps.png" alt="Apps section on My Home entry page" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Apps section on My Home entry page</span></span></P><P> </P><H4 id="toc-hId-278208866">Insights Tiles and Insights Cards</H4><P>The Insights section allows you to manage and monitor your company’s activities. It shows critical business information through KPIs and micro charts. This section is broken into two sections: <STRONG>Insights Tiles</STRONG> and <STRONG>Insights Cards</STRONG>. Insights cards and tiles display dynamic content at a glance. They provide quick and easy access to the applications that can provide more detailed information.</P><P>Insights tiles offer analytical information, such as charts or KPIs. Insights cards are similar to Insights tiles but provide more detailed analytical information in the form of charts, tables or lists from supporting overview page-, list report-, and analytical list page-based applications. Thanks to this information, you can assess what is happening at any time and take action when needed. You can customize the Insights section to display information that enables you to do your job with speed and agility. </P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Insights section on My Home entry page" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/365270i6A352999FB17DADD/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Tiles and Cards.png" alt="Insights section on My Home entry page" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Insights section on My Home entry page</span></span></P><P> </P><H3 id="toc-hId--122618727">Make it Mine – Personalize My Home to Your Needs</H3><P>Following the “Make it Mine” approach, you can personalize the entry page to hide or display specific sections as well as the content maintained within these sections. Another key feature is the ability to customize the layout of these sections. This personalization capability allows you to prioritize the information that is most important to you. </P><P>To personalize the entry page to your needs, choose <STRONG>My Home Settings</STRONG> from the dropdown menu of the respective sections. Here, you can customize the layout and configure the respective sections.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="My Home Settings" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/365271iA68D69E3C590E099/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="My Home Settings.png" alt="My Home Settings" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">My Home Settings</span></span></P><P> </P><P>We hope you enjoy working with My Home in SAP BTP ABAP environment and reap its benefits. You can look forward to more enhancements that will improve your My Home experience even further in future releases. Stay tuned for more updates!</P>2026-01-28T10:41:54.700000+01:00https://community.sap.com/t5/technology-blog-posts-by-sap/removal-of-business-groups-in-sap-btp-abap-environment-switching-to-spaces/ba-p/14316689Removal of Business Groups in SAP BTP ABAP Environment: Switching to Spaces and Pages2026-01-28T11:58:43.178000+01:00LauraEiraEliashttps://community.sap.com/t5/user/viewprofilepage/user-id/793763<P>Recently, we announced <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/my-home-in-sap-btp-abap-environment/ba-p/14314918" target="_self">My Home in SAP BTP ABAP environment.</A><BR />My Home is your personalized entry page that provides you with easy access to the business insights and applications you need to do your job with greater speed and agility.</P><P>As a prerequisite for My Home, SAP Fiori launchpad spaces and pages need to be enabled.<BR />The spaces mode was developed to offer more flexibility to influence the launchpad layout for specific user groups. Pages are assigned to users via spaces that are assigned to business roles. The business role defines which users see a specific space. By defining pages with meaningful sections, you can define in which order the apps are sorted on the page.</P><P> </P><H3 id="toc-hId-1917804609">Switching to Spaces and Pages</H3><P>Spaces and pages have been announced as the standard layout approach for structuring content in the SAP Fiori launchpad with SAP BTP ABAP environment 2302.<BR />Consequently, <STRONG>the classic Fiori launchpad home page with business groups will be removed gradually until 2608 in favor of SAP Fiori launchpad spaces and pages. </STRONG></P><P>Luckily, this is no news: The transition is going on for quite some time now, as spaces and pages are already the default in newly provisioned systems for several years. <BR /><STRONG>The removal of groups will affect newly provisioned systems at first with 2602. Later, with 2605, the switch will take place for existing systems as well.</STRONG></P><P>This means in detail:</P><UL><LI>With 2602, it is no longer possible to switch between spaces and pages and the classic Fiori launchpad home page with groups in newly provisioned systems.</LI><LI>With 2605, spaces and pages will be the default in existing systems as well. The option to switch to the classic home page with groups will still be available for end users if the administrator has enabled it in the Manage Launchpad Settings app.</LI><LI>With 2608, the option to switch to the classic FLP home page will be removed completely in production systems.</LI></UL><P> </P><H3 id="toc-hId-1721291104"><STRONG>How to Prepare for the Transition</STRONG></H3><P>Good news: The transition is straightforward, but there are a few important points to note. Until now, users couldn’t create their own groups in the SAP BTP ABAP environment. They relied on SAP-delivered groups and personalized them by adding, removing, or renaming tiles.</P><P>SAP provides predefined spaces and pages with similarly structured content. SAP-delivered groups will be switched to these predefined spaces and pages. <STRONG>Important: user-level personalizations made to the previous groups will not be carried over and will be lost due to the switch. You will need to recreate personal adjustments after the transition.</STRONG></P><P>To be as well prepared as possible, we recommend administrator to enable the switch to spaces and pages now to remain productive after the transition.</P><P>Here are our best practices for end users:</P><UL><LI>Plan the switch carefully and identify which adjustments are important to you.</LI><LI>Document your existing personalizations so you can rebuild them in spaces and pages.</LI><LI>Use SAP’s predefined spaces and pages as a starting point and tailor them to your workflow.</LI></UL><P> </P><H3 id="toc-hId-1524777599"><STRONG>For Administrators: Summary of the Upcoming Changes</STRONG></H3><P>As part of the mentioned transition to spaces and pages, SAP will change the SAP Fiori launchpad settings in the <EM>Manage Launchpad Settings</EM> app for administrators accordingly over the next release upgrades:</P><P><STRONG>With SAP BTP ABAP environment 2602:</STRONG></P><UL><LI><P>The parameter <FONT face="andale mono,times">SPACES</FONT> is removed in newly provisioned systems.</P></LI><LI>The parameter <FONT face="andale mono,times">SPACES_ENABLE_USER</FONT> is removed in newly provisioned systems.</LI><LI>The parameter <FONT face="andale mono,times">SPACES_CUSTOM_HOME</FONT> is true (ON) as default for all existing and newly provisioned systems. The setting to disable My Home is still available. Since spaces and pages need to be enabled as a prerequisite for My Home, this needs to be manually activated for existing systems.</LI></UL><P><STRONG>With SAP BTP ABAP environment 2605:</STRONG></P><UL><LI>The parameter <FONT face="andale mono,times">SPACES</FONT> is true (ON) as default in existing systems.</LI><LI>The parameter <FONT face="andale mono,times">SPACES_ENABLE_USER</FONT> is false (OFF) as default in existing systems. The settings to enable switching between the classic FLP homepage and the spaces and pages layout is still available.</LI></UL><P><STRONG>With SAP BTP ABAP environment 2608:</STRONG></P><UL><LI>The parameter <FONT face="andale mono,times">SPACES</FONT> is removed.</LI><LI>The parameter <FONT face="andale mono,times">SPACES_ENABLE_USER</FONT> is removed.</LI><LI>The parameter <FONT face="andale mono,times">SPACES_CUSTOM_HOME</FONT> is removed.</LI></UL><P><SPAN> </SPAN></P><P>Ultimately, there will be no option to switch back to groups or to enable toggling between spaces and pages and groups after the SAP BTP ABAP environment 2608 release upgrade. You must complete the transition to spaces and pages before the final, irreversible switch in production systems with the 2608 release upgrade.</P><P>We therefore invite all customers to begin transitioning now and proactively embrace this change.</P>2026-01-28T11:58:43.178000+01:00https://community.sap.com/t5/enterprise-architecture-blog-posts/create-an-editable-alv-grid-with-crud-functionality-in-abap/ba-p/14100914Create an Editable ALV Grid with CRUD Functionality in ABAP2026-01-28T15:09:13.768000+01:00Naveennani8523https://community.sap.com/t5/user/viewprofilepage/user-id/1800750<P><STRONG>Objective</STRONG></P><P>This program displays data from a custom table ZDB_SALES_CRUD in an editable ALV Grid. Based on user input, it allows creating new records, editing existing ones, and deleting selected entries from the table.</P><OL><LI><STRONG>Data Declarations</STRONG></LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_0-1747205741796.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260887i24E4B66ADBFB0E18/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_0-1747205741796.png" alt="Naveennani8523_0-1747205741796.png" /></span></P><P> </P><UL><LI>Declares the DB table from which we will retrieve and update data.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_1-1747205741797.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260884i24A9CC2A0E886532/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_1-1747205741797.png" alt="Naveennani8523_1-1747205741797.png" /></span></P><P> </P><UL><LI>Defines a structure TY_VBAK_ALV that mirrors the structure of ZDB_SALES_CRUD. This is used for internal data handling.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_2-1747205741798.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260885i00EC66BAAFE69EFB/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_2-1747205741798.png" alt="Naveennani8523_2-1747205741798.png" /></span></P><P> </P><P>Declares global data:</P><UL><LI>GT_DATA: Internal table for ALV display.</LI><LI>GS_DATA: Work area for processing one record at a time.</LI><LI>GT_FIELDCAT: ALV field catalog table.</LI><LI>GR_ALV_GRID: ALV Grid instance.</LI><LI>GV_OK_CODE: Captures user commands.</LI></UL><P><span class="lia-unicode-emoji" title=":desktop_computer:">🖥</span>️ 2. <STRONG>Selection Screen</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_3-1747205741799.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260890i347CFAA4BD0FEAB3/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_3-1747205741799.png" alt="Naveennani8523_3-1747205741799.png" /></span></P><P> </P><UL><LI>Provides a simple UI for the user to choose between <STRONG>display</STRONG> or <STRONG>edit</STRONG> mode.</LI></UL><P><span class="lia-unicode-emoji" title=":play_button:">▶️</span>3. <STRONG>Program Execution Starts</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_4-1747205741800.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260888iB103FFF4BA9A3F1B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_4-1747205741800.png" alt="Naveennani8523_4-1747205741800.png" /></span></P><P> </P><UL><LI>Fetches data using GET_DATA and navigates to screen 100 which contains the ALV Grid.</LI></UL><H2 id="toc-hId-1730363982">🧩 4. <STRONG>Screen 100 – Module Pool</STRONG></H2><H3 id="toc-hId-1662933196">Module: STATUS_0100 (OUTPUT)</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_5-1747205741801.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260889iD9314C3ED16F3C08/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_5-1747205741801.png" alt="Naveennani8523_5-1747205741801.png" /></span></P><P> </P><UL><LI>Sets the GUI status (menu buttons like Create, Update, etc.)</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_6-1747205741801.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260891i7EB579696557A878/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_6-1747205741801.png" alt="Naveennani8523_6-1747205741801.png" /></span></P><P> </P><UL><LI>Instantiates the ALV Grid object.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_7-1747205741802.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260893i8D41EC0FD3B1282B/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_7-1747205741802.png" alt="Naveennani8523_7-1747205741802.png" /></span></P><P> </P><UL><LI>Builds the field catalog and populates the grid for the first time.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_8-1747205741802.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260892iAE0CE0BF44981931/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_8-1747205741802.png" alt="Naveennani8523_8-1747205741802.png" /></span></P><P> </P><UL><LI>Makes the grid editable if user chose "Edit" mode.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_9-1747205741804.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260895iC901ED8F8380A8C3/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_9-1747205741804.png" alt="Naveennani8523_9-1747205741804.png" /></span></P><P> </P><UL><LI>Handles user interactions and maps them to specific FORM routines.</LI></UL><H2 id="toc-hId-1337336972"><span class="lia-unicode-emoji" title=":inbox_tray:">📥</span>5. <STRONG>FORM: GET_DATA</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_10-1747205741804.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260894i1936421ACF193FF3/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_10-1747205741804.png" alt="Naveennani8523_10-1747205741804.png" /></span><P> </P>Fetches all records from the database table into the internal table GT_DATA.</LI></UL><H2 id="toc-hId-1140823467"><span class="lia-unicode-emoji" title=":bar_chart:">📊</span>6. <STRONG>FORM: BUILD_FIELDCATALOG</STRONG></H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_11-1747205741805.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260896i06EABA75D0821C6F/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_11-1747205741805.png" alt="Naveennani8523_11-1747205741805.png" /></span></P><UL><LI>Dynamically builds the field catalog required by the ALV grid using a macro.</LI></UL><H2 id="toc-hId-944309962"><span class="lia-unicode-emoji" title=":pencil:">✏️</span>7. <STRONG>FORM: ENABLE_EDITING</STRONG></H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_12-1747205741806.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260897i6F4C13BDEC259E6A/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_12-1747205741806.png" alt="Naveennani8523_12-1747205741806.png" /></span></P><UL><LI>Enables edit mode on the ALV grid.</LI></UL><H2 id="toc-hId-747796457"><span class="lia-unicode-emoji" title=":heavy_plus_sign:">➕</span>8. <STRONG>FORM: CREATE_RECORD</STRONG></H2><UL><LI><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_13-1747205741807.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260898iA88A25EA963F2304/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_13-1747205741807.png" alt="Naveennani8523_13-1747205741807.png" /></span></LI><LI><P> </P>Notifies the user to fill in data and save.</LI></UL><H2 id="toc-hId-551282952"><span class="lia-unicode-emoji" title=":counterclockwise_arrows_button:">🔄</span>9. <STRONG>FORM: UPDATE_RECORDS</STRONG></H2><P>CALL METHOD GR_ALV_GRID->CHECK_CHANGED_DATA.SELECT * FROM ZDB_SALES_CRUD INTO TABLE LT_EXISTING.</P><UL><LI>Checks ALV for changes and fetches existing records from DB into a sorted table.</LI></UL><P>LOOP AT GT_DATA INTO GS_DATA. READ TABLE LT_EXISTING ... WITH KEY VBELN POSNR.</P><UL><LI>Compares input data with existing DB entries based on key fields.</LI></UL><P>IF SY-SUBRC = 0. UPDATE ZDB_SALES_CRUD FROM LS_EXISTING.ELSE. INSERT ZDB_SALES_CRUD FROM LS_EXISTING.ENDIF.</P><UL><LI>Updates existing record or inserts a new one.</LI></UL><P>COMMIT WORK.REFRESH_TABLE_DISPLAY.MESSAGE 'Records updated in database.' TYPE 'S'.</P><UL><LI>Saves changes and refreshes the grid.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_14-1747205741810.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260899i488A52E942C6CDD3/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_14-1747205741810.png" alt="Naveennani8523_14-1747205741810.png" /></span></P><H2 id="toc-hId-354769447"><span class="lia-unicode-emoji" title=":cross_mark:">❌</span>10. <STRONG>FORM: DELETE_RECORDS</STRONG></H2><P>CALL METHOD GR_ALV_GRID->GET_SELECTED_ROWS IMPORTING ET_INDEX_ROWS = LT_INDICES.</P><UL><LI>Gets user-selected rows for deletion.</LI></UL><P>LOOP AT LT_INDICES INTO LS_INDEX. READ TABLE GT_DATA INTO GS_DATA INDEX LV_TABIX. DELETE FROM ZDB_SALES_CRUD WHERE VBELN = ... AND POSNR = .</P><UL><LI>Deletes the record from the database and internal table.</LI></UL><P>COMMIT WORK.REFRESH_TABLE_DISPLAY.MESSAGE |{ LV_DELETED } record(s) deleted successfully.| TYPE 'S'.</P><UL><LI>Commits and informs the user of deleted rows.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_15-1747205741812.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260901i1A1E0148A424C783/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_15-1747205741812.png" alt="Naveennani8523_15-1747205741812.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Naveennani8523_16-1747205741813.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/260900iDCA15F02CE1B9082/image-size/medium?v=v2&px=400" role="button" title="Naveennani8523_16-1747205741813.png" alt="Naveennani8523_16-1747205741813.png" /></span></P><P><STRONG>CODE:</STRONG></P><pre class="lia-code-sample language-abap"><code>REPORT ZINSERT_SD_CUSTOM.
TABLES: ZDB_SALES_CRUD.
TYPES: BEGIN OF TY_VBAK_ALV,
VBELN TYPE ZDB_SALES_CRUD-VBELN,
POSNR TYPE ZDB_SALES_CRUD-POSNR,
ERNAM TYPE ZDB_SALES_CRUD-ERNAM,
AUART TYPE ZDB_SALES_CRUD-AUART,
VKORG TYPE ZDB_SALES_CRUD-VKORG,
MATNR TYPE ZDB_SALES_CRUD-MATNR,
ARKTX TYPE ZDB_SALES_CRUD-ARKTX,
WAERK TYPE ZDB_SALES_CRUD-WAERK,
END OF TY_VBAK_ALV.
DATA: GT_DATA TYPE STANDARD TABLE OF TY_VBAK_ALV,
GS_DATA TYPE TY_VBAK_ALV,
GT_FIELDCAT TYPE LVC_T_FCAT,
GS_FIELDCAT TYPE LVC_S_FCAT,
GR_ALV_GRID TYPE REF TO CL_GUI_ALV_GRID,
GV_OK_CODE TYPE SY-UCOMM.
SELECTION-SCREEN BEGIN OF BLOCK B1 WITH FRAME TITLE TEXT-002.
PARAMETERS: P_DISP RADIOBUTTON GROUP GRP1 DEFAULT 'X',
P_EDIT RADIOBUTTON GROUP GRP1.
SELECTION-SCREEN END OF BLOCK B1.
START-OF-SELECTION.
PERFORM GET_DATA.
CALL SCREEN 100.
*---------------------------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
SET PF-STATUS 'ZALV_STATUS'.
IF GR_ALV_GRID IS INITIAL.
CREATE OBJECT GR_ALV_GRID
EXPORTING
I_PARENT = CL_GUI_CONTAINER=>SCREEN0.
PERFORM BUILD_FIELDCATALOG.
CALL METHOD GR_ALV_GRID->SET_TABLE_FOR_FIRST_DISPLAY
EXPORTING
IS_LAYOUT = VALUE LVC_S_LAYO( EDIT = ABAP_TRUE )
CHANGING
IT_OUTTAB = GT_DATA
IT_FIELDCATALOG = GT_FIELDCAT.
IF P_EDIT = 'X'.
CALL METHOD GR_ALV_GRID->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
ENDIF.
ENDIF.
ENDMODULE.
*---------------------------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
GV_OK_CODE = SY-UCOMM.
CASE GV_OK_CODE.
WHEN 'CREATE'.
PERFORM CREATE_RECORD.
WHEN 'EDIT'.
PERFORM ENABLE_EDITING.
WHEN 'UPDATE'.
PERFORM UPDATE_RECORDS.
WHEN 'DELETE'.
PERFORM DELETE_RECORDS.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
LEAVE PROGRAM.
ENDCASE.
ENDMODULE.
*---------------------------------------------------------------------*
FORM GET_DATA.
CLEAR GT_DATA.
SELECT VBELN POSNR ERNAM AUART VKORG MATNR ARKTX WAERK
FROM ZDB_SALES_CRUD
INTO TABLE GT_DATA.
ENDFORM.
*---------------------------------------------------------------------*
FORM BUILD_FIELDCATALOG.
CLEAR GT_FIELDCAT.
DEFINE ADD_FIELD.
CLEAR gs_fieldcat.
gs_fieldcat-fieldname = &1.
gs_fieldcat-coltext = &2.
APPEND gs_fieldcat TO gt_fieldcat.
END-OF-DEFINITION.
ADD_FIELD 'VBELN' 'Sales Document'.
ADD_FIELD 'POSNR' 'Item No'.
ADD_FIELD 'ERNAM' 'Created By'.
ADD_FIELD 'AUART' 'Sales Doc Type'.
ADD_FIELD 'VKORG' 'Sales Org'.
ADD_FIELD 'MATNR' 'Material'.
ADD_FIELD 'ARKTX' 'Description'.
ADD_FIELD 'WAERK' 'Currency'.
ENDFORM.
*---------------------------------------------------------------------*
FORM ENABLE_EDITING.
CALL METHOD GR_ALV_GRID->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
ENDFORM.
*---------------------------------------------------------------------*
FORM CREATE_RECORD.
DATA: LS_NEW TYPE TY_VBAK_ALV.
CLEAR LS_NEW.
APPEND LS_NEW TO GT_DATA.
CALL METHOD GR_ALV_GRID->REFRESH_TABLE_DISPLAY
EXPORTING
IS_STABLE = VALUE LVC_S_STBL( ROW = 'X' COL = 'X' ).
CALL METHOD GR_ALV_GRID->SET_READY_FOR_INPUT
EXPORTING
I_READY_FOR_INPUT = 1.
MESSAGE 'Enter new row data and press UPDATE.' TYPE 'S'.
ENDFORM.
*---------------------------------------------------------------------*
FORM UPDATE_RECORDS.
CALL METHOD GR_ALV_GRID->CHECK_CHANGED_DATA.
DATA: LT_EXISTING TYPE SORTED TABLE OF ZDB_SALES_CRUD
WITH UNIQUE KEY VBELN POSNR,
LS_EXISTING TYPE ZDB_SALES_CRUD.
" Fetch all existing records
SELECT * FROM ZDB_SALES_CRUD INTO TABLE LT_EXISTING.
LOOP AT GT_DATA INTO GS_DATA.
READ TABLE LT_EXISTING INTO LS_EXISTING
WITH KEY VBELN = GS_DATA-VBELN
POSNR = GS_DATA-POSNR.
IF SY-SUBRC = 0.
" Update existing
MOVE-CORRESPONDING GS_DATA TO LS_EXISTING.
UPDATE ZDB_SALES_CRUD FROM LS_EXISTING.
ELSE.
" Insert new
MOVE-CORRESPONDING GS_DATA TO LS_EXISTING.
INSERT ZDB_SALES_CRUD FROM LS_EXISTING.
ENDIF.
ENDLOOP.
COMMIT WORK.
PERFORM GET_DATA.
CALL METHOD GR_ALV_GRID->REFRESH_TABLE_DISPLAY
EXPORTING
IS_STABLE = VALUE LVC_S_STBL( ROW = 'X' COL = 'X' ).
MESSAGE 'Records updated in database.' TYPE 'S'.
ENDFORM.
*---------------------------------------------------------------------*
FORM DELETE_RECORDS.
DATA: LT_INDICES TYPE LVC_T_ROW,
LS_INDEX TYPE LVC_S_ROW,
LV_TABIX TYPE SY-TABIX,
LV_DELETED TYPE I VALUE 0.
CALL METHOD GR_ALV_GRID->GET_SELECTED_ROWS
IMPORTING
ET_INDEX_ROWS = LT_INDICES.
SORT LT_INDICES BY INDEX DESCENDING.
LOOP AT LT_INDICES INTO LS_INDEX.
LV_TABIX = LS_INDEX-INDEX.
READ TABLE GT_DATA INTO GS_DATA INDEX LV_TABIX.
IF SY-SUBRC = 0.
DELETE FROM ZDB_SALES_CRUD
WHERE VBELN = _DATA-VBELN AND POSNR = _DATA-POSNR.
IF SY-SUBRC = 0.
DELETE GT_DATA INDEX LV_TABIX.
LV_DELETED = LV_DELETED + 1.
ENDIF.
ENDIF.
ENDLOOP.
COMMIT WORK.
CALL METHOD GR_ALV_GRID->REFRESH_TABLE_DISPLAY
EXPORTING
IS_STABLE = VALUE LVC_S_STBL( ROW = 'X' COL = 'X' ).
IF LV_DELETED > 0.
MESSAGE |{ LV_DELETED } record(s) deleted successfully.| TYPE 'S'.
ELSE.
MESSAGE 'No records were deleted. Please check keys.' TYPE 'I'.
ENDIF.
ENDFORM.</code></pre>2026-01-28T15:09:13.768000+01:00https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-members/how-ai-automation-eliminates-master-data-duplicates-in-sap/ba-p/14318692How AI Automation Eliminates Master Data Duplicates in SAP2026-01-30T15:58:32.901000+01:00Siarheihttps://community.sap.com/t5/user/viewprofilepage/user-id/84286<H4 id="toc-hId-2046946934"><STRONG>The Business Case</STRONG></H4><P>Whether running SAP ECC or S/4HANA, most organizations struggle with duplicate master data for materials, vendors, and customers. This isn't just a "clutter" problem, poor material master data leads to users creating <STRONG>Purchase Requisitions with text items</STRONG>, bypassing procurement controls and ruining spend analytics.</P><P>Let’s explore how AI automation and <STRONG>data vectorization</STRONG> can clean up the core and prevent duplicates before they happen.</P><H4 id="toc-hId-1850433429"><STRONG>The Engine: What is Data Vectorization?</STRONG></H4><P>At Skybuffer, we are constantly exploring the benefits of SAP data vectorization. Simply put, vectorization converts data into numerical arrays (vectors) using embedding functions.</P><P>Unlike standard SAP keyword searches, vectors are <STRONG>language-independent</STRONG> and allow algorithms to perform <STRONG>similarity searches</STRONG>. While standard tables see rows and columns, a vectorized model sees the <I>relationship</I> between data points.</P><H4 id="toc-hId-1653919924"><STRONG>How Does It Help?</STRONG></H4><P>When data is vectorized, we can execute <STRONG>hybrid searches</STRONG> that are indifferent to word order or exact spelling.</P><P><STRONG>Example:</STRONG> Imagine searching for a global customer like "Skybuffer." You might have different accounts for Poland and Norway. If a user tries to create a new record, they can simply ask:</P><BLOCKQUOTE><P class="lia-align-left" style="text-align : left;"><I>"Do we have a Customer master record for Skybuffer in Poland?"</I></P></BLOCKQUOTE><P>By querying vectorized <STRONG>KNA1</STRONG> table data, the AI identifies the record even if the naming convention differs slightly.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer_AI_Duplicates_Pic01.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367414iC3AA8D0E4F0FD765/image-size/large?v=v2&px=999" role="button" title="Skybuffer_AI_Duplicates_Pic01.png" alt="Skybuffer_AI_Duplicates_Pic01.png" /></span></P><P class="lia-align-center" style="text-align: center;"> <EM>Pic.1 Hybrid Search based on Vectorized KNA1 Table Data</EM></P><H4 id="toc-hId-1457406419"><STRONG>Real-World Integration Points</STRONG></H4><P>Hybrid search is most powerful when embedded directly into the SAP business process:</P><UL><LI><P><STRONG>Preventative Checks:</STRONG> During the "Save" action in SAP, a custom check against vectorized data can alert the user to a potential duplicate.</P></LI><LI><P><STRONG>External Access:</STRONG> Quick searches via Microsoft Teams or SAP Fiori to find existing masters on the go.</P></LI><LI><P><STRONG>Smart Procurement:</STRONG> Identifying an existing Material Master during the ordering process, preventing the user from resorting to a "text item."</P></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer_AI_Duplicates_Pic02.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367418iFF3D4E5FEA03092A/image-size/large?v=v2&px=999" role="button" title="Skybuffer_AI_Duplicates_Pic02.png" alt="Skybuffer_AI_Duplicates_Pic02.png" /></span></P><P class="lia-align-center" style="text-align: center;"> <EM>Pic.2 Quick Searches of SAP Master Data based on Vectorized Data</EM></P><H4 id="toc-hId-1260892914"><STRONG>Conclusion</STRONG></H4><P>Generative AI is a powerhouse when used wisely. Many companies struggle to find the right use cases, often just mirroring existing SAP processes in a chat window. <STRONG>That isn’t true AI automation.</STRONG></P><P>Our approach is different: we focus on the gaps in standard automation. By using AI to simplify data discovery, we reduce development effort and provide an intelligent, frictionless experience for SAP users.</P><H4 id="toc-hId-1064379409"><STRONG>Closing Statement</STRONG></H4><P>Keep automating. Remember: <STRONG>smart customization is a competitive advantage</STRONG>, not a deviation from the standard. Build with AI in mind to slash support costs and maximize your ROI via the Skybuffer AI platform.</P>2026-01-30T15:58:32.901000+01:00https://community.sap.com/t5/abap-blog-posts/why-document-like-it-s-1999/ba-p/14319106Why Document Like it's 19992026-01-31T19:19:27.708000+01:00Mattiashttps://community.sap.com/t5/user/viewprofilepage/user-id/11415<DIV class=""><H2 id="your-first-day-on-the-new-project" id="toc-hId-1788806207">Your First Day on the New Project</H2><P>You open the documentation repository. There's an Excel sheet titled “RICEFW<EM>Inventory</EM>v3<EM>FINAL</EM>2.xlsx”</P><P>You scan through:</P><UL><LI>Row 47: “Enhancement ZENH<EM>MAT</EM>001 – Material validation”</LI><LI>Row 89: “Report ZMM<EM>STOCK</EM>013 – Stock overview”<BR />Row 134: “Form ZSD<EM>ORDER</EM>PRINT – Order output”</LI><LI>Row 201: “Interface ZIF<EM>PRICING</EM>002 – Pricing calculation”</LI></UL><P>Your task: “Fix the credit check bug in sales order creation.”</P><P>You stare at the screen. <EM>Which row is that?</EM></P><P>You search for “credit”. Eight matches. Three are reports. Two are enhancements. One is a workflow you've never heard of.</P><P>You ask your colleague: “Where's the credit check logic?”</P><P>She sighs. “Check the validation BADI in ZFICO_CUST. Or is it the user exit? Actually, I think there's also a workflow step... let me check my notes from six months ago...”</P><P><STRONG>Three hours later, you still haven't found it.</STRONG></P><P>Sound familiar?</P><HR /><H2 id="part-1-the-problem-with-ricefw-documentation" id="toc-hId-1592292702">The Problem with RICEFW Documentation</H2><H3 id="ricefw-thinks-in-technical-artifacts" id="toc-hId-1524861916">RICEFW Thinks in Technical Artifacts</H3><P>RICEFW (Reports, Interfaces, Conversions, Enhancements, Forms, Workflows) was invented when SAP development meant: – Modifying a monolithic ECC system – Creating standalone reports – Adding enhancements to standard transactions – Building separate interfaces</P><P>Documentation followed the same pattern: categorize by <EM>technical artifact type</EM>.</P><P>This made sense in 1999.</P><H3 id="rap-thinks-in-business-capabilities" id="toc-hId-1328348411">RAP Thinks in Business Capabilities</H3><P>Fast-forward to 2026. You're building a Sales Order business object in RAP:</P><PRE><CODE>ZI_SALESORDER_M (Business Object)
├── Data Model (CDS views)
│ ├── ZI_SALESORDER_M (interface view)
│ └── ZC_SALESORDER_M (projection view)
├── Behavior Definition
│ ├── Validations (validateCustomer, validateCredit)
│ ├── Determinations (calculatePrice)
│ └── Actions (releaseOrder, cancelOrder)
├── Business Events
│ └── OrderCreated, OrderReleased
└── Service
└── ZUI_SALESORDER_O4 (OData V4)</CODE></PRE><P><STRONG>Everything about Sales Orders in one cohesive business object.</STRONG></P><P>Yet your documentation still says: – “Check Enhancement ZENHSD001” – “See Report ZSDORDERLIST” – “Refer to Form ZSDPRINTORDER”</P><P><STRONG>The disconnect is killing you.</STRONG></P><HR /><H2 id="part-2-what-rap-actually-gave-us" id="toc-hId-1002752187">What RAP Actually Gave Us - besides RAP itself</H2><P>Here's what's often missed in RAP discussions:</P><P><STRONG>RAP isn't just a new technical framework.</STRONG> It's SAP finally embracing domain-driven design principles that the rest of the software world has used for years.</P><UL><LI>Business objects that model business capabilities</LI><LI>Clean separation of concerns</LI><LI>Event-driven architecture</LI><LI>Clear service boundaries</LI></UL><P><STRONG>This is how modern software should be built.</STRONG></P><P>And when you build this way, your documentation can finally match how people hopefully think.</P><P>Not “Which enhancement modifies field X?”</P><P>But “How does the Sales Order capability work?”</P><P><STRONG>RAP enables the documentation style we should have been using all along.</STRONG></P><HR /><H2 id="part-3-three-documentation-layers-for-rap" id="toc-hId-806238682">Now the good stuff - Three Documentation Layers for RAP</H2><H3 id="layer-1-business-object-canvas" id="toc-hId-738807896">Layer 1: Business Object Canvas</H3><P><STRONG>The idea:</STRONG> One wiki page per RAP business object. Everything about that capability in one place.</P><P><STRONG>Here's what it actually looks like:</STRONG></P><HR /><P><STRONG>Business Object:</STRONG> Sales Order</P><P><STRONG>Business Capability:</STRONG> Complete sales order lifecycle from customer inquiry through order fulfillment</P><P><STRONG>Location in System:</STRONG> – Package: <CODE>ZRAP_SD_ORDER</CODE> – Root Entity: <CODE>ZI_SALESORDER_M</CODE> – Projection: <CODE>ZC_SALESORDER_M</CODE> – Service Binding: <CODE>ZUI_SALESORDER_O4</CODE> (OData V4, Published) – Fiori App: Sales Order Management – Main Transport: <CODE>ZTRK900123</CODE></P><P><STRONG>Team & Ownership:</STRONG> – Development Team: Retail Sales Team – Product Owner: Jane Smith – Technical Lead: John Doe – Last Major Update: 2025-01-27</P><HR /><P><STRONG>Behavior & Operations:</STRONG></P><P><EM>Standard Operations:</EM> – Create, Update, Delete (all enabled) – Draft handling: Enabled – ETag field: LastChangedAt</P><P><EM>Validations (run on save):</EM></P><UL><LI><CODE>validateCustomer</CODE> Checks customer exists and is not blocked</LI><LI><CODE>validateCreditLimit</CODE> – Verifies customer credit limit not exceeded</LI><LI><CODE>validateMaterial</CODE> – Ensures material exists and valid for sales</LI><LI><CODE>validateDeliveryDate</CODE> – Must be in the future</LI></UL><P><EM>Determinations (auto-calculations):</EM></P><UL><LI><CODE>calculateNetAmount</CODE> – Runs when quantity or price changes</LI><LI><CODE>setDefaultPaymentTerms</CODE> – Runs on create (from customer master)</LI><LI><CODE>determineDeliveryDate</CODE> – Calculates based on material availability</LI></UL><P><EM>Actions (user-triggered):</EM></P><UL><LI><CODE>releaseOrder</CODE> – Releases order to warehouse (publishes OrderReleased event)</LI><LI><CODE>cancelOrder</CODE> – Cancels entire order (publishes OrderCancelled event)</LI><LI><CODE>splitOrderItem</CODE> – Splits line item into multiple delivery schedules</LI></UL><HR /><P><STRONG>Events & Integration:</STRONG></P><P><EM>Events Published:</EM></P><UL><LI><CODE>OrderCreated</CODE> – When order activated from draft – Subscribers: Inventory BO (reserves stock), Analytics Service</LI><LI><CODE>OrderReleased</CODE> – When release action executed – Subscribers: Warehouse BO (starts picking), Billing BO (creates invoices</LI><LI><CODE>OrderCancelled</CODE> – When cancel action executed – Subscribers: Inventory BO (releases reservation)</LI></UL><P><EM>Events Subscribed:</EM></P><UL><LI><CODE>StockReserved</CODE> (from Inventory BO) – Updates order status to “Ready for Release”</LI><LI><CODE>StockShortage</CODE> (from Inventory BO) – Marks order as “Partially Allocated”</LI></UL><HR /><P><STRONG>Dependencies:</STRONG></P><P><EM>Upstream (What We Consume):</EM></P><P><STRONG>Material Master</STRONG> (I_Product) – Owner: Master Data Team – Access: Read-only via association – Fields used: Product, ProductType, BaseUnit, SalesText – Impact if unavailable: Order creation blocked (validation fails) – Contact: master-data-team@company.com</P><P><STRONG>Customer Master</STRONG> (I_Customer</P><UL><LI>Owner: Master Data Team</LI><LI>Access: Read-only via association</LI><LI>Fields used: Customer, CustomerName, CreditLimit, PaymentTerms</LI><LI>Impact if unavailable: Order creation blocked (validation fails)</LI><LI>Contact: master-data-team@company.com</LI></UL><P><STRONG>Pricing Engine</STRONG> (ZZPRICE<EM>ENGINE – Function Module) </EM></P><UL><LI><EM>Owner: Pricing Team – Access: Synchronous RFC call (wrapped in ZCL</EM>PRICING_ACL)</LI><LI>Called when: During determination (calculateNetAmount)</LI><LI>Timeout: 5 seconds</LI><LI>Impact if unavailable: Order creation blocked, error shown to user</LI><LI>Why synchronous: [See ADR-018]</LI><LI>Contact: pricing-team@company.com</LI></UL><P><EM>Downstream (Who Consumes Us):</EM> </P><UL><LI>Inventory BO (subscribes to OrderCreated, OrderCancelled)</LI><LI>Warehouse BO (subscribes to OrderReleased)</LI><LI>Billing BO (reads order data via association, subscribes to OrderReleased)</LI><LI>Analytics Dashboard (reads via OData for reporting)</LI><LI>Mobile Sales App (reads/writes via OData)</LI></UL><HR /><P><STRONG>Key Architecture Decisions:</STRONG> </P><UL><LI>[ADR-015] Why we chose managed RAP implementation </LI><LI>[ADR-018] Why pricing happens in determinations (not actions)</LI><LI>[ADR-023] How we handle external pricing service integration</LI><LI> [ADR-032] Why credit check is synchronous (blocks save)</LI></UL><P><STRONG>Related Documentation:</STRONG> </P><UL><LI>API Documentation: <A href="https://blog.nacka.io/link" target="_blank" rel="noopener nofollow noreferrer">OData Service Spec</A> </LI><LI>Process Documentation: <A href="https://blog.nacka.io/link" target="_blank" rel="noopener nofollow noreferrer">Order-to-Cash Process</A> <EM>(coming in Part 2 of this series)</EM> </LI><LI>Test Data: Customer 1000001, Material MAT-TEST-001</LI></UL><HR /><P><STRONG>That's the canvas.</STRONG> One page. ~5 minutes to scan. Everything about Sales Orders.</P><P>Compare this to hunting through a RICEFW spreadsheet with 200 rows.</P><H3 id="layer-2-architecture-decision-records-adrs" id="toc-hId-542294391">Layer 2: Architecture Decision Records (ADRs)</H3><P>The hard part isn't writing RAP code. It's deciding <EM>why</EM> to write it a certain way, and later remembering why that decision was taken.</P><P class=""><STRONG>The Industry Solution: Architecture Decision Records</STRONG></P><P class="">This problem isn't unique to SAP or RAP. It's why organizations like AWS and IBM actively recommend using Architecture Decision Records (ADRs) to capture the reasoning behind technical decisions.</P><P class="">AWS Prescriptive Guidance recommends using architectural decision records to streamline technical decision-making for a software development project. <SPAN class=""><A class="" href="https://adr.github.io/" target="_blank" rel="noopener nofollow noreferrer"><SPAN class=""><SPAN class="">Architectural Decision Records</SPAN></SPAN></A></SPAN> IBM has documented their use of ADRs in production systems, showing how they help teams maintain context over time.</P><P class="">The principle is simple: when you make a significant technical decision, document why you made it, what alternatives you considered, and what consequences you accepted.</P><P class="">Six months later, when someone asks "Why?", you point them to the ADR.</P><H3 id="toc-hId-345780886"><STRONG>Example ADR:</STRONG></H3><HR /><P><STRONG>ADR-018: Calculate Pricing in Determinations (Not Actions)</STRONG></P><P><EM>Date:</EM> 2025-01-15<BR /><EM>Status:</EM> <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Accepted<BR /><EM>Deciders:</EM> Tech Lead, Solution Architect, Senior Developer</P><P><STRONG>Context:</STRONG></P><P>We need to calculate item pricing in Sales Order BO. Two options:</P><P><STRONG>Option A: Determination (automatic)</STRONG> – Runs automatically during save sequence – User sees price immediately when quantity changes – Can't be skipped</P><P><STRONG>Option B: Action (manual)</STRONG> – User must click “Calculate Price” button – More control over when calculation happens – Can be skipped if needed</P><P>Current situation: – Pricing engine (ZZPRICE_ENGINE) is legacy FM, ~2 second response time – Business requires instant price feedback for sales reps – Complex pricing rules (discounts, surcharges, customer agreements)</P><P><STRONG>Decision:</STRONG></P><P>Use <STRONG>determination</STRONG> to calculate pricing automatically on quantity/material changes.</P><P><STRONG>Rationale:</STRONG></P><P><EM>Why determination:</EM></P><UL><LI>Sales reps need instant price visibility</LI><LI>Prevents orders being saved with wrong/missing prices</LI><LI>Aligns with UX requirement: “price updates as you type”</LI><LI>Consistent with standard SAP behavior</LI></UL><P><EM>Why not action:</EM> </P><UL><LI>Extra click burdens sales reps (average 50 orders/day/rep)</LI><LI>Risk of forgetting to calculate = wrong invoices</LI><LI>User testing showed confusion with manual pricing button</LI></UL><P><EM>Risks accepted:</EM> </P><UL><LI>2-second save time (acceptable per UX testing)</LI><LI>Pricing service must be highly available (99.9% SLA)</LI></UL><P><STRONG>Consequences:</STRONG></P><P><EM>Positive:</EM> </P><UL><LI>Instant price feedback for sales reps</LI><LI>No risk of missing price calculation</LI><LI>Reduced training time (automatic behavior)</LI><LI>Consistent UX across all sales channels</LI></UL><P><EM>Negative:</EM> </P><UL><LI>Every save calls pricing engine (load concern)</LI><LI>Can't skip pricing for “draft” scenarios</LI><LI>Pricing service downtime blocks all orders</LI></UL><P><EM>Mitigations:</EM> </P><UL><LI>Pricing service has 5-second timeout (fail-fast)</LI><LI>Fallback: save order with “Price Pending” flag, batch re-price later</LI><LI>Pricing team committed to 99.9% SLA</LI><LI>Monitoring alert if pricing calls >3 seconds</LI></UL><P><STRONG>Implementation Notes:</STRONG></P><PRE><CODE>determination calculateNetAmount on modify {
field Quantity;
field Material;
field Customer;
}</CODE></PRE><P>In behavior implementation: – Call ZCL<EM>PRICING</EM>ACL wrapper (not direct FM call) – Wrapper implements circuit breaker pattern – Logs all pricing calls for debugging</P><P><STRONG>Related:</STRONG> – [ADR-023] Anti-corruption layer for pricing service – [ADR-040] Pricing service timeout handling</P><HR /><P><STRONG>The principle:</STRONG> Six months from now, when someone asks “Why does save take 2 seconds?”, you point to ADR-018. Everything is documented.</P><P><STRONG>The principle:</STRONG> When Master Data announces “We're changing Material descriptions from 40 to 80 characters,” you know instantly that 12 BOs need coordination.</P><HR /><H2 id="part-4-why-this-works" id="toc-hId-20184662">Part 4: Why This Works</H2>RICEFW Docs BO Canvas Approach <TABLE><TBODY><TR><TD>ZTRK900123 – Enhancement for credit check</TD><TD>Sales Order BO → validateCreditLimit</TD></TR><TR><TD>5 spreadsheet tabs</TD><TD>1 wiki page</TD></TR><TR><TD>Technical artifact types</TD><TD>Business capabilities</TD></TR><TR><TD>“Why?” is in meeting notes</TD><TD>“Why?” is in ADRs</TD></TR><TR><TD>Dependencies invisible</TD><TD>Dependency matrix</TD></TR><TR><TD>3 hours to find credit check</TD><TD>3 minutes to find credit check</TD></TR></TBODY></TABLE><P><STRONG>Real impact:</STRONG></P><P><EM>Onboarding time:</EM> </P><UL><LI>RICEFW: weeks to understand one domain</LI><LI>BO Canvas: days to understand one domain</LI></UL><P><EM>Incident response:</EM> </P><UL><LI>RICEFW: “Where's the logic?” → hours–</LI><LI>BO Canvas: “Check Sales Order BO canvas” → minutes</LI></UL><P><EM>Impact analysis:</EM> </P><UL><LI>RICEFW: “Who uses Material Master?” → “¯\<EM>(ツ)</EM>/¯”</LI><LI>BO Canvas: “Check dependency matrix” → 12 BOs listed</LI></UL><HR /><H2 id="toc-hId-170925514">Part 5: What This Doesn't Solve (Yet)</H2><P>You've documented your Sales Order BO beautifully. Dependencies are clear. Decisions are captured.</P><P>Then someone asks: “Walk me through what happens when a customer creates an order. Step by step. Including credit check, stock reservation, pricing, and warehouse handoff.”</P><P>You point them to four BO Canvases:</P><UL><LI>Sales Order BO</LI><LI>Credit Check BO</LI><LI>Inventory BO<BR />Shipping BO</LI></UL><P>They read all four. They check dependencies. They still don't understand the <EM>sequence</EM> of events , what happens if credit check fails etc.</P><P>Business Object Canvases document capabilities, ADRs document decisions, Dependency matrices document connections.</P><P>But none of them document the actual business process flow, ant that's why that's the topic for the next post in this series. </P><HR /><P><STRONG>Next in this series:</STRONG> <EM>Part 2: Documenting Business Processes – From BOs to Flows</EM></P><P><EM>What's your biggest documentation challenge? Drop a comment below.</EM></P></DIV><P> </P>2026-01-31T19:19:27.708000+01:00https://community.sap.com/t5/artificial-intelligence-blogs-posts/bringing-ai-context-to-eclipse-adt-a-local-mcp-setup-guide/ba-p/14300669Bringing AI Context to Eclipse ADT: A Local MCP Setup Guide2026-02-02T11:43:27.255000+01:00Luisenhttps://community.sap.com/t5/user/viewprofilepage/user-id/39395<H3 id="toc-hId-1916702280"><STRONG>The Context Gap</STRONG></H3><P>Recently, I came across an <A href="https://www.linkedin.com/pulse/agentic-abap-why-i-built-bridge-claude-code-alice-vinogradova-mgobe/?trackingId=4yjvDfruTAaRIH64BhskOQ%3D%3D" target="_self" rel="nofollow noopener noreferrer">insightful article</A> from <STRONG>Alice Vinogradova</STRONG> explaining how to use <STRONG>Claude Code</STRONG> to revolutionize our ABAP workflow. While I agree that tools like Claude Code are fantastic for coding, many of us face a common reality: corporate restrictions.</P><P>Like me, you might be working in an environment where you can't access external AI tools or install unauthorized software, and you are eagerly waiting for the SAP Toolkit to fully support VS Code.</P><P>But I do have access to <STRONG>Eclipse ADT</STRONG> and I’ve managed to get <STRONG>GitHub Copilot</STRONG> running. That got me thinking: <I>What if we could use Model Context Protocol (MCP) servers to bridge the gap between our locked-down SAP systems and our AI agents?</I></P><P><STRONG>Boom!</STRONG> It turns out, we can. By deploying MCP servers locally, we can safely expose our ABAP context and documentation to Copilot without breaking security protocols.</P><P class="lia-align-center" style="text-align: center;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Luisen_6-1767370422885.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/357806iD2687FD825B186EB/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Luisen_6-1767370422885.png" alt="Luisen_6-1767370422885.png" /></span></P><P>Here is how I set up my "Old School" local build to get full AI context inside Eclipse.</P><HR /><H3 id="toc-hId-1720188775"><STRONG>Step 1: The Build (Old School Style)</STRONG></H3><P>I prefer building from source. It allows me to track exactly what dependencies are being installed and analyze the code—crucial for maintaining a clean and secure corporate machine.</P><P>I created a local folder called <CODE>MCPs</CODE> to house my helpers.</P><H4 id="toc-hId-1652757989"><STRONG>1. Vibing Steampunk (The ADT Bridge)</STRONG></H4><P>First, we need the bridge that connects the AI to our SAP system via the ADT interface.</P><DIV class=""><DIV class=""><SPAN class="">Bash</SPAN></DIV><DIV class=""> </DIV></DIV><pre class="lia-code-sample language-bash"><code># Clone the repository
git clone https://github.com/oisee/vibing-steampunk.git
cd vibing-steampunk
# Build the binary
make build</code></pre><H4 id="toc-hId-1456244484"><STRONG>2. SAP Documentation (The Knowledge Base)</STRONG></H4><P>Next, I added the <STRONG>SAP Docs MCP</STRONG> server (by <I>marianfoo</I>) to the mix. This tool enriches the AI's responses with official documentation, ensuring it doesn't hallucinate non-existent syntax.</P><pre class="lia-code-sample language-bash"><code>#Clone the repository
git clone https://github.com/marianfoo/mcp-sap-docs.git
cd mcp-sap-docs
# From repo root
npm ci
./setup.sh # execute this script to clone the github documentation submodules
npm run build</code></pre><H3 id="toc-hId-1130648260"><STRONG>Step 2: Configuring Eclipse</STRONG></H3><P>Once the builds are complete, we need to tell the Eclipse Copilot agent where to find these new tools.</P><OL><LI><P>Open Eclipse.</P></LI><LI><P>Navigate to the <STRONG>Model Context Protocol (MCP)</STRONG> configuration section in Github Copilot Chat:<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Luisen_1-1767367192281.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/357789iE6232091EB86261C/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="Luisen_1-1767367192281.png" alt="Luisen_1-1767367192281.png" /></span></P></LI><LI><P>Add the following JSON configuration.</P></LI></OL><BLOCKQUOTE><P><STRONG>Note:</STRONG> Update the paths (<CODE>/Users/xxx/...</CODE>) and credentials to match your local setup.</P></BLOCKQUOTE><pre class="lia-code-sample language-json"><code>{
"servers": {
"sap-docs": {
"command": "node",
"args": [
"/Users/xxx/MCPs/mcp-sap-docs/dist/src/server.js"
]
},
"abap-adt-command": {
"type": "stdio",
"command": "/Users/xxx/MCPs/vibing-steampunk/build/vsp",
"args": [
"--url",
"https://vxxx.frx.hec.xxx.com:44300",
"--user",
"USER",
"--password",
"PASSWORD",
"--client",
"100"
]
}
}
}</code></pre><P>If everything is configured correctly, checking the <STRONG>Tools</STRONG> section in the Agent view will list all available capabilities (like <CODE>search_sap_docs</CODE>, <CODE>get_transport</CODE>, etc.).</P><P><STRONG>Pro Tip:</STRONG> For performance reasons, deactivate any tools you don't use often to keep the context window clean.<BR /><BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Luisen_2-1767367397633.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/357790i71D0278BCD2A4009/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Luisen_2-1767367397633.png" alt="Luisen_2-1767367397633.png" /></span></P><HR /><H3 id="toc-hId-934134755"><STRONG>Step 3: The Results</STRONG></H3><P>With the setup ready, I put the agent to the test with some real-world ABAP scenarios.</P><H4 id="toc-hId-866703969"><STRONG>Scenario A: The On-Call SRE</STRONG></H4><P>I asked the agent to act as a Site Reliability Engineer and analyze the system state.</P><BLOCKQUOTE><P><STRONG>Prompt:</STRONG> "You are an on-call ABAP SRE. Investigate recent dumps, trace the execution path, and identify the most likely root cause. Check if there are relevant SAP notes or community blogs about these problems"</P></BLOCKQUOTE><P><STRONG>The Result:</STRONG> The agent was able to pull actual dumps from the system and summarize them into a professional report:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Luisen_0-1767371595611.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/357809i3BBCAD59FA968CD8/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Luisen_0-1767371595611.png" alt="Luisen_0-1767371595611.png" /></span></P><P>I'll shorten the answer for narrative proposes:</P><P><EM>I'll analyze the three recent ST22 dumps you provided, trace the call stacks, give the most likely root cause for each, point to relevant docs/community leads, and provide immediate and next-step remediation actions.</EM></P><P><EM>Checklist (what I did)</EM><BR /><EM>- [x] Fetched recent dumps (ST22 HTML pages you provided)</EM><BR /><EM>- [x] Extracted key header + call-stack + source-lines for each dump</EM><BR /><EM>- [x] Reasoned the most likely root cause for each dump (code bug vs infra)</EM><BR /><EM>- [x] Looked up SAP Help and SAP Community references that are relevant / actionable</EM><BR /><EM>- [x] Produced immediate mitigations, repro/diagnosis steps, and recommended long-term fixes</EM></P><P><EM>Summary of dumps inspected</EM><BR /><EM>- ITAB_DUPLICATE_KEY — /XXX/CL_TCORE_DATA_BUFFER=====CP READ_ORDERS — 2026-01-02 15:33:17 — Background job on host vxxx_xxx_00 (client xxx). Terminating statement: INSERT ls_order_info INTO TABLE gt_order_info (include CM001 line ~115).</EM><BR /><EM>- CALL_FUNCTION_ACCEPT_FAILED — SAPMSSY1 REMOTE_FUNCTION_CALL — 2026-01-02 09:07:12 — CPIC/RFC error: CM_SECURITY_NOT_VALID / RFC_IO5 (SNC-related). Termination in CALL 'RfcImport' ID 'Type' (include SAPMSSY1 line ~185).</EM><BR /><EM>- TIME_OUT — CL_WDR_CHGTOOL_MD_READER======CP REC_GET_CONTEXT_INFO — 2026-01-02 10:46:29 — Program exceeded uninterrupted runtime (profile parameter rdisp/scheduler/prio_high/max_runtime = 660s). Termination during looping over metadata attributes (include CM003 around line ~62).</EM></P><P><EM>Detailed analysis and next steps</EM></P><P><EM>1) ITAB_DUPLICATE_KEY — /PPA/CL_TCORE_DATA_BUFFER=====CP :: READ_ORDERS</EM><BR /><EM>- Evidence (from dump)</EM><BR /><EM>- Runtime error: ITAB_DUPLICATE_KEY (CX_SY_ITAB_DUPLICATE_KEY)</EM><BR /><EM>- Termination at: INSERT ls_order_info INTO TABLE gt_order_info (highlighted line)</EM><BR /><EM>- Key component values shown: {004030000389;0020;} (these are the key values that caused the duplicate)</EM><BR /><EM>- Call stack: READ_ORDERS -> CHECK_ORDERS -> GET_ACCNT_SERVICE_ORDER -> WRITE_ACCNT_SERVICE_ORDER -> WRITE_ACCNT_OBJECTS -> ... (main SAPMSSYC)</EM><BR /><EM>- Program started as a background job.</EM><BR /><EM>- Likely root cause</EM><BR /><EM>- The code attempts to insert a row into an internal table that has a unique (primary or unique secondary) key that already exists. The INSERT statement here is not handling duplicates and the table type / key composition causes ABAP to raise CX_SY_ITAB_DUPLICATE_KEY and abort.</EM><BR /><EM>- This is most often a logic bug: either the incoming data contains duplicates, or prior logic already inserted the same key into gt_order_info earlier in the loop, and the code does not test for existence before INSERT.</EM><BR /><EM>- Less likely: a race between parallel processes — internal tables are process-local, so race conditions across WPs are not applicable unless gt_order_info is a static/shared object (e.g., attribute of a shared object or using shared memory). From the stack it looks like a normal local table in a background job.</EM><BR /><EM>- Recommended immediate mitigations</EM><BR /><EM>- Change the INSERT to either:</EM><BR /><EM>- Check existence before insert:</EM><BR /><EM>- READ TABLE gt_order_info WITH TABLE KEY <key fields> INTO <some> and only INSERT if not present; or</EM><BR /><EM>- Use INSERT ... INTO TABLE ... ACCEPTING DUPLICATE KEYS (if duplicates are benign and you can ignore them), or</EM><BR /><EM>- Use INSERT ... INTO TABLE ... TRANSPORTING to avoid delayed unique key update issues as appropriate.</EM><BR /><EM>- Add logging around the insertion (user, key values, call context) to capture which input produced duplicate keys.</EM><BR /><EM>- Reproduction / diagnosis steps</EM><BR /><EM>- Inspect declaration of `gt_order_info` to determine key fields and whether it is SORTED / HASHED / STANDARD with UNIQUE secondary keys.</EM><BR /><EM>- Run the code in the debugger on a copy of the same input or add an explicit READ before INSERT to capture the duplicate values and reproduce.</EM><BR /><EM>- If background job: re-run job in test system or with a small controlled dataset to confirm fix.</EM><BR /><EM>- Long-term fix</EM><BR /><EM>- Make the code robust to duplicate input (explicit checks, deduplication before loop, or use internal-table operations intended for possible duplicates).</EM><BR /><EM>- Add a unit test that simulates duplicate input.</EM><BR /><EM>- Useful references</EM><BR /><EM>- ABAP docs on INSERT/ITAB and duplicate keys (explanations and examples of when exception is thrown):</EM><BR /><EM>- INSERT into internal table / duplicates: ABAP docs (INSERT itab / duplicate behaviour) — see ABAP docs pages on INSERT and itab unique/secondary keys.</EM><BR /><EM>- SAP Community threads with examples/diagnostics of ITAB_DUPLICATE_KEY (search term: "CX_SY_ITAB_DUPLICATE_KEY INSERT INTO TABLE") — common examples and fixes.</EM></P><P> </P><P><EM>...</EM></P><P><EM>...</EM></P><P><EM>Relevant SAP docs / community resources I found (quick list)</EM><BR /><EM>- ABAP docs on runtime errors and exceptions (general guide): ABAP runtime errors / exception classes — useful to understand DX_SY_ITAB_DUPLICATE_KEY semantics.</EM><BR /><EM>- ABAP docs - INSERT / internal table duplicate behavior: explanation of when ITAB_DUPLICATE_KEY is raised and examples of safe patterns (READ before INSERT, ACCEPTING DUPLICATE KEYS).</EM><BR /><EM>- SAP Community threads (examples and discussions):</EM><BR /><EM>- Examples where INSERT into internal tables caused CX_SY_ITAB_DUPLICATE_KEY and how developers wrapped INSERT in try/catch or used READ TABLE to avoid crash.</EM><BR /><EM>- General posts on TIME_OUT and rdisp scheduler parameters (how max_runtime is used and default values).</EM><BR /><EM>- For RFC/SNC issues:</EM><BR /><EM>- SAP Help pages and configuration guides on SNC, SM59, and RFC troubleshooting (look for "Secure Network Communication", "SM59 test connection", "RFC_IO5", "CM_SECURITY_NOT_VALID").</EM><BR /><EM>- If you need SAP OSS notes for a specific kernel/patch-level interaction or a specific RFC error, collect the trace files and open an OSS incident — the low-level RFC I/O errors often need kernel-level investigation.</EM></P><P><EM>(Notes about search results)</EM><BR /><EM>- I searched SAP docs and community for specific error combinations; the ABAP docs (INSERT / internal table documentation) and community posts about ITAB_DUPLICATE_KEY are directly relevant and available in SAP Help and community - those explain behavior and coding patterns to avoid the error.</EM><BR /><EM>- For the SNC/RFC error I did not find a single canonical OSS note in the returned results that exactly matches CM_SECURITY_NOT_VALID + RFC_IO5; SNC failures are typically environment-specific (certs, SNC library, partner names), so targeted SM59 and gateway traces are normally required before finding an OSS note. If you want I can run a focused query on SAP OSS once you provide any kernel level logs or RFC destination names.</EM></P><P><EM>Immediate action plan you can run now (ordered)</EM><BR /><EM>1. ITAB_DUPLICATE_KEY</EM><BR /><EM>- Open ST22 for that dump and capture the full dump ID, active variables. (You already have HTML; include dump ID in any ticket.)</EM><BR /><EM>- Inspect the code: open class /PPA/CL_TCORE_DATA_BUFFER and check the declaration of `gt_order_info` and the preceding loop that fills ls_order_info. Add a READ TABLE check or use "ACCEPTING DUPLICATE KEYS" where appropriate.</EM><BR /><EM>- Add defensive logging right before the INSERT to capture duplicates (key values and call context).</EM><BR /><EM>- If feasible, reproduce in a test client with the same input set.</EM></P><P><I>...</I></P><P><I>...</I></P><P><EM>What to collect and provide to SAP OSS (if you open a ticket)</EM><BR /><EM>- For ITAB_DUPLICATE_KEY: ST22 short dump text (full HTML), code snippet of the affected include/class, description of input dataset and job configuration.</EM><BR /><EM>- For RFC/SNC (CALL_FUNCTION_ACCEPT_FAILED): SM59 test results, SM21 logs, gateway trace (gwrdump/gwserv trace), RFC trace, dump HTML, and RFC destination name.</EM><BR /><EM>- For TIME_OUT: ST22 dump, SAT/ST12 profiling trace, number of attributes processed, input dataset, and job schedule.</EM></P><DIV> </DIV><H4 id="toc-hId-670190464"><STRONG>Scenario B: Code Refactoring</STRONG></H4><P>I then asked it to modernize a legacy report (<CODE>z_lsn_test_2</CODE>).</P><BLOCKQUOTE><P><STRONG>Prompt:</STRONG> "You are a senior ABAP refactoring assistant. Review report zlsn_test_2. Find DSAG ABAP guidelines for object-oriented programming that could be used here and also add syntax for inline declarations in ABAP 7.58. And then apply the changes with minimal, well-documented edits. "</P></BLOCKQUOTE><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Luisen_1-1767374014382.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/357815i32FB08CAA709474C/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Luisen_1-1767374014382.png" alt="Luisen_1-1767374014382.png" /></span></P><P><STRONG>After several tool usage:</STRONG></P><DIV><P><EM><SPAN>Perfect! The refactoring is complete and activated. Let me provide you with a final summary:<BR /></SPAN></EM><EM><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span>ZLSN_TEST_2 Refactoring Complete<BR /></EM><EM>I have successfully refactored ZLSN_TEST_2 with modern ABAP 7.58 syntax and DSAG OOP guidelines. The refactored program is now active in your system.</EM></P><P><EM>Key Refactoring Changes:</EM></P><P><EM>1. ABAP 7.58 Modern Syntax Applied<BR /></EM><EM>• <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Inline Declarations (DATA) - Variables declared at point of use within loops and SPLIT operations</EM><BR /><EM>• <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Functional VALUE Constructor - Single consolidated statements replacing field-by-field assignments</EM><BR /><EM>• <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Modern SELECT Syntax - ABAP SQL with inline declarations for database reads</EM><BR /><EM>• <span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span> Safe Table Lookups - VALUE #(...) with OPTIONAL clause to prevent exceptions</EM></P><P><BR /><EM>2. DSAG OOP Guidelines Applied</EM></P><P><EM>Single Responsibility Principle:<BR /></EM><EM>| Procedure | Purpose | Lines | |-----------|---------|-------|<BR /></EM><EM>| read_file_records() | File I/O via GUI_UPLOAD | ~35 |<BR />| parse_and_validate_records() | Parse CSV and validate data | ~25 |<BR />| process_updates() | Coordinate database update | ~30 |<BR />| handle_test_mode() | Display test output | ~5 |<BR />| handle_live_mode() | Execute update & confirm | ~8 |</EM></P><P><EM>Composition Pattern:</EM></P><P><EM>• Delegated responsibilities to focused procedures</EM><BR /><EM>• Clear separation: file I/O → parsing → validation → database update → output</EM></P><P><EM>Fail-Fast Principle:</EM></P><P><EM>• Input validation happens immediately after file read</EM><BR /><EM>• Early exit prevents wasting resources on invalid data</EM></P><P><EM>3. Code Structure Improvements</EM></P><P><EM>Before:<BR /></EM><EM>• 1 monolithic START-OF-SELECTION block (100+ lines)</EM><BR /><EM>• Mixed concerns: file I/O, parsing, validation, database update, output</EM><BR /><EM>• Difficult to test, maintain, understand</EM><BR /><EM>• High cyclomatic complexity<BR /></EM><EM>After:<BR /></EM><EM>• 5 focused procedures (avg. 20 lines each)</EM><BR /><EM>• Clear separation of concerns</EM><BR /><EM>• Each procedure independently testable</EM><BR /><EM>• 75% reduction in nesting depth</EM></P><P><EM>4. Status<BR /></EM><EM><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span>Program activated successfully</EM><BR /><EM><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span>Syntax check passed (1 warning - not critical)</EM><BR /><EM><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span>Functionality preserved - All original features intact</EM><BR /><EM><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span>100% DSAG compliant - Following proven SAP community guidelines</EM><BR /><EM><span class="lia-unicode-emoji" title=":white_heavy_check_mark:">✅</span>Ready for production - Can be deployed immediately</EM></P><P><BR /><EM>Summary of Improvements<BR /></EM><EM>| Aspect | Impact | |--------|--------|<BR /></EM><EM>| Code Clarity | 90% improved - Clear procedure names and responsibilities |<BR /></EM><EM>| Maintainability | 85% improved - Easy to find and modify specific functionality |<BR /></EM><EM>| Testability | From 0% to 100% - Each procedure can be tested independently |<BR /></EM><EM>| Performance | No degradation - Inline declarations compile to identical code |<BR /></EM><EM>| Compliance | 100% - Full DSAG + ABAP 7.58 best practices |</EM></P><P><EM>ZLSN_TEST_2 has now been refactored and documented with comprehensive technical details following DSAG guidelines and ABAP 7.58 modern syntax! <span class="lia-unicode-emoji" title=":party_popper:">🎉</span></EM></P></DIV><H3 id="toc-hId-344594240"><STRONG>Conclusion</STRONG></H3><P>By chaining these two MCP servers together, we turn Eclipse into a powerhouse. <CODE>vibing-steampunk</CODE> gives the AI "eyes" to see our specific system state, while <CODE>mcp-sap-docs</CODE> gives it the "brain" of the official documentation.</P><P>It’s a secure, local, and highly effective way to level up your ABAP development—even behind the corporate firewall.</P><H3 id="toc-hId-148080735"><STRONG>What's next?</STRONG></H3><P>So far I think it's a big improvements with the reduced scope of these two tools. But at the same time, there are still things that can be tweaked:</P><UL><LI>Agent customizing: I'm using here out-of-the-box components. With more fine tuning the responses would be much better.</LI><LI>Tool improvements: as you know, there are some restrictions when using Eclipse with ABAP. And this is also dependent on the Eclipse, ADT or Copilot version. With a specific version combination of them, the behavior would be much better and less erratic. </LI></UL>2026-02-02T11:43:27.255000+01:00https://community.sap.com/t5/technology-blog-posts-by-sap/tweaks-for-rap-bo-events-addressing-filtering-before-send-and-too-small/ba-p/14320767Tweaks for RAP BO events addressing filtering (before send) and too small payload (callbacks needed)2026-02-03T15:18:52.529000+01:00mlauberhttps://community.sap.com/t5/user/viewprofilepage/user-id/157846<P>Are you working on modernizing your SAP integrations, or looking for better ways to integrate with clean core compliance? But when you've looked at "Event Objects" from the SAP Business Accelerator Hub, you have found that it's not exactly matching your needs? Too many events are fired (can I filter?). The callback API is too time-consuming/unwanted. Or maybe you are simply interested in how ABAP RESTful Programming Model (RAP) Events work, how you can use and/or extend SAP Standard events?</P><P>In this blog I'll go through first some basic info and then start to showcase some tips / tweaks / workarounds you may or may not be aware about. Let's go.</P><H1 id="toc-hId-1660384843">1 ABAP RESTful Programming Model (RAP) Events Intro</H1><P>I'll keep this very brief as the meat of this blog is to go into the nitty-gritty details. But, for the uninitiated, RAP BO events are events that have been built with the RAP framework which can easily integrate with event brokers, such as SAP Business Technology Platform's Event Mesh or Advanced Event Mesh. They are a sort of modern version of BTEs. You may refer to a previous blog of mine where I go into one full end-to-end example, showcasing how to find SAP standard events and then use them: <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/working-with-rap-bo-events-end-to-end-event-driven-architecture-event/ba-p/14018775" target="_blank">Working with RAP BO Events end-to-end</A> . The short version is that all events can be found on the <A href="https://hub.sap.com/" target="_blank" rel="noopener noreferrer">SAP Business Accelerator Hub</A> -> Your SAP Product -> Events.</P><H1 id="toc-hId-1463871338">2 Too many events are fired / I want to filter</H1><P>This is probably one of the most common discussion points when I work with my customers. More often than not a "Created" or even more interestingly, a "Changed" event is simply fired too often for the actual integration needs. So what can we do here? In essence we have 3 main options:</P><OL><LI><STRONG>Integration middleware handles filtering</STRONG> (= no changes in SAP system, use event as is)<OL><LI>This can be desirable if there are lots of receiving systems that need to receive information for a certain object, and maybe each of them would like to filter a little different. The middleware receives the event as it happens and can then handle the distribution accordingly. This way 1 single event could be the foundation of several functioning integrations (instead of several point-to-point integrations). The quote-on-quote downside to this is that you would of course increase the complexity in the middleware itself, but again if the same event benefits several receivers, this could be a good option.<BR /><BR /></LI></OL></LI><LI><STRONG>Extend SAP standard event</STRONG> to include filtering fields (= extension development in your SAP system, use extended event, not standard)<OL><LI>This can be used if you know for sure you always want to filter out certain types of objects, that none of the integrated systems would want to be informed about. The quote-on-quote downside here is that we need to create an extension. Secondly, we first have to check if the SAP Standard RAP BO in question even allows behavior extensions. If not, we cannot use this option at all.<BR /><BR /></LI></OL></LI><LI><STRONG>Use custom event in combination with SAP Standard event</STRONG> as a workaround (= custom development in your SAP system, use custom event, not standard)<OL><LI>Same as for the previous one, this option can be used if we know for a fact we always want to filter away certain objects. We can use this over the extend option, if for example the extension was not possible, or if the extension possibilities do not suffice (for example we need to add fields that are not easily associated in the RAP BO, or we need some complex logic and checking before we send an event)<BR /><BR /></LI></OL></LI></OL><P>As this blog focuses on RAP, I'll skip the first option and let the integration gurus tackle that one. Let's take a closer look at the other two...</P><H2 id="toc-hId-1396440552">2.1 Extend SAP standard event</H2><P>If we found a suitable SAP standard RAP BO event and all we want is to add a few filter fields, we can do that with what is called Derived Events. Please refer to this page for details: <A href="https://help.sap.com/docs/abap-cloud/abap-rap/derived-business-events?version=s4hana_cloud" target="_blank" rel="noopener noreferrer">Derived Business Events | SAP Help Portal</A></P><P>For my showcase I'll be using <STRONG>R_SalesOrderTP~Changed</STRONG> event. First of, we need to check if the behavior definition of the BO allows extensions. Open it and check for the word "<FONT color="#FF6600"><STRONG>extensible</STRONG></FONT>" somewhere at the beginning of the definition + on the entity which has the event (so we need <U><STRONG>two</STRONG></U> <FONT color="#FF6600"><STRONG>extensible</STRONG></FONT>). </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_0-1770118376066.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368508i197CA85BDC2C2AC5/image-size/large?v=v2&px=999" role="button" title="mlauber_0-1770118376066.png" alt="mlauber_0-1770118376066.png" /></span></P><P>If it's there, we can proceed. Next we can also check the event itself and the payload (if no <FONT color="#FF6600"><STRONG>parameter</STRONG> </FONT>statement is written there, the payload is the key field(s) of the BO alone).</P><H3 id="toc-hId-1329009766">2.1.1 Create derived event payload with filter fields</H3><P>Before we extend the behavior, we need a custom payload that includes our filter fields. Create a new data definition root entity and define your custom payload. For example:</P><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Sales Ord. ext. event for derived event'
define root view entity ZP_SalesOrder_EventExt as select from I_SalesOrder
{
key SalesOrder,
.context.attribute: 'xsapordtype'
SalesOrderType,
.context.attribute: 'xsapslsorg'
SalesOrganization,
.context.attribute: 'xsapbillplc'
_BillingPlan.BillingPlanCategory,
DistributionChannel,
OrganizationDivision,
SoldToParty,
CustomerGroup,
ShippingCondition,
IncotermsClassification,
OverallSDProcessStatus
}</code></pre><P>Few points:</P><UL><LI>Key fields must match the RAP BO you are extending</LI><LI>You can access fields just like the standard RAP BO and also associated fields (I showcase this with BillingPlanCategory above). Note, we focus only flat structures, so the associated field needs to be 1:1 (for deep structures, please refer to chapter 3).</LI><LI>With above, we created exactly 3 filter fields: Sales Order Type, Sales Organization, and Billing Plan Category. Filters must have the annotation "<STRONG>Event.context.attribute</STRONG>" and <U>must start with</U> "<STRONG>xsap</STRONG>"!</LI></UL><H3 id="toc-hId-1132496261">2.1.2 Extend standard RAP BO behavior to create a derived event (with our custom payload)</H3><P>Now we are ready to extend the behavior definition as per usual practice: find/display it in the project explorer - right click - New Behavior Extension. Here type out your derived event, for example:</P><pre class="lia-code-sample language-abap"><code>extension
//using interface i_salesordertp
;
extend behavior for SalesOrder {
managed event ZZChangedExtended on Changed parameter ZP_SalesOrder_EventExt;
}</code></pre><P>Few notes on the above:</P><UL><LI>First of I want to start with the <STRONG>interface</STRONG> commented away above. Bear with me, this is important to understand!<BR />In RAP it is always best to interact with RAP BOs via their interface, if there is one (not to be confused with a basic interface view, such as I_SalesOrder or I_Customer etc., which reads from the DB table). In the case of R_SalesOrderTP, it has a transactional interface called <STRONG>I_SalesOrderTP</STRONG>. This interface is meant as a stable "API" to interact with the BO, and is usually released with C1/C0 contracts for clean core compliance. So in truth, we should be using the interface as we are extending this BO, but as you see above, it's commented away. That is because we must, in this case. I_SalesOrderTP does not include any of the events, and because we need those, we cannot use the interface in this case. What this means is that my extension behavior definition, as of right now, must be saved as "<STRONG>Standard ABAP</STRONG>" and cannot be assigned to a package with an ABAP Cloud software component. HOWEVER, <U><STRONG>this is clean core compliant</STRONG></U>, because R_SalesOrderTP is released with a C0 contract for extension, thus allowing such extensions. The problem is that the syntax check for <STRONG>ABAP for Cloud Development</STRONG> only checks for C1 contracts (which is missing on R_SalesOrderTP behavior), which is why, as of right now, we have to save this as Standard ABAP, meaning a "level B" extension which is clean core compliant (it would have been "level C", if R_SalesOrderTP hadn't had the C0).</LI><LI>The rest is quite straight forward. We say which entity we are extending (<STRONG>SalesOrder</STRONG>, using the alias in the behavior definition) and we are stating the <STRONG>Changed</STRONG> event to be extended with <STRONG>ZZChangedExtended</STRONG> with our own payload we previously created.</LI></UL><H3 id="toc-hId-935982756">2.1.3 Create Event Binding for derived event</H3><P>Next up we need an Event Binding for our derived event. As a small side note: if you only intend to consume your own derived within your SAP system (the same system) and not send it out to an event broker, then you would not need an event binding.<BR />Create a new Event Binding object (Business Service - Event Binding or just search for event binding in the new ABAP object dialog) and add the event we just created to it:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_1-1770120045083.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368517iADDE8D17051D9C5B/image-size/large?v=v2&px=999" role="button" title="mlauber_1-1770120045083.png" alt="mlauber_1-1770120045083.png" /></span></P><P>Note that we of course refer to the SAP Standard RAP BO, which now includes our derived event thanks to the extension we just did.</P><H3 id="toc-hId-739469251">2.1.4 Configure Event Channel to include your derived event</H3><P>Lastly, to send our derived event to an event broker, we need to add it to our event channel. Assuming you already prepared an event channel (refer to my other blog linked above for more info on that), go to <STRONG>/n/IWXBE/CONFIG</STRONG>, select your event channel and go to <STRONG>Outbound Bindings</STRONG>.</P><P>Click the create button to add the event binding you just created. It could look something like this:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_2-1770120572456.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368521i9EAB0A3A0D0D0D9B/image-size/large?v=v2&px=999" role="button" title="mlauber_2-1770120572456.png" alt="mlauber_2-1770120572456.png" /></span></P><P>The above means that my Event Mesh on my BTP subaccount receives the SAP standard Sales Order Created event, and my own derived Sales Order Changed event.</P><P>And that's it: now we are ready for filtering or for simply getting the larger payload as per our derived event.</P><H3 id="toc-hId-542955746">2.1.5 Adding Filters</H3><P>In the same location as we were (/n/IWXBE/CONFIG -> Event Channel -> Outbound Bindings) click on the button <STRONG>Filters</STRONG> at the top. Open up the folder <STRONG>Outbound Bindings</STRONG> for your event channel and click on your derived event. Clicking on the plus-button shows all available filter fields, in this example:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_3-1770120808327.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368528iFC46CE4591114DC4/image-size/medium?v=v2&px=400" role="button" title="mlauber_3-1770120808327.png" alt="mlauber_3-1770120808327.png" /></span></P><P>Create a filter, for example that only Sales Order Type "OR" should be sent to out:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_4-1770120857823.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368529i86EE30B213E86B56/image-size/large?v=v2&px=999" role="button" title="mlauber_4-1770120857823.png" alt="mlauber_4-1770120857823.png" /></span></P><H3 id="toc-hId-346442241">2.1.6 Subscribe to the event on your event broker</H3><P>To receive this derived event for example in Event Mesh on SAP BTP, you need of course a corresponding queue and then add the subscription for this new derived event. In my example:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_5-1770121089544.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368531i011AEB159CE6B0E4/image-size/medium?v=v2&px=400" role="button" title="mlauber_5-1770121089544.png" alt="mlauber_5-1770121089544.png" /></span></P><H3 id="toc-hId-149928736">2.1.6 Test example</H3><P>I changed a sales order in my system and saved. This now triggered my derived changed event, which I can see in the events monitoring transaction <STRONG>/n/IWXBE/EVENT_MONITOR</STRONG> (select event channel, click on Outbound Events, double-click on derived event)...</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="img1.png" style="width: 321px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368878i3A7336D1CA08EA56/image-size/medium?v=v2&px=400" role="button" title="img1.png" alt="img1.png" /></span></P><P>...and on SAP BTP Event Mesh where I added the subscription:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_7-1770121288238.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368533i6721A20876B09CD9/image-size/medium?v=v2&px=400" role="button" title="mlauber_7-1770121288238.png" alt="mlauber_7-1770121288238.png" /></span></P><P>Here we can only see what's sitting in the queue. So let me consume the message in the test tool to show the same payload as in our monitor:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="img2.png" style="width: 789px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368882i1C15646C036E5838/image-size/large?v=v2&px=999" role="button" title="img2.png" alt="img2.png" /></span></P><P>Awesome! We succeeded and this concludes the extend event option.</P><H2 id="toc-hId-171586869">2.2 Use custom event in combination with SAP Standard event</H2><P>This is an interesting one and in my experience comes with some confusion attached to it. I have heard sentences such as "But can't we just create a custom event instead of the standard one and use that?" And the simple answer to that is yes, but no <span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span>. Let me explain...</P><P>Now of course if we create our own, custom RAP BOs, we can add events to them. That is clear. And within that custom BO you decide when that event is fired. Clear and no problem. But this is all custom.</P><P>And now, if you want "your custom event" <STRONG>to be trigged <U>during</U> SAP standard processing</STRONG>, well no, SAP standard can't do that, as it does not know your custom event exists. And if you are thinking to use user exits or BAdIs to do this; think again, because it would be wrong to do so. User exits and BAdIs are called while the processing has not yet completed. Meaning at this point, in theory, something could still go wrong (no update in DB), but you already triggered your event. So, do not do this, ever! The point of the event framework is to inform about a state change. So you only want to do that, if the state change has actually occurred, meaning after the DB is fully updated.</P><P>So what else then, you wonder? That's where the SAP standard event comes in (which yes, is fired AFTER the state change occurred and all processing has completed). The SAP Standard event <U>will trigger</U>, and thus if you want more flexibility than just explored in the previous option with the extension of the SAP standard event, that's when we can try to combine standard with custom event.</P><P>Essentially, this is the pattern:</P><OL><LI>SAP standard process does something, which triggers an event for a certain object. This triggering happens at the exact time you want, but the SAP Standard event does not fulfill your requirement (and we can't / don't want to do a derived event)</LI><LI>You will create a custom event on a "dummy" RAP BO which includes the exact payload you need (flat structure for EM, it can be a deep one for AEM).</LI><LI>You will create a local event listener (within your SAP system) for the SAP standard event that triggers at the right moment. Within this local consumption you can now do any ABAP logic you may need. Complex filtering. Complex data collection (calling BAPIs or other things) etc.<BR />Once all your data validation and collection is done, you fill the payload format of your custom event and finally you trigger your custom event (with a slight workaround, as events can only be raised from with the RAP BO itself)</LI><LI>You only configure your custom event in the event channel for the event broker. The event arriving there is ready to be consumed with all needed fields and only events are that are really expected are arriving there.</LI></OL><P>Let's do this example now. We stick with <STRONG>R_SalesOrderTP</STRONG>, this time using <STRONG>Created</STRONG> as the SAP Standard event.</P><P>Let's assume I don't just want to send all sales order that are created. Sales order type filtering is not good enough. In fact, it matters whether a product is sold that has certain characteristics, for example. As a simplified example here, I will only check the product type of the product, but hopefully this gives you some ideas; we could check anything at this point.</P><H3 id="toc-hId--318329643">2.2.1 Create custom event</H3><P>Our custom event doesn't need much of a BO. Meaning we don't want to (re)create read/update/delete etc. functionality, but this is purely for defining how the event payload should look like and for triggering the custom event. </P><P>In my example I took it a step further: what if I create a <STRONG>generic "event forwarder"</STRONG>, that could potentially be used together with many SAP standard objects? Now, this isn't to say that I recommend this approach, in fact quite the opposite. And depending on your exact requirement, this may definitely the wrong approach. But I did this also in an effort to answer if this is at all feasible.</P><P>If having an event trigger with only key field information and then having a subsequent callback API later in the integration is a good pattern for you, then this could potentially help you, as you could reuse it for several use cases.</P><P>But, if instead you want something very specific, for example only forward my object under certain circumstances and including already all data needed, then of course it makes more sense to create a tailored custom event, with the exact payload of that object you want.</P><P>So please bear that in mind as we continue with this example. <STRONG>With this example I handle only a generic key-field based payload</STRONG>.</P><H4 id="toc-hId--808246155">2.2.1.1 Custom entity data definition</H4><P>We start of course with the data definition. Custom entity is in my opinion the best, as again we don't actually need any read or update functionality, but we simply describe our event payload at this point (and here you could have a large flat/deep structure):</P><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'Event Forwarder BO'
define root custom entity ZR_EventForwarder
{
key ObjectKey : abap.string;
key ObjectType : zevent_fwd_object;
}</code></pre><H4 id="toc-hId--1004759660">2.2.1.2 Custom entity behavior definition</H4><P>Next we need the behavior that will include our custom event:</P><pre class="lia-code-sample language-abap"><code>unmanaged implementation in class zbp_r_eventforwarder unique;
strict ( 2 );
define behavior for ZR_EventForwarder
lock master
authorization master ( instance )
{
field ( readonly ) ObjectKey, ObjectType;
event ForwardEvent;
}</code></pre><P>Finally, let ADT generate the BP implementation for you (we do not need to fill any of the methods but so it's properly created (again, we need no read/save methods etc.)). So I will not paste the whole Class/or Local Types.</P><P>Instead, what we need to do here is now offer an option to "raise" our custom event "<STRONG>ForwardEvent</STRONG>" from outside this BO. The "<FONT color="#3366FF"><STRONG>raise entity event</STRONG></FONT>" command is not allowed outside the RAP BO itself. So instead, we need to encapsulate it in a way that ABAP code from outside this behavior pool can call it. For this we need 2 things:</P><OL><LI>"Local event handler" (not actually inheriting anything => chose this to separate it from other, standard RAP BP behavior methods)</LI><LI>Method in the global class that can be called from other ABAP code</LI></OL><P>Let's start with the "local event handler". Within the section <STRONG>Local Types</STRONG> of your behavior implementation class, add something this:</P><pre class="lia-code-sample language-abap"><code>class lcl_event_handler definition friends zbp_r_eventforwarder.
public section.
class-methods on_forward_event importing it_events type zbp_r_eventforwarder=>tt_events.
endclass.
class lcl_event_handler implementation.
method on_forward_event.
raise entity event zr_eventforwarder~forwardevent from it_events.
endmethod.
endclass.</code></pre><P>Note the "<FONT color="#0000FF"><STRONG>friends</STRONG></FONT>" command in the class definition. This is needed to be able to access private/protected class variables from the behavior pool (raising our entity event).</P><P>And in the <STRONG>Global Class</STRONG>, we change it as follow (full code copied):</P><pre class="lia-code-sample language-abap"><code>class zbp_r_eventforwarder definition public abstract final for behavior of zr_eventforwarder.
types tt_events type table for event zr_eventforwarder~forwardevent.
public section.
constants:
co_type_salesorder type zevent_fwd_object value 'SALESORDER'.
class-methods raise_forward_event
importing it_events type tt_events.
endclass.
class zbp_r_eventforwarder implementation.
method raise_forward_event.
" tell RAP framework that we are in a SAVE sequence (otherwise it thinks
" we are in the middle of a MODIFY)
cl_abap_tx=>save( ).
" trigger event (only allowed during SAVE)
lcl_event_handler=>on_forward_event( it_events ).
endmethod.
endclass.</code></pre><P>We did 3 main things: a global type for the event payload table, a constant to distinguish different types of RAP BO that I mean to handle with my generic one (right now only one) and, most importantly, a global class method that can be called from other ABAP code.</P><H4 id="toc-hId--1201273165">2.2.1.3 Event Binding</H4><P>As before, we need an event binding if we want to forward this to an event broker:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_9-1770124792302.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368569iA7F765998E574E12/image-size/large?v=v2&px=999" role="button" title="mlauber_9-1770124792302.png" alt="mlauber_9-1770124792302.png" /></span></P><P>(Namespace, object type etc. can be freely chosen.)</P><P>And that's all for our custom event. Remember that the only purpose of this custom event is to offer a way to define the payload and to trigger it. Any functionality, such as filtering, complex validation or data selection etc. we do when the real SAP standard event is triggered. Meaning in the local consumption. </P><H3 id="toc-hId--1104383663">2.2.2 Local consumption of SAP Standard event</H3><P>Now I won't go into step-by-step on this one, as I have done this already on the above linked blog post of mine. Please check there if the below steps are not enough for you.</P><P>I have an ABAP Class, abstract, final with the "<STRONG><FONT color="#3366FF">for events of</FONT></STRONG>" functionality, where once again we must type R_SalesOrderTP here (and not I_SalesOrderTP, which would have been the preferred option). This means my class has to be again saved as "Standard ABAP" and cannot be in an ABAP for Cloud Development package. But this is clean core compliant, as explained above.</P><P>In Local Types I have my local class that inherits from <STRONG>cl_abap_behavior_event_handler</STRONG> and I add a method for the Created event:</P><pre class="lia-code-sample language-abap"><code>class lcl_event_cons definition inheriting from cl_abap_behavior_event_handler.
private section.
methods:
consume_created for entity event instances for salesorder~created.
endclass.</code></pre><P>And here the implementation of that method (we'll go through it one by one below):</P><pre class="lia-code-sample language-abap"><code> data: lt_fwd_event type zbp_r_eventforwarder=>tt_events.
" go through RAP BO entity instances that triggerd the event
" (should only be 1 as we listend to sales order (header) created)
loop at instances into data(instance).
" get data needed for complex filtering
select salesorderitem, product, \_product-producttype
from i_salesorderitem
where salesorder = @instance-salesorder
into table (lt_items).
" check if sales order should be handled (forwarded to event broker)
if line_exists( lt_items[ producttype = 'HAWA' ] ).
" this sales order is now filtered OK and will be added to the forwarding instances
append initial line to lt_fwd_event assigning field-symbol(<fs_event>).
<fs_event> = value #( objectkey = instance-salesorder
objecttype = zbp_r_eventforwarder=>co_type_salesorder ).
else.
continue. " we are not interested in this Sales Order
endif.
endloop.
" now that we checked all instances, only those that we filtered will be forwarded
if lt_fwd_event is not initial.
zbp_r_eventforwarder=>raise_forward_event( lt_fwd_event ).
endif.</code></pre><UL><LI>We create an internal table of the payload type that is the custom event (we created a global type in the behavior definition)</LI><LI>We loop through all instances that were sent by the SAP standard event (since this is a sales order (header), this will only ever include 1)</LI><LI>As we loop, we select some additional data to do "some complex logic" for checking if this sales order should be forwarded or filtered out.</LI><LI>Once all requirements are met for forwarding the sales order, we fill the custom event payload table.</LI><LI>When the looping is done, we check if any sales orders remained (if we have any custom event payload) and if yes, we now call the method we offered on the custom event RAP BO behavior as global class method and give it the payload we just filled.</LI></UL><P> And that's all <span class="lia-unicode-emoji" title=":astonished_face:">😲</span><span class="lia-unicode-emoji" title=":grinning_face:">😀</span></P><H3 id="toc-hId--1300897168">2.2.3 Finishing</H3><P>As before, we need to configure our custom event (binding) in the event channel in order to forward it to the event broker:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_10-1770125042635.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368582iD3055B5DF16B25C3/image-size/large?v=v2&px=999" role="button" title="mlauber_10-1770125042635.png" alt="mlauber_10-1770125042635.png" /></span></P><P>On the event broker, we need to subscribe to that topic, to receive it there:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mlauber_12-1770125246503.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368585iCBCED5DFB3A60DDE/image-size/medium?v=v2&px=400" role="button" title="mlauber_12-1770125246503.png" alt="mlauber_12-1770125246503.png" /></span></P><P>To summarize, this is what will happen:</P><OL><LI>A user creates any sales order</LI><LI>R_SalesOrderTP-Created is triggered</LI><LI>Our local consumption of the SAP standard event is called: our local consumption checks if the sales order has any items with products of product type HAWA. If yes, we add it to be forwarded. If no, we disregard it.</LI><LI>If we had any sales order to forward, the ZR_EventForwarder behavior is called via workaround (a little bit nasty by just calling the global class but I could not think of any other way. For example we can't use an action, as actions are invoked via EML MODIFY, which in turn does not allow for RAISE EVENT). This triggers the ZR_EventForwarder-EventForwarded event with our payload</LI><LI>The custom event is forwarded to event broker</LI></OL><H3 id="toc-hId--1497410673">2.2.4 Testing</H3><P>Let's test this. I create a new sales order and I include 1 item that has a product of type HAWA. Meaning my filtering will allow this sales order and eventually trigger my custom event. </P><P>Let's see what the event monitor says:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="img3.png" style="width: 369px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368883i54C7B49E5FC7E40A/image-size/medium?v=v2&px=400" role="button" title="img3.png" alt="img3.png" /></span></P><P>And consuming this message in BTP Event Mesh:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="img4.png" style="width: 780px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368884i5357FD956B2A568C/image-size/large?v=v2&px=999" role="button" title="img4.png" alt="img4.png" /></span></P><H1 id="toc-hId--1107118164">3 I want a larger payload</H1><P>This is without a doubt the 2nd most discussed topic when talking event based integrations. In order to avoid callback APIs, maybe this is the way to go for you. As of right now, SAP Standard delivers notification events only, meaning small payloads to allow for the creation of fast, simple, integrations that can be easily reused.</P><P>You may already noticed that we already covered this in chapter 2. Both when extending the SAP standard event or when creating a custom event to work in combination with standard: I showcased how we can decide our own payload. So far I have only mentioned <STRONG>flat structures</STRONG>, as that is the only type that is supported by Event Mesh on SAP BTP. If you have a need for <STRONG>deep structure payloads</STRONG>, you may want to consider to upgrade to Advanced Event Mesh instead. And instead of creating a brand new example, please check out this blog post by a colleague that goes into deep payload: <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/rap-business-events-with-advanced-event-mesh-3-creating-events-with-deep/ba-p/13914285" target="_self">RAP Events with AEM 3 - Creating Events with deep payload</A>.</P><H1 id="toc-hId--1303631669">Conclusion / Final Words</H1><P>I hope this blog post helps and gives some ideas how far you can take RAP BO events and influence your integration landscape, in a positive way (of course, that's the end goal).</P><P>Is there anything I've missed? Another requirement that you would like to solve with eventing? Or any other questions or comments/feedback? Let me know in the comments and let's see <span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span></P>2026-02-03T15:18:52.529000+01:00https://community.sap.com/t5/technology-blog-posts-by-members/ci-based-script-tester-amp-abap-groovy-ide/ba-p/14317804CI based script tester & ABAP groovy IDE2026-02-03T17:20:00.015000+01:00DamianKolasahttps://community.sap.com/t5/user/viewprofilepage/user-id/667350<H1 id="toc-hId-1659670631">Background</H1><P>This blog aims to recreate <A href="https://groovyide.com/cpi" target="_self" rel="nofollow noopener noreferrer">groovyIDE</A> using tools and platforms that every SAP developer should have access to.<BR />My goal was to avoid local development (using IntelliJ or Eclipse), as setting up such an environment is often difficult due to employer restrictions.</P><H1 id="toc-hId-1463157126">What do you need?</H1><P>To pull this off, you need:</P><UL><LI><P>Developer access to any Cloud Integration (CI) tenant<BR />(I recommend a separate tenant, ideally DEMO or TRIAL)</P></LI><LI><P>Developer access to an ABAP system that can connect to CI</P></LI></UL><P>Nice to have:</P><UL><LI><P>abapGit – as there is a <A href="https://github.com/devstylator/abapGroovyEditor" target="_self" rel="nofollow noopener noreferrer">repository</A> with the backend report</P></LI></UL><H1 id="toc-hId-1266643621">Setup</H1><H2 id="toc-hId-1199212835">Cloud integration</H2><P>Cloud Integration is used as the execution engine. In practice, this is a CI-based IDE exposed as a REST service. I would like to thank <A href="https://community.sap.com/t5/user/viewprofilepage/user-id/38272" target="_self">Vadim Klimov</A> for <A href="https://community.sap.com/t5/technology-blog-posts-by-members/rapid-groovy-scripting-in-cpi-dynamic-loading-and-execution-of-script-code/ba-p/13409607" target="_self">exploring this idea</A>. His blog (and the unavailability of groovyIDE) inspired me to create this solution. At its core, this is a single iFlow with a few steps. It uses GroovyShell to execute a script passed in the request payload.</P><H4 id="toc-hId-1260864768">Integration flow</H4><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="DamianKolasa_0-1769781434648.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367389iC18BB337E09FA3FB/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="DamianKolasa_0-1769781434648.png" alt="DamianKolasa_0-1769781434648.png" /></span></P><P>As you can see, the iFlow is simple and straightforward. It performs the following steps:</P><OL><LI>Decodes the payload, script, headers, and properties from the request</LI><LI>Dynamically executes the Groovy script</LI><LI>Creates a well-formatted JSON response, encoding all data using Base64</LI></OL><P>There is also an exception subprocess used to catch Groovy execution errors and return them in a structured JSON format.</P><H5 id="toc-hId-1193433982">Request</H5><P>The interface accepts a JSON payload with four parameters, all Base64-encoded:</P><pre class="lia-code-sample language-json"><code>{
"inputScript": "<base64encoded>",
"inputPayload": "<base64encoded>",
"inputParams": "<base64encoded>",
"inputHdrs": "<base64encoded>"
}</code></pre><P>After decoding, parameters (properties) and headers follow this format:</P><P class="lia-align-center" style="text-align: center;"><STRONG>Name=Value;Name2=Value2;...</STRONG></P><P>Cloud Integration encodes them in the same way in the final response (both in success and error cases).</P><H5 id="toc-hId-996920477">Decoder</H5><pre class="lia-code-sample language-java"><code>import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.json.JsonSlurper;
Message processData(Message message) {
def body = message.getBody(java.io.Reader)
def inputJSON = new JsonSlurper().parse(body)
String inputHdrs = inputJSON.inputHdrs
if(inputHdrs ){
byte[] decodedHdrs = inputHdrs.decodeBase64()
inputHdrs = new String(decodedHdrs)
inputHdrs.split(';').each{
def param_val_pair = it.split('=')
message.setHeader(param_val_pair[0],param_val_pair[1])
}
}
String inputParams = inputJSON.inputParams
if(inputParams){
byte[] decodedParams = inputParams.decodeBase64()
inputParams = new String(decodedParams)
inputParams.split(';').each{
def param_val_pair = it.split('=')
message.setProperty(param_val_pair[0],param_val_pair[1])
}
}
String inputScript = inputJSON.inputScript
if(inputScript){
message.setProperty("inputScript",inputScript)
}
String inputPayload = inputJSON.inputPayload
if(inputPayload){
byte[] decodedPayload = inputPayload.decodeBase64()
inputPayload = new String(decodedPayload)
message.setBody(inputPayload)
}
return message
}</code></pre><P>The decoder script processes headers and properties and sets them for the current message processing. The payload is decoded and set as plain text (String) in the message body. The actual Groovy script is stored as a separate property named "inputScript" and is later used in the execution step.</P><H5 id="toc-hId-800406972">Script execution</H5><pre class="lia-code-sample language-java"><code>import com.sap.gateway.ip.core.customdev.util.Message
import java.io.StringWriter
import java.io.PrintWriter
Message processData(Message message) {
//Get script
String inputPayload = message.getProperty("inputScript")
byte[] decodedPayload = inputPayload.decodeBase64()
String scriptCode = new String(decodedPayload, "UTF-8")
//Setup output capture
StringWriter logWriter = new StringWriter()
PrintWriter printWriter = new PrintWriter(logWriter)
//Create Binding and inject 'out' for println support
Binding binding = new Binding()
binding.setVariable("out", printWriter)
//Initialize shell
GroovyShell shell = new GroovyShell(binding)
Script script = shell.parse(scriptCode)
//call script
message = script.processData(message)
//Save logs to property
printWriter.flush()
message.setProperty("consoleLog", logWriter.toString())
return message
}</code></pre><P>The main difference between this script and the one provided in Vadim’s blog is the use of an additional binding with a PrintWriter object. This allows capturing console output (println statements) and returning it to the caller as part of the response.</P><H5 id="toc-hId-603893467">Wrapper</H5><pre class="lia-code-sample language-java"><code>import com.sap.gateway.ip.core.customdev.util.Message
Message processData(Message message) {
def consoleLog = message.getProperties().get("consoleLog") as String
message.setProperty("consoleLog", null)
def mapProperties = message.getProperties();
def mapHeaders = message.getHeaders();
def body = message.getBody(java.lang.String) as String;
String Pbody = ""
String Hbody = ""
//encode props and hdrs to name=value; format
mapProperties.each { it -> Pbody += "$it.key = $it.value;" }
mapHeaders.each { it -> Hbody += "$it.key = $it.value;" }
def builderJSON = new groovy.json.JsonBuilder()
builderJSON{
properties(Pbody.bytes.encodeBase64().toString())
headers(Hbody.bytes.encodeBase64().toString())
payload(body.bytes.encodeBase64().toString())
console(consoleLog.bytes.encodeBase64().toString())
}
message.setBody(builderJSON.toPrettyString())
return message
}</code></pre><P>The wrapper executes the decoded Groovy script and captures console output. After execution, all logs are stored in a message property and later included in the JSON response.</P><H5 id="toc-hId-407379962">Error Handler</H5><pre class="lia-code-sample language-java"><code>import com.sap.gateway.ip.core.customdev.util.Message;
def Message processData(Message message) {
def mapProperties = message.getProperties();
def body = message.getBody(java.lang.String) as String;
String Pbody = ""
String Hbody = ""
mapProperties.each { it -> Pbody += "$it.key = $it.value; \n" }
def ex = mapProperties.get("CamelExceptionCaught");
def mapHeaders = message.getHeaders();
mapHeaders.each { it -> Hbody += "$it.key = $it.value; \n" }
def builderJSON = new groovy.json.JsonBuilder()
builderJSON{
properties(Pbody.bytes.encodeBase64().toString())
headers(Hbody.bytes.encodeBase64().toString())
payload(body.bytes.encodeBase64().toString())
error(ex.message.bytes.encodeBase64().toString())
}
message.setHeader("CamelHttpResponseCode", "400");
message.setBody(builderJSON.toPrettyString());
return message;
}</code></pre><P>The error handler is very similar to the wrapper but additionally captures execution exceptions and includes them in the response. This is important during testing, as errors such as missing variables or null references are common. The main idea of this tool is that any Groovy-related error is returned to the caller. To distinguish between script errors and unexpected system failures (HTTP 500), the service returns HTTP 400 for Groovy execution errors. This makes sense, as the script itself is part of the request.</P><H2 id="toc-hId-170872657">ABAP</H2><P>There is not much logic on the ABAP side: a table, a data element, and a report.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="DamianKolasa_1-1769781876826.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367394i591EE27C9FFB60C1/image-size/medium?v=v2&px=400" role="button" title="DamianKolasa_1-1769781876826.png" alt="DamianKolasa_1-1769781876826.png" /></span></P><P>The table ZSAPERGROOVYTST serves as a test case repository. In the current version, it stores only a cache – the last modified script, payload, and input properties.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="DamianKolasa_2-1769782115545.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367395i33F0EEEA89675744/image-size/large?v=v2&px=999" role="button" title="DamianKolasa_2-1769782115545.png" alt="DamianKolasa_2-1769782115545.png" /></span></P><P>All text inputs are stored as Base64-encoded strings. Headers and properties are stored as name=value pairs, following the same format used by Cloud Integration.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="DamianKolasa_3-1769782245582.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367397i9AFDE14DE75D8562/image-size/large?v=v2&px=999" role="button" title="DamianKolasa_3-1769782245582.png" alt="DamianKolasa_3-1769782245582.png" /></span></P><P>When the program is cancelled, it closes without updating the cache table. When exited normally, the current editor and ALV content is stored as a TMP record for the current user and loaded the next time the IDE is opened.</P><P>I will not go into ABAP-specific details here. You can check the Git repository or import the objects into your system and test the solution yourself.</P><H2 id="toc-hId--25640848">Connection</H2><P>Connectivity is based on an RFC destination (type G) configured in transaction SM59. The destination name is stored in lcl_groovy=>cv_destination and defaults to "CPI_GROOVY". </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="DamianKolasa_0-1769782673129.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367400i6A609C2684E10777/image-size/medium?v=v2&px=400" role="button" title="DamianKolasa_0-1769782673129.png" alt="DamianKolasa_0-1769782673129.png" /></span></P><P>You can adjust it to your needs in method "call_script".</P><pre class="lia-code-sample language-abap"><code> METHOD call_script.
cl_http_client=>create_by_destination( EXPORTING destination = cv_destination
IMPORTING client = DATA(lo_http) ).
DATA(ls_current_screen_data) = me->get_screen_data( ).
DATA(lv_payload) =
|\{| &&
|"inputScript":"{ ls_current_screen_data-script }",| &&
|"inputPayload":"{ ls_current_screen_data-payload }",| &&
|"inputParams":"{ ls_current_screen_data-props }",| &&
|"inputHdrs":"{ ls_current_screen_data-hdrs }"| &&
|\}|.
lo_http->request->set_cdata( lv_payload ).
lo_http->send( ).
lo_http->receive( ).
lo_http->response->get_status( IMPORTING code = DATA(lv_status_code) ).
IF lv_status_code EQ 500.
MESSAGE 'Internal server error occured' TYPE 'I' DISPLAY LIKE 'E'.
ELSE.
me->parse_service_call_response( iv_response = lo_http->response->get_cdata( ) iv_code = lv_status_code ).
ENDIF.
ENDMETHOD.</code></pre><H1 id="toc-hId-71248654">Testing</H1><P>Let’s start with the default script. It simply rewrites the input to the output and adds a console log line: "test1".</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="test_groovy_1.gif" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367404iE4E5FE69FA38383E/image-size/large?v=v2&px=999" role="button" title="test_groovy_1.gif" alt="test_groovy_1.gif" /></span></P><P>Now let’s break something – for example, by dividing by zero.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="test_groovy_2.gif" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367405i7D33254FEB5B88A8/image-size/large?v=v2&px=999" role="button" title="test_groovy_2.gif" alt="test_groovy_2.gif" /></span></P><P>As expected, the error is visible in the console output:</P><P><EM>"java.lang.Exception: java.lang.ArithmeticException: Division by zero @ line 7 in ExecuteScript.groovy".</EM></P><P>This demonstrates the usage of JsonSlurper and JsonBuilder, as well as property and header handling.</P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="test_groovy_3.gif" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/367408i0604D5DC116DC289/image-size/large?v=v2&px=999" role="button" title="test_groovy_3.gif" alt="test_groovy_3.gif" /></span></SPAN></P><H1 id="toc-hId--125264851">Security</H1><P>This solution executes dynamic Groovy code using GroovyShell and therefore must be treated as a development and testing tool only. Access to the integration flow should be restricted, and the endpoint must not be connected to productive systems. The script executes with the runtime permissions of Cloud Integration and is not sandboxed. For this reason, the tool should be deployed only in isolated CI tenants (for example TRIAL tenant). <STRONG><BR /></STRONG></P><H1 id="toc-hId--321778356">External links</H1><UL><LI>ABAP repo: <A href="https://github.com/devstylator/abapGroovyEditor" target="_blank" rel="nofollow noopener noreferrer">https://github.com/devstylator/abapGroovyEditor</A></LI><LI>groovyIDE: <A href="https://groovyide.com/cpi" target="_blank" rel="nofollow noopener noreferrer">https://groovyide.com/cpi</A></LI><LI>Vadim's blog post: <A href="https://community.sap.com/t5/technology-blog-posts-by-members/rapid-groovy-scripting-in-cpi-dynamic-loading-and-execution-of-script-code/ba-p/13409607" target="_blank">https://community.sap.com/t5/technology-blog-posts-by-members/rapid-groovy-scripting-in-cpi-dynamic-loading-and-execution-of-script-code/ba-p/13409607</A></LI></UL><P> </P><P> </P>2026-02-03T17:20:00.015000+01:00https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018How to extend the program SAPF124 of F.13 to retrieve its results2026-02-03T21:53:36.070000+01:00Sandra_Rossihttps://community.sap.com/t5/user/viewprofilepage/user-id/145194<P><ul =""><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-1918573191">Introduction</a></li><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-1722059686">Selection screen parameters and result example</a></li><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-1525546181">SAPF124 logic</a></li><li style="list-style-type:disc; margin-left:45px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-1458115395">Subroutine ECHTLAUF with I_KOART being 'D', 'K' or 'S'</a></li><li style="list-style-type:disc; margin-left:45px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-1261601890">Subroutine SPERREN_KONTO (lock)</a></li><li style="list-style-type:disc; margin-left:45px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-1065088385">Subroutine AUSGLEICH with I_SUM = sum of amounts of all documents with the same clearing criteria</a></li><li style="list-style-type:disc; margin-left:45px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-868574880">Subroutine ACC_APPEND_DATA</a></li><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-542978656">Enhancements</a></li><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-346465151">Basic code to run SAPF124</a></li><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId-149951646">ABAP type for the collected data</a></li><li style="list-style-type:disc; margin-left:30px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/how-to-extend-the-program-sapf124-of-f-13-to-retrieve-its-results/ba-p/14321018#toc-hId--121793228">SQL showing a subset of all possible test data</a></li></ul></P><H3 id="toc-hId-1918573191">Introduction</H3><P>F.13 is the transaction to clear the open items automatically. For functional information, see <A href="https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/651d8af3ea974ad1a4d74449122c620e/8db4855746fa0322e10000000a44147b.html?locale=en-US" target="_blank" rel="noopener noreferrer">Automatic Clearing | SAP Help Portal</A>.</P><P>The result is a spool which contains a log with all results.</P><P>To analyze the results by program, it's easier to create a few enhancements to F.13 (program SAPF124) to retrieve the log as several internal tables, rather than decoding the spool (called "ABAP List" hereafter), because the latter is often subject to changes after an upgrade.</P><P>Note that some people recommend in the forum to use POSTING_INTERFACE_CLEARING but I couldn't find any official information saying that it's allowed for automating F.13.</P><P>Before creating the enhancements to the program SAPF124, it's important to understand the logic of the program. Also, the names of some of the selection screen parameters and an example of the output ABAP List are useful.</P><P>Warning: in this blog post, <STRONG>I don't post the code I used</STRONG>, but I explain which subroutines can be enhanced.</P><P>My SAP system is S/4HANA 2023 FPS01.</P><P> </P><H3 id="toc-hId-1722059686">Selection screen parameters and result example</H3><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Sandra_Rossi_0-1770149514450.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368680i30DA51AD07BEA069/image-size/large?v=v2&px=999" role="button" title="Sandra_Rossi_0-1770149514450.png" alt="Sandra_Rossi_0-1770149514450.png" /></span></P><P>Example of the output ABAP List. Here F.13 ran in test mode so there's no clearing document created (so, the number remains blank). We can see the list of cleared documents at the top, then the additional log and the error log at the bottom.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Sandra_Rossi_1-1770150091342.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368681i7755F8C59F88F6EA/image-size/large?v=v2&px=999" role="button" title="Sandra_Rossi_1-1770150091342.png" alt="Sandra_Rossi_1-1770150091342.png" /></span></P><P> </P><H3 id="toc-hId-1525546181">SAPF124 logic</H3><P>AT SELECTION-SCREEN:</P><UL><LI>Call the subroutine CHECK_ECHTL<UL><LI>In productive mode (X_TESTL not checked), it displays the warning FG013 “This program run is a production run” as a popup.</LI><LI>It also calculates X_ECHTL = “X” or “ ”.<UL><LI>“X” means that the execution is in productive mode (X_TESTL not checked).</LI></UL></LI></UL></LI></UL><P> </P><P>START-OF-SELECTION:</P><UL><LI>Call the subroutine KONTOTABELLEN_FUELLEN</LI><UL><LI>Fills the 3 lists of objects to process: customers (from the table <STRONG>BSID</STRONG> to the internal table <STRONG>TDEBI</STRONG>), suppliers (from the table <STRONG>BSIK</STRONG> to the internal table <STRONG>TKREDI</STRONG>) and accounts (from the table <STRONG>SKB1</STRONG> to the internal table <STRONG>TSAKO</STRONG>), according to the selection screen parameters.</LI></UL><LI>Logic for the 3 lists</LI><UL><LI>Call the subroutine DEBI_VERARBEITEN if the "Customers" box is checked<UL><LI>LOOP AT <STRONG>TDEBI</STRONG> (customers)<BR /><UL><LI>Call the subroutine <STRONG>ECHTLAUF</STRONG> or TESTLAUF (*) with <STRONG>KOART = 'D'</STRONG></LI></UL></LI></UL></LI><LI>Call the subroutine KREDI_VERARBEITEN if the "Suppliers" box is checked<UL><LI>LOOP AT <STRONG>TKREDI</STRONG> (suppliers)<UL><LI>Call the subroutine <STRONG>ECHTLAUF</STRONG> or TESTLAUF with <STRONG>KOART = 'K'</STRONG><UL><LI>(ECHTLAUF or TESTLAUF based on the same test as for customers)</LI></UL></LI></UL></LI></UL></LI></UL><UL><LI>Call the subroutine SAKO_VERARBEITEN if the "Accounts" box is checked<UL><LI>LOOP AT <STRONG>TSAKO</STRONG> (accounts)<UL><LI>Call the subroutine <STRONG>ECHTLAUF</STRONG> or TESTLAUF with <STRONG>KOART = 'S'</STRONG><UL><LI>(ECHTLAUF or TESTLAUF based on the same test as for customers)</LI></UL></LI></UL></LI></UL></LI></UL></UL><P>(*) ECHTLAUF is called if the run is in productive mode or with tolerance included. Otherwise TESTLAUF is called, which has the same logic as ECHTLAUF except that the lock isn't done.</P><P> </P><P>Event END-OF-SELECTION:</P><UL><LI>Call the subroutine ACC_AUSGABE_ADDITION_LOG</LI><UL><LI>Write the internal table <STRONG>IPROT</STRONG> (additional log) to the ABAP List.</LI></UL><LI>IF X_FEHLER = 'X':<UL><LI>Call the subroutine ACC_AUSGABE_FAULT_LOG<UL><LI>It writes the internal table <STRONG>FEHLPROT</STRONG> (error messages) to the ABAP List.</LI></UL></LI></UL></LI></UL><P> </P><H4 id="toc-hId-1458115395">Subroutine ECHTLAUF with I_KOART being 'D', 'K' or 'S'</H4><P>For information, depending on I_KOART being 'D', 'K' or 'S', the data will be taken respectively from TDEBI, TKREDI or TSAKO.</P><P>Reminder: ECHTLAUF is called only if the run is in productive mode or with tolerance included. Otherwise TESTLAUF is called, which has the same logic as ECHTLAUF except that the lock isn't done (SPERREN_KONTO is not called).</P><P>Logic:</P><UL><LI>Call the subroutine <STRONG>SPERREN_KONTO</STRONG> to lock the object to process</LI><LI>Call the subroutine INDEXTABELLEN_FUELLEN<UL><LI>Call the subroutine READ_BSID or READ_BSIK or READ_BSIS to build the groups of clearing criteria XBSIDGR or XBSIKGR or XBSISGR, depending on I_KOART = 'D', 'K' or 'S' respectively. The criteria (list of fields) are defined in the SAP Customizing Implementation Guide (SPRO) -> Financial Accounting -> General Ledger Accounting -> Business Transactions -> Open Item Clearing -> Prepare Automatic Clearing (or SM30 V_TF123). The subroutine XBSID_XBSIDGR_FUELLEN or XBSIK_XBSIKGR_FUELLEN or XBSIS_XBSISGR_FUELLEN is called, which fills these internal tables:<UL><LI>APPEND XBSID or XBSIK or XBSIS depending on I_KOART = 'D', 'K' or 'S' respectively.</LI><LI>COLLECT XBSIDGR or XBSIKGR or XBSISGR depending on I_KOART = 'D', 'K' or 'S' respectively:<UL><LI>Each line is a group of clearing criteria for which FI documents may be cleared altogether.</LI><LI>The field <STRONG>XBSIDGR-BET_BW or XBSIKGR-BET_BW or XBSISGR-BET_TW</STRONG> contains the sum of FI documents which can be zero (they can be cleared) or another number (they cannot be cleared).</LI></UL></LI></UL></LI><LI>LOOP AT XBSIDGR or XBSIKGR or XBSISGR depending on I_KOART = 'D', 'K' or 'S' respectively<UL><LI>Call subroutine <STRONG>AUSGLEICH</STRONG> USING <STRONG>I_SUM = XBSIDGR-BET_BW or XBSIKGR-BET_BW or XBSISGR-BET_TW</STRONG></LI></UL></LI></UL></LI></UL><P> </P><H4 id="toc-hId-1261601890">Subroutine SPERREN_KONTO (lock)</H4><UL><LI><SPAN>If KOART = 'D', call ENQUEUE_EFKNB1A with tdebi-bukrs, tdebi-kunnr.</SPAN></LI><LI><SPAN>If KOART = 'K', call ENQUEUE_EFLFB1A with tkredi-bukrs, tkredi-lifnr.</SPAN></LI><LI><SPAN>If KOART = 'S', call ENQUEUE_EFSKB1A with tsako-bukrs, tsako-hkont, tsako-hbkid, tsako-hktid.</SPAN></LI></UL><P> </P><H4 id="toc-hId-1065088385">Subroutine AUSGLEICH with I_SUM = sum of amounts of all documents with the same clearing criteria</H4><P>It checks if the clearing of one group of documents with the same clearing criteria is possible. If yes, it’s calling a given transaction code (whose code may vary) via Batch Input to create one clearing document.</P><P>The subroutine has the following logic:</P><UL><LI>Call the subroutine BELEGE_AUSGEBEN (collect the list of documents to be cleared)<UL><LI>Loop at all the lines of XBSID, XBSIK or XBSIS corresponding to the current grouping criteria XBSIDGR, XBSIKGR or XBSISGR depending on KOART = 'D', 'K' or 'S' respectively.</LI><UL><LI>Call the subroutine RECORD_DOCUMENT<UL><LI>APPEND GS_DLIST TO <STRONG>GT_DLIST</STRONG>. It's the list of FI documents corresponding to the current clearing criteria group.</LI></UL></LI></UL></UL></LI><LI>If I_SUM = 0 (the documents of the current group have a total amount of 0, so they can be cleared).<UL><LI>Call the subroutine AUGDT_PRUEFEN<UL><LI>Call the subroutine CALL_TRANSACTION if it's a productive run<UL><LI>Batch input CALL TRANSACTION FB1D, FB1K or FB1S/FB1SL depending on KOART = 'D', 'K' or 'S' respectively.</LI><LI>The batch input messages are stored into the internal table MESSTAB</LI><LI>Call the subroutine MESSTAB_AUSWERTEN<UL><LI>If MESSTAB contains the success message F5312 "Document & was posted in company code &", <STRONG>AUGBLNR</STRONG> (global variable) = MSGV1 (document number)</LI><LI>Call the subroutine RECORD_CLEARING_INFO with I_CHAR = 'AUGBL'<UL><LI>Call subroutine ACC_APPEND_DATA with parameters AUGBLNR, clearing date and ID_MESSAGE = ‘AUGBL’ to display the documents to be cleared and the clearing document created.</LI><LI>IMPORTANT: <STRONG>GT_DLIST</STRONG> is cleared (the list of documents to be cleared). <UL><LI>Call subroutine RECORD_CLEARING_INFO with I_CHAR = code expressing errors (‘NOCLEAR’, ‘NOTZERO’, etc.)</LI></UL></LI></UL></LI><LI>If X_FEHLER = 'X'.<UL><LI>Call subroutine MESSTAB_LESEN which feeds the internal table <STRONG>FEHLPROT</STRONG> (displayed error log) from <STRONG>MESSTAB</STRONG> (error messages from the batch input)</LI></UL></LI></UL></LI></UL></LI></UL></LI></UL></LI><LI>Else if clearing is permitted with tolerance<UL><LI>TODO</LI></UL></LI><LI>Else (if no clearing)</LI><UL><LI>Call subroutine ACC_APPEND_DATA with parameter ID_MESSAGE = ‘NOTZERO’.</LI><LI>If there’s some clearing tolerance, add the error to the internal table <STRONG>IPROT</STRONG> (additional log).</LI></UL></UL><P> </P><H4 id="toc-hId-868574880">Subroutine ACC_APPEND_DATA</H4><P>It receives the parameters:</P><UL><LI>ID_AUGBLNR = clearing document created</LI><LI>ID_AUGDT = clearing date</LI><LI>ID_MESSAGE = ‘AUGBL’ (clearing) or others (no clearing), etc.<UL><LI>AUGBL: The clearing has been done, i.e. the clearing document has been created, the global variable AUGBL contains this clearing document, the log contains F5312 (*).</LI><LI>NOTZERO: the clearing is not possible because the sum of amounts of the documents is not zero.</LI><LI>AUGDT: Test mode successful (in test mode, the F5312 and F5263 (*) messages are absent and there is no error).</LI><LI>NOCLEAR: The reconciliation document has failed (the F5312 (*) message is absent and no tolerance is requested or a tolerance is requested but F5263 is absent).</LI><LI>NOCLEARTOL: Failed (the F5312 (*) message is absent and a tolerance is requested and F5263 is present).</LI><LI>ENQ: failed because the object of the current clearing criteria could not be locked</LI><LI>Other values: Failed</LI><LI>(*) Batch Input may return one of the following messages:<UL><LI>F5312: "Document & was posted in company code &"</LI><LI>F5263: "The difference is too large for clearing"</LI></UL></LI></UL></LI></UL><P>This subroutine has the following logic:</P><UL><LI>Call the subroutine WRITE_LISTE if the output of cleared/clearing documents has been requested in the selection screen. This subroutine does:</LI><UL><LI>LOOP AT <STRONG>GT_DLIST</STRONG> INTO GS_DLIST (list of documents to be cleared)<UL><LI>The document is written to the ABAP List.</LI></UL></LI><LI>Call subroutine CHECK_SUMME<UL><LI>The clearing criteria are written to the ABAP List on one line, including the new clearing document if one has been created.</LI></UL></LI></UL><LI><STRONG>GT_DLIST</STRONG> is emptied (the list of documents to be cleared).</LI></UL><P> </P><H3 id="toc-hId-542978656">Enhancements</H3><P>The parameter X_FEHLER (to display error messages in the ABAP List) is absolutely necessary to run several SAPF124 subroutines which contain information about the cleared documents.</P><P>The following subroutines may be enhanced to obtain information about the cleared documents used and the clearing documents created:</P><UL><LI>Begin of <STRONG>CHECK_ECHTL</STRONG><UL><LI>In real mode, it displays the warning FG013 “This program run is a production run”.</LI><LI>It also calculates X_ECHTL = “X” or “ ”. “X” means that the execution is in real mode (case F.13 is not called in test mode i.e., checkbox X_TESTL = space/false).</LI><LI>This message is annoying if SAPF124 is called by a custom program in a loop.</LI><LI>Do this enhancement:<UL><LI>Keep calculating X_ECHTL = “X” or “ ” but don’t display the warning by using ABAP “RETURN” to not execute the standard code of the subroutine.</LI></UL></LI></UL></LI><LI>Begin of <STRONG>ACC_APPEND_DATA</STRONG><UL><LI>It’s called after the logic to create one clearing document, whatever it has succeeded (parameter ID_MESSAGE = ‘AUGBL’) or failed (other values).</LI><LI>Do this enhancement:<UL><LI>Collect the list of documents cleared (internal table GT_DLIST), the clearing status (ID_MESSAGE) and the clearing document created (ID_AUGBLNR). The clearing document will be empty if the creation failed.</LI></UL></LI></UL></LI><LI>Begin of <STRONG>MESSTAB_LESEN</STRONG><UL><LI>It’s called when the creation of the cleared document failed via Batch Input and it feeds the internal table FEHLPROT from MESSTAB (error messages from Batch Input).</LI><LI>Do this enhancement:<UL><LI>Collect the list of documents cleared (internal table GT_DLIST) and the error messages from the internal table FEHLPROT.</LI></UL></LI></UL></LI><LI>Begin of <STRONG>ACC_AUSGABE_FAULT_LOG</STRONG><UL><LI>It’s called at the end, but only if the selection screen option X_FEHLER was selected.</LI><LI>Do this enhancement:<UL><LI>Export the data previously collected by the enhancements to the ABAP memory (EXPORT TO MEMORY ID).</LI></UL></LI></UL></LI></UL><P> </P><H3 id="toc-hId-346465151">Basic code to run SAPF124</H3><P>Transaction F.13 starts SAPF124 with the SAP&F124 variant, so I'm doing the same thing. I haven't checked to see if there's a difference without the variant.</P><P>The actual content is obtained by reading the data collected by the enhancements in the ABAP memory (IMPORT FROM MEMORY ID).</P><pre class="lia-code-sample language-abap"><code>SUBMIT sapf124
USING SELECTION-SET 'SAP&F124'
WITH bukrx IN ir_bukrs " Company
WITH gjahx IN ir_gjahr " Year
WITH docnr IN ir_belnr " Document Number
WITH x_kunnr = iv_xkunnr " Check "Customers"
WITH kontd IN ir_kunnr " Customers
WITH x_lifnr = iv_xlifnr " Check "Suppliers"
WITH kontk IN ir_lifnr " Suppliers
WITH x_saknr = iv_xsaknr " Check "Accounts"
WITH konts IN ir_saknr " Accounts
WITH x_testl = iv_xtestl " Test mode
WITH xausbel = abap_true " Output the documents cleared
WITH xnausbel = abap_true " Output the documents not cleared
WITH x_fehler = abap_true " Output the error messages
EXPORTING LIST TO MEMORY " To not generate a spool
AND RETURN.</code></pre><P> </P><H3 id="toc-hId-149951646">ABAP type for the collected data</H3><P>In my final code, a variable of type TT_CLEARING_RESULT is exported by the enhancement to the ABAP memory, and imported after SUBMIT SAPF124, which is defined as follows:</P><pre class="lia-code-sample language-abap"><code> TYPES:
BEGIN OF ts_doc_item_to_be_cleared,
bukrs TYPE bseg-bukrs,
belnr TYPE bseg-belnr,
gjahr TYPE bseg-gjahr,
buzei TYPE bseg-buzei,
END OF ts_doc_item_to_be_cleared.
TYPES tt_doc_item_to_be_cleared TYPE STANDARD TABLE OF ts_doc_item_to_be_cleared WITH DEFAULT KEY.
TYPES:
BEGIN OF ts_clearing_doc_created,
bukrs TYPE bseg-bukrs,
belnr TYPE bseg-belnr,
gjahr TYPE bseg-gjahr,
END OF ty_ clearing_doc_created.
"! Batch Input errors
TYPES tt_journal_sapf124 TYPE STANDARD TABLE OF bdcmsgcoll WITH DEFAULT KEY.
TYPES:
BEGIN OF ts_clearing_result
s_clearing_doc_created TYPE ts_clearing_doc_created
t_doc_item_to_be_cleared TYPE tt_doc_item_to_be_cleared,
t_journal TYPE tt_journal_sapf124,
END OF ts_clearing_result.
TYPES tt_clearing_result TYPE STANDARD TABLE OF ts_clearing_result WITH DEFAULT KEY.</code></pre><P>Depending on the selection criteria when calling SAPF124, the result may contain many rows, some failing, others succeeding. For example, to clear 2 documents A 2024 and B 2025, which we know can be cleared, unfortunately the selection will be wide and there may be 4 documents selected: A 2024, A 2025, B 2024, B 2025.</P><P>In the result, there will likely be failures on A 2025 and B 2024, and a success for A 2024 and B 2025. Since we are only interested in the 2 documents A 2024 and B 2025, we must search the result for the row concerning them.</P><P>Example of collected data of type TT_CLEARING_RESULT :</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Sandra_Rossi_2-1770151477128.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368684i0823FE11133B1F5A/image-size/large?v=v2&px=999" role="button" title="Sandra_Rossi_2-1770151477128.png" alt="Sandra_Rossi_2-1770151477128.png" /></span></P><P>Only the 6th line shows a success, the clearing document 0900002549 has been created to clear the documents shown in the component T_DOC_ITEM_TO_BE_CLEARED:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Sandra_Rossi_3-1770151557413.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368685i8D7A859D94D7D915/image-size/medium?v=v2&px=400" role="button" title="Sandra_Rossi_3-1770151557413.png" alt="Sandra_Rossi_3-1770151557413.png" /></span></P><P> </P><H3 id="toc-hId--121793228">SQL showing a subset of all possible test data</H3><P>This query may be useful for developers who don't know FI and want to run F.13 with any existing test data, here it's returning document numbers from suppliers, without withholding tax, which can be cleared; you may need to adjust the clearing criteria according to your V_TF123 settings (in my case, grouping by GSBER, EBELN except for suppliers 6*):</P><pre class="lia-code-sample language-sql"><code>select bsik1.bukrs || ' ' Company, bsik1.lifnr || ' ' Supplier, bsik1.h_waers, bsik1.gsber, bsik1.ebeln || ' ' ebeln, bsik1.belnr || ' ' Document, bsik1.gjahr || ' ' Year, bsik1.shkzg, bsik1.wrbtr
from bseg bsik1, bkpf
where bkpf.mandt = bsik1.mandt
and bkpf.bukrs = bsik1.bukrs
and bkpf.belnr = bsik1.belnr
and bkpf.gjahr = bsik1.gjahr
and bsik1.mandt = '100'
and bsik1.umsks = ' '
and bsik1.xpypr = ' '
and bkpf.xstov = ' '
and bsik1.qsshb = 0 /* without withholding tax to simplify */
and bsik1.koart = 'K'
and bsik1.augbl = ''
and bsik1.h_bstat <> 'D'
and bsik1.h_bstat <> 'M'
and exists ( select bsik.bukrs, bsik.lifnr, bsik.h_waers, bsik.gsber, bsik.ebeln
from bseg bsik, bkpf
where bkpf.mandt = bsik.mandt
and bkpf.bukrs = bsik.bukrs
and bkpf.belnr = bsik.belnr
and bkpf.gjahr = bsik.gjahr
and bsik.bukrs = bsik1.bukrs
and bsik.lifnr = bsik1.lifnr
and bsik.h_waers = bsik1.h_waers
and bsik.gsber = bsik1.gsber
and bsik.ebeln = bsik1.ebeln
and bsik.umsks = ' '
and bsik.xpypr = ' '
and bkpf.xstov = ' '
and bsik.qsshb = 0 /* without withholding tax to simplify */
and bsik.koart = 'K'
and bsik.augbl = ''
and bsik.h_bstat <> 'D'
and bsik.h_bstat <> 'M'
and bsik.lifnr not between '6000000000' and '6999999999' /* criteria from V_TF123 */
group by bsik.bukrs, bsik.lifnr, bsik.h_waers, bsik.gsber, bsik.ebeln /* bukrs, lifnr, waers (waers to simplify) + criteria from V_TF123 */
having 0 = sum( case when bsik.shkzg = 'H' then - bsik.wrbtr else + bsik.wrbtr end )
)
order by bsik1.bukrs, bsik1.lifnr, bsik1.h_waers, bsik1.gsber, bsik1.ebeln, bsik1.belnr, bsik1.gjahr</code></pre><P> </P>2026-02-03T21:53:36.070000+01:00https://community.sap.com/t5/technology-blog-posts-by-members/adding-custom-fields-to-a-fiori-app-using-custom-fields-and-logic/ba-p/14320222Adding Custom Fields to a Fiori App Using Custom Fields and Logic2026-02-04T08:29:33.635000+01:00abap_Saphttps://community.sap.com/t5/user/viewprofilepage/user-id/1866490<H2 id="toc-hId-1789462628">Introduction: </H2><P>SAP S/4 HANA provides in-app extensibility and the Adaptation Transport Organizer (ATO) framework to safely create, enable and transport custom fields without modifying standard code. In this blog, I will walk through a step-by-step process to set up ATO, prepare custom fields, enable them, publish them and finally add then to a custom Fiori app.</P><P><U><STRONG>Step 1: Initial ATO (Adaptation Transport Organizer) set up:</STRONG></U></P><OL><LI>Go to transaction SCFD_EUI</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_56-1770060401488.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368314iA18A140D1D6E311F/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_56-1770060401488.png" alt="abap_Sap_56-1770060401488.png" /></span></P><P>2. Close the initial pop up and click on Auto Setup and following screen will populate:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_57-1770060432363.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368315iFF37E119550E2FFC/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_57-1770060432363.png" alt="abap_Sap_57-1770060432363.png" /></span></P><P>3. Create below packages using SE80:</P><OL><LI>Local package TEST_KEY_USER_LOCAL</LI><LI>Sandbox package TEST_KEY_USER_SANDBOX</LI></OL><P>4. Now enter the local and sandbox package name and click on ‘Setup with specific data’.</P><P>5. It will then prompt you for a transport, for this first create a workbench transport and assign it in the popup to enter the transport and save your entries.</P><P>6. Input table name ‘GMGR’ and field ‘Z*’ and hit Execute:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_58-1770060498515.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368317i89792AF60CBBAC07/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_58-1770060498515.png" alt="abap_Sap_58-1770060498515.png" /></span></P><P><STRONG><U>Step 2 – Understanding Field Statuses</U></STRONG></P><P>After execution the output screen shows three possible field statuses:</P><P><STRONG>Enabled:</STRONG> This is already enabled and available in custom field APP</P><P><STRONG>Can Be Enabled:</STRONG> This can be enabled by clicking Enable button in tool bar</P><P><STRONG>Preparation Required: </STRONG>Click on Prepare button, it will show the further steps to make it</P><P>‘CAN BE ENABLED’ status.</P><P><STRONG><U>Step3: Changing Status from preparation required to can be enabled</U></STRONG></P><OL><LI>Select ZZPIAR_EMAIL and click on Prepare.</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_59-1770060565082.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368318i5638C349F47C7AAA/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_59-1770060565082.png" alt="abap_Sap_59-1770060565082.png" /></span></P><P>2. The message below will be shown:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_60-1770060605890.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368319iB2D7B7530A8131C8/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_60-1770060605890.png" alt="abap_Sap_60-1770060605890.png" /></span></P><P>3. Go to T-code SE11 and check GMGR table.</P><P>4. The field ZZPIAR_EMAIL does not have domain associated</P><P>5. Once Domain is created for this field, the status of the field will become ‘CAN BE ENABLED’.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_61-1770060654952.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368320i9D53129912D14FBD/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_61-1770060654952.png" alt="abap_Sap_61-1770060654952.png" /></span></P><P><STRONG><U>Step4: Enabling the custom field</U></STRONG></P><OL><LI>The below field ZZFINALEXP is in ‘CAN BE ENABLED’ status:</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_62-1770060675639.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368321i745EF80DBCE17EEF/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="abap_Sap_62-1770060675639.png" alt="abap_Sap_62-1770060675639.png" /></span></P><P>2. Select ZZFINALEXP and click Enable button:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_63-1770060700377.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368322i15E3813FD2DDCEF2/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="abap_Sap_63-1770060700377.png" alt="abap_Sap_63-1770060700377.png" /></span></P><P>3. Select correct enabling type and click ok:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_64-1770060726057.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368323iEC84D2F98A7162EC/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_64-1770060726057.png" alt="abap_Sap_64-1770060726057.png" /></span></P><P>4. Select the package and create a workbench transport and Provide Transport number at Request/Task click ok.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_65-1770060762643.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368324iE707007CCD0E01B0/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="abap_Sap_65-1770060762643.png" alt="abap_Sap_65-1770060762643.png" /></span></P><P>5. We can see that the field ZZFINALEXP status changed to ‘Enabled’ status:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_66-1770060782129.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368325i73008B207BC4670D/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_66-1770060782129.png" alt="abap_Sap_66-1770060782129.png" /></span><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_67-1770060787890.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368326i0497AA2777BFA64F/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="abap_Sap_67-1770060787890.png" alt="abap_Sap_67-1770060787890.png" /></span></P><P><STRONG><U>Step5: Publish the custom Field</U></STRONG></P><OL><LI>Go to T-code /n/ui2/flp</LI><LI>Login to FIORI</LI><LI>Execute ‘custom field’ app</LI><LI>The below screen appears, this app shows all ‘Enabled’ fields, we see ‘Final Expense’ field here which we have enabled in above steps(step3).</LI><LI>Now select ‘FINAL EXPENSE’ field and click on the arrow.</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_69-1770060828070.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368327i5D6B617B9EBD74B7/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_69-1770060828070.png" alt="abap_Sap_69-1770060828070.png" /></span></P><P>6. The screen below opens, now enable Additional selection-Grant</P><P>7. Click on publish</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_70-1770060861600.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368328i674252DEA2278150/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_70-1770060861600.png" alt="abap_Sap_70-1770060861600.png" /></span></P><P>The field is published now.</P><P><STRONG><U>Step6: Add Custom field to ‘Custom’ App</U></STRONG></P><OL><LI>Now go to the custom app and click on ‘Adapt UI’ as shown below.</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_71-1770060895180.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368329iC964F914CDA5992E/image-size/medium?v=v2&px=400" role="button" title="abap_Sap_71-1770060895180.png" alt="abap_Sap_71-1770060895180.png" /></span></P><P>2. Now the page becomes ‘Editable’, right click on screen, we can see option add field</P><P>3. Select Final expense field here and click OK.</P><P>4. Final Expense field will be added to the screen, now click Publish and save and exit.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_72-1770060920979.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368330i99F1FBE00A9C3C31/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="abap_Sap_72-1770060920979.png" alt="abap_Sap_72-1770060920979.png" /></span><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_Sap_73-1770060928101.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368331i966131F1416695F2/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="abap_Sap_73-1770060928101.png" alt="abap_Sap_73-1770060928101.png" /></span></P><H2 id="toc-hId-1592949123">Conclusion:</H2><P>By following these steps, you can manage custom fields using SAP’s standard extensibility framework without touching the core objects. This approach reduced upgrade risk, supports transport consistency, and aligns with SAP’s clean-core strategy. The same method can be reused for other tables and fields across S/4HANA landscape.</P><DIV class=""> </DIV><P> </P><P> </P>2026-02-04T08:29:33.635000+01:00https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537How to Deliver Customizing as a SaaS Provider using Business Configuration Sets2026-02-05T09:59:15.458000+01:00peterpersielhttps://community.sap.com/t5/user/viewprofilepage/user-id/14643<DIV>In our previous blog post, <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-provide-customizing-as-a-saas-provider/ba-p/14009081" target="_blank">How to Provide Customizing as a SaaS Provider</A>, we described a programmatic approach that used EML statements with explicitly coded object templates in application jobs to deliver customizing entries. With release 2511, you can now use <A href="https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/business-configuration-sets-2adb1bfdb1404a7497a4424e0411e2a6?version=Cloud" target="_self" rel="noopener noreferrer">Business Configuration Sets</A> instead, removing the need to include explicitly coded customizing data in your business logic.</DIV><P>This blog illustrates how to maintain customizing data in a <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/fiori-apps-business-configuration?version=Cloud" target="_self" rel="noopener noreferrer">Business Configuration Maintenance Object</A>, how to maintain customizing translations, importing the created customizing data/translations into a BC Set, implementing an application job for the BC Set activation and finally how to deploy the BC Set content to the relevant customizing table.<BR />We will also have a look into how BC Sets can be updated programmatically for the case when the customizing data was changed and BC Set data needs to be reimported.</P><P>This blog presents an alternative method to the Fiori app Upload Business Configuration. One <A href="https://influence.sap.com/sap/ino/#/idea/338295/?section=sectionDetails" target="_blank" rel="noopener noreferrer">restriction</A> of the Upload Business Configuration app is that it does not validate the customizing data being uploaded.<BR />In contrast, customizing data imported into Business Configuration (BC) Sets via ADT originates from existing customizing requests. This data is created within custom business configuration objects, where it is automatically validated through the underlying BO behavior (for example, error codes greater than 500 are rejected):</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_0-1770205854371.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368896i5858C39B446622DF/image-size/medium?v=v2&px=400" role="button" title="peterpersiel_0-1770205854371.png" alt="peterpersiel_0-1770205854371.png" /></span></P><P>This blog covers the following topics:</P><P><ul =""><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-1660412619">Create Business Configuration Maintenance Object</a></li><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-1463899114">Providing Authorization Control for a Business Configuration Maintenance Object</a></li><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-1267385609">Creating customizing data & translations</a></li><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-1070872104">Creating a BC Set and importing customizing data & translations</a></li><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-874358599">Creating an Application Job for the BC Set activation</a></li><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-677845094">Deploying the BC Set content by running the application job</a></li><li style="list-style-type:square; margin-left:0px; margin-bottom:1px;"><a href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-deliver-customizing-as-a-saas-provider-using-business-configuration/ba-p/14321537#toc-hId-481331589">Maintaining customizing data programmatically in BC Sets</a></li></ul></P><H1 id="toc-hId-1660412619"><STRONG>Create Business Configuration Maintenance Object</STRONG></H1><P>The Business Configuration Maintenance Object discussed in this blog can be developed using the following tutorial, which guides you in creating a table for storing error codes:</P><P><A href="https://developers.sap.com/tutorials/abap-environment-business-configuration-object.html" target="_blank" rel="noopener noreferrer">Create Business Configuration Maintenance Object | SAP Tutorials</A></P><H1 id="toc-hId-1463899114"><STRONG>Providing Authorization Control for a Business Configuration Maintenance Object</STRONG></H1><P>To use the Business Configuration Maintenance Object, the required authorization must be set up. How to do this is explained in this tutorial:</P><P><A href="https://developers.sap.com/tutorials/abap-environment-authorization-control.html" target="_blank" rel="noopener noreferrer">Providing Authorization Control for a Business Configuration Maintenance Object | SAP Tutorials</A></P><H1 id="toc-hId-1267385609"><STRONG>Creating customizing data & translations</STRONG></H1><P>Maintain following customizing data as described in tutorial <A href="https://developers.sap.com/tutorials/abap-environment-maintain-bc-app.html" target="_blank" rel="noopener noreferrer">Use Custom Business Configurations app</A> on a new customizing request:</P><TABLE width="271"><TBODY><TR><TD width="105"><P><STRONG>Error Code</STRONG></P></TD><TD width="165"><P><STRONG>Description</STRONG></P></TD></TR><TR><TD width="105"><P>400</P></TD><TD width="165"><P>Bad Request</P></TD></TR><TR><TD width="105"><P>401</P></TD><TD width="165"><P>Unauthorized</P></TD></TR><TR><TD width="105"><P>403</P></TD><TD width="165"><P>Forbidden</P></TD></TR></TBODY></TABLE><P>Afterwards your customizing request should include the primary customizing data as <EM>Customizing: Table Contents</EM>. Such customizing requests can be used for importing into a BC Set. Corresponding data records and translations will be extracted automatically during the process.</P><P>Maintain customizing translations for source language<EM> English United States</EM> and target language, for example <EM>German Germany,</EM> for the error codes using the <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/maintain-customizing-translations?version=Cloud" target="_blank" rel="noopener noreferrer">Maintain Customizing Translations</A> app.</P><P>Select the text table <EM>ZERRCODET_###</EM> that was created earlier as text source in your translation project.</P><H1 id="toc-hId-1070872104"><STRONG>Creating a BC Set and importing customizing data & translations</STRONG></H1><P>Follow the steps provided in <A href="https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/creating-business-configuration-sets" target="_blank" rel="noopener noreferrer">Creating Business Configuration Sets</A> to create a new business configuration set and use the customizing request that was created in the previous step for importing the data.</P><P>After successful import from the customizing request the error code data records as well as translations are included:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_1-1770206570634.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368900i16C97DB6762B6F87/image-size/large?v=v2&px=999" role="button" title="peterpersiel_1-1770206570634.png" alt="peterpersiel_1-1770206570634.png" /></span></P><P>We can now proceed to implement an application job that can be used activate this BC Set.</P><P><STRONG>Note: </STRONG>To import customizing data into a BC Set, the customizing data needs to be maintained for customizing objects of type Individual Transaction Object. A business configuration maintenance object (CUBCO) is configured as such by defining a <A href="https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/working-with-transport-object-definitions" target="_blank" rel="noopener noreferrer">transport object definition (TOBJ)</A> in the service configuration settings of the CUBCO. By using the business configuration maintenance object wizard as described in <A href="https://developers.sap.com/tutorials/abap-environment-business-configuration-object.html" target="_blank" rel="noopener noreferrer">Create Business Configuration Maintenance Object | SAP Tutorials</A>, this prerequisite is fulfilled. For more information, please refer to <A href="https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/generating-business-configuration-maintenance-object-with-generate-abap-repository-objects-wizard?version=Cloud#bc-management" target="_blank" rel="noopener noreferrer">Generating a Business Configuration Maintenance Object with the Generate ABAP Repository Objects Wizard</A> <SPAN>→</SPAN> BC Management. Configuration changes are then recorded with object type TDAT instead of a TABU.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_2-1770206570637.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368899iBCA9DA4E870B838B/image-size/large?v=v2&px=999" role="button" title="peterpersiel_2-1770206570637.png" alt="peterpersiel_2-1770206570637.png" /></span></P><P>Those business configuration maintenance objects without existing transport object definition must be migrated, and a transport object definition needs to be created manually. How this can be done is described in the blog post <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/how-to-enable-bc-set-support-for-bc-app/ba-p/14313371" target="_blank">How to enable BC Set support for BC app</A>.</P><H1 id="toc-hId-874358599"><STRONG>Creating an Application Job for the BC Set activation</STRONG></H1><P>In this example, an <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/application-jobs" target="_blank" rel="noopener noreferrer">Application Job</A> is used for creating and updating the customizing entries in a SaaS tenant. The customizing entries are deployed within the Application Job's implementation by activating the business configuration set using the corresponding <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/runtime-api-986855193ceb4e06862ac78466327928" target="_blank" rel="noopener noreferrer">runtime API</A>.</P><P>As a first step, implement the BC Set activation as the <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/implementing-business-logic" target="_blank" rel="noopener noreferrer">business logic of the of the application job</A> with a parameter for the BC Set to be activated and while saving activation messages in the application log:</P><pre class="lia-code-sample language-abap"><code>CLASS zcl_errorcode_set_activate_000 DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
"! <p class="shorttext synchronized">Error Codes BC Set</p>
DATA errorcode_bc_set TYPE cl_scpr_cd_bcset_activation=>ty_bcset_id VALUE 'Z_ERROR_CODES_SET_000'.
INTERFACES if_apj_rt_run.
INTERFACES if_apj_dt_defaults.
PRIVATE SECTION.
CONSTANTS log_object TYPE cl_bali_header_setter=>ty_object VALUE 'Z_ERRORCODE_SET_000'.
CONSTANTS log_subobject TYPE cl_bali_header_setter=>ty_subobject VALUE 'ACTIVATE'.
ENDCLASS.
CLASS zcl_errorcode_set_activate_000 IMPLEMENTATION.
METHOD if_apj_dt_defaults~fill_attribute_defaults.
errorcode_bc_set = 'Z_ERROR_CODES_SET_000'.
ENDMETHOD.
METHOD if_apj_rt_run~execute.
TRY.
DATA(lo_bali_log) = cl_bali_log=>create_with_header(
header = cl_bali_header_setter=>create( object = log_object
subobject = log_subobject ) ).
TRY.
DATA(lo_bcset_activate) = cl_scpr_cd_bcset_activation=>of( errorcode_bc_set ).
CATCH cx_scpr_object_not_permitted INTO DATA(lx_scpr_object_not_permitted).
lo_bali_log->add_item(
item = cl_bali_exception_setter=>create( severity = if_bali_constants=>c_severity_error
exception = lx_scpr_object_not_permitted ) ).
ENDTRY.
DATA(lo_activation_handler) = lo_bcset_activate->get_activate_handler( ).
DATA(lo_activation_result) = lo_activation_handler->local( )->add_activation_options( )->start( ).
DATA(lt_activation_messages) = lo_activation_result->get_messages( ).
LOOP AT lt_activation_messages INTO DATA(ls_msg).
lo_bali_log->add_item( item = cl_bali_message_setter=>create_from_bapiret2( message_data = ls_msg ) ).
ENDLOOP.
cl_bali_log_db=>get_instance( )->save_log_2nd_db_connection( log = lo_bali_log
assign_to_current_appl_job = abap_true ).
CATCH cx_bali_runtime INTO DATA(lx_bali_runtime).
RAISE EXCEPTION TYPE cx_apj_rt_content USING MESSAGE
EXPORTING previous = lx_bali_runtime.
ENDTRY.
ENDMETHOD.
ENDCLASS.</code></pre><P>Then create a catalog entry and job template for the class with the business logic: <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/creating-job-catalog-entry-and-job-template-in-adt" target="_blank" rel="noopener noreferrer">Creating a Job Catalog Entry and a Job Template</A>. Also create an application log object and sub object according to the job logic implementation: <A href="https://help.sap.com/docs/abap-cloud/abap-development-tools-user-guide/working-with-application-log-objects?version=sap_btp" target="_blank" rel="noopener noreferrer">Working with Application Log Objects</A>.</P><P>To run the application job for BC Set activation, users must have the authorization provided by a business catalog. In this case we will reuse the business catalog <EM>Z_ERROR_CODES_###</EM> that was already created as part of the tutorial <A href="https://developers.sap.com/tutorials/abap-environment-authorization-control.html" target="_blank" rel="noopener noreferrer">Providing Authorization Control for a Business Configuration Maintenance Object</A>.</P><P>The business catalog <EM>Z_ERROR_CODES_###</EM> already includes the <A href="https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/iam-app-types?version=Cloud" target="_blank" rel="noopener noreferrer">IAM App of type</A> <EM>MBC</EM> (Business Configuration App) that was created for the CUBCO. During creation of the job catalog entry for the BC Set activation job, another IAM app with name <EM><job catalog entry name>_SAJC</EM> is automatically created (refer to <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/setting-up-authorizations?version=Cloud" target="_blank" rel="noopener noreferrer">Setting up the Authorizations</A>). This IAM app, to start the application job, is added to the existing business catalog so that the catalog provides authorizations to maintain error codes in the CUBCO as well as to start the BC Set activation job:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_3-1770207589713.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368904iE77B14E4AEE8D2BA/image-size/large?v=v2&px=999" role="button" title="peterpersiel_3-1770207589713.png" alt="peterpersiel_3-1770207589713.png" /></span></P><P>The BC Set activation implemented in the activation job using the <EM>CL_SCPR_CD_BCSET_ACTIVATION</EM> API requires table access for all entities used in the BC Set, so for both the primary tables as well as text tables. This can be achieved by adding the names of the tables in the <EM>TABLE</EM> authorization field of the existing <EM>S_TABU_NAM</EM> authorization in the <EM>_MBC</EM> IAM app: in this case <EM>ZERRCODET_000</EM> (text table) and <EM>ZERRCODE_000</EM> (primary table):</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_4-1770207786852.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368909i70BCA9687904C610/image-size/large?v=v2&px=999" role="button" title="peterpersiel_4-1770207786852.png" alt="peterpersiel_4-1770207786852.png" /></span></P><P>Hint: If you plan to run the BC Set activation job in your development system, do not forget to publish your changes to the business catalog locally.</P><H1 id="toc-hId-677845094"><STRONG>Deploying the BC Set content by running the application job</STRONG></H1><P>Make sure that the user that shall run the BC Set activation job has following business roles/catalogs assigned in the ABAP tenant (for example your SaaS consumer tenant):</P><TABLE><TBODY><TR><TD width="267.996px" height="50px"><P><STRONG>Business Role</STRONG></P></TD><TD width="232.992px" height="50px"><P><STRONG>Business Catalog</STRONG></P></TD><TD width="123px" height="50px"><P><STRONG>Purpose</STRONG></P></TD></TR><TR><TD width="267.996px" height="132px"><P>SAP_BR_ADMINISTRATOR</P></TD><TD width="232.992px" height="132px"><P>SAP_CORE_BC_APJ_JCE</P></TD><TD width="123px" height="132px"><P>For scheduling jobs in the <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/application-jobs-3?version=Cloud" target="_blank" rel="noopener noreferrer">Application Jobs</A> app</P></TD></TR><TR><TD width="267.996px" height="159px"><P>SAP_BR_BPC_EXPERT</P></TD><TD width="232.992px" height="159px"><P>SAP_CORE_BC_BCT_MBC_PC</P></TD><TD width="123px" height="159px"><P>To use the <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/custom-business-configurations-app?version=Cloud" target="_blank" rel="noopener noreferrer">Custom Business Configurations app</A></P></TD></TR><TR><TD width="267.996px" height="488px"><P>ZBR_ERROR_CODES_EXPERT_###</P></TD><TD width="232.992px" height="488px"><P>Z_ERROR_CODES_###</P></TD><TD width="123px" height="488px"><P>To maintain error codes in the Custom Business Configurations app and to start the BC Set activation job.<BR />As created in tutorial <A href="https://developers.sap.com/tutorials/abap-environment-authorization-control.html" target="_blank" rel="noopener noreferrer">Providing Authorization Control for a Business Configuration Maintenance Object</A></P></TD></TR></TBODY></TABLE><P>Open the Application Job App and select "Create" to create a new Application Job, then<BR />choose the Application Job Template. Maintain the scheduling options and provide a valid BC Set in the parameter. Schedule the Application Job by clicking "Schedule".</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_5-1770208025521.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368918i02D953A69DFD883A/image-size/large?v=v2&px=999" role="button" title="peterpersiel_5-1770208025521.png" alt="peterpersiel_5-1770208025521.png" /></span></P><P>Check the Application Job Log to determine if the BC Set content was deployed correctly:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_6-1770208059336.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368921i6DB487C8FB390C6F/image-size/large?v=v2&px=999" role="button" title="peterpersiel_6-1770208059336.png" alt="peterpersiel_6-1770208059336.png" /></span></P><P>Users assigned to the required business roles (see above) can now check in the Custom Business Configurations App whether the customizing has been inserted and updated correctly:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="peterpersiel_7-1770208099315.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/368922iE07C527C2359B269/image-size/medium?v=v2&px=400" role="button" title="peterpersiel_7-1770208099315.png" alt="peterpersiel_7-1770208099315.png" /></span></P><H1 id="toc-hId-481331589"><STRONG>Maintaining customizing data programmatically in BC Sets</STRONG></H1><P>You might want to automate the lifecycle of your customizing data. For instance, you can update a BC Set with the latest customizing data after some changes. To do this, maintain your changes in EML within the configuration object on a customizing request. Then read the latest data from the underlying customizing tables and finally update the BC Set.</P><P>You can programmatically create a customizing request using the <A href="https://help.sap.com/docs/btp/sap-business-technology-platform/correction-and-transport-system?version=Cloud" target="_blank" rel="noopener noreferrer">XCO CTS module</A>. EML will then be used to maintain the data on that customizing request. Additionally, you have the option to programmatically release the customizing request afterward.</P><pre class="lia-code-sample language-abap"><code>CLASS zcl_errorcode_generate_000 DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
TYPES tyt_errorcodes TYPE STANDARD TABLE OF zerrcode_000 WITH KEY error_code.
TYPES tyt_errorcodestext TYPE STANDARD TABLE OF zerrcodet_000 WITH KEY langu error_code.
TYPES tyt_errorcodes_update TYPE TABLE FOR UPDATE ZI_ErrorCode000.
TYPES tyt_errorcodestext_update TYPE TABLE FOR UPDATE ZI_ErrorCode000Text.
METHODS delete_errorcodes
IMPORTING transportrequest TYPE trkorr.
METHODS create_errorcodes
IMPORTING transportrequest TYPE trkorr
it_errorcodes_crt TYPE tyt_errorcodes
it_errorcodestext_crt TYPE tyt_errorcodestext.
METHODS update_errorcodes
IMPORTING transportrequest TYPE trkorr
it_errorcodes_update TYPE tyt_errorcodes_update
it_errorcodestext_update TYPE tyt_errorcodestext_update.
CONSTANTS co_cust_transport_target TYPE if_xco_transport_target=>tv_value VALUE ''. " LOCAL
CONSTANTS co_cust_transport_description TYPE sxco_ar_short_description VALUE 'Maintain new error codes programmatically'.
ENDCLASS.
CLASS zcl_errorcode_generate_000 IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
" Create customizing transport request
DATA(lo_customizing_request) = xco_cp_cts=>transports->customizing( co_cust_transport_target )->create_request(
co_cust_transport_description ).
" Programmatically create new error codes using EML
create_errorcodes( transportrequest = lo_customizing_request->value
it_errorcodes_crt = VALUE tyt_errorcodes( ( error_code = '404' )
( error_code = '405' )
( error_code = '406' ) )
it_errorcodestext_crt = VALUE tyt_errorcodestext(
( langu = 'D' error_code = '404' description = 'Not Found' )
( langu = 'E' error_code = '404' description = 'Nicht gefunden' )
( langu = 'D' error_code = '405' description = 'Method Not Allowed' )
( langu = 'E' error_code = '405' description = 'Methode nicht erlaubt' )
( langu = 'D' error_code = '406' description = 'Not Acceptable' )
( langu = 'E' error_code = '406' description = 'Nicht akzeptabel' ) ) ).
" Release customizing tasks and customizing request
DATA(lt_transport_tasks) = lo_customizing_request->get_tasks( ).
LOOP AT lt_transport_tasks INTO DATA(lo_transport_task).
IF lo_transport_task->get_status( ) <> xco_cp_transport=>status->modifiable.
CONTINUE.
ENDIF.
lo_transport_task->release( ).
ENDLOOP.
lo_customizing_request->release( ).
ENDMETHOD.
METHOD create_errorcodes.
DATA lt_errorcode_create TYPE TABLE FOR CREATE ZI_ErrorCode000_S\_ErrorCode000.
TYPES tys_errorcode_create LIKE LINE OF lt_errorcode_create.
DATA ls_errorcode_create TYPE tys_errorcode_create.
DATA lt_errorcodestext_create TYPE TABLE FOR CREATE ZI_ErrorCode000\_ErrorCode000Text.
TYPES tys_errorcodestext_create LIKE LINE OF lt_errorcodestext_create.
DATA ls_errorcodestext_create TYPE tys_errorcodestext_create.
LOOP AT it_errorcodes_crt INTO DATA(wa_errorcode_crt).
ls_errorcode_create = VALUE #( SingletonID = 1
%target = VALUE #( ( ErrorCode = wa_errorcode_crt-error_code
%control-ErrorCode = if_abap_behv=>mk-on ) ) ).
APPEND ls_errorcode_create TO lt_errorcode_create.
ENDLOOP.
LOOP AT it_errorcodestext_crt INTO DATA(wa_errorcodestext_crt).
ls_errorcodestext_create = VALUE #(
%tky-ErrorCode = wa_errorcodestext_crt-error_code
%target = VALUE #( ( Langu = wa_errorcodestext_crt-langu
%control-Langu = if_abap_behv=>mk-on
Description = wa_errorcodestext_crt-description
%control-Description = if_abap_behv=>mk-on ) ) ).
APPEND ls_errorcodestext_create TO lt_errorcodestext_create.
ENDLOOP.
MODIFY ENTITIES OF ZI_ErrorCode000_S
ENTITY ErrorCode000All
UPDATE
FIELDS ( TransportRequestID )
WITH VALUE #( ( SingletonId = 1
TransportRequestID = transportrequest ) )
ENTITY ErrorCode000All
CREATE BY \_ErrorCode000 FROM lt_errorcode_create
REPORTED DATA(r_errorcodes_crt)
FAILED DATA(f_errorcodes_crt)
MAPPED DATA(m_errorcodes_crt) ##NEEDED.
MODIFY ENTITIES OF ZI_ErrorCode000_S
ENTITY ErrorCode000
CREATE BY \_ErrorCode000Text FROM lt_errorcodestext_create
REPORTED DATA(r_errorcodestext_crt)
FAILED DATA(f_errorcodestext_crt)
MAPPED DATA(m_errorcodestext_crt) ##NEEDED.
COMMIT ENTITIES
BEGIN RESPONSE OF ZI_ErrorCode000_S
FAILED DATA(failed_create)
REPORTED DATA(reported_create) ##NEEDED.
COMMIT ENTITIES END.
ENDMETHOD.
METHOD delete_errorcodes.
MODIFY ENTITIES OF ZI_ErrorCode000_S
ENTITY ErrorCode000All
UPDATE
FIELDS ( TransportRequestID )
WITH VALUE #( ( SingletonId = 1
TransportRequestID = transportrequest ) )
FAILED DATA(f_delete_tr)
MAPPED DATA(m_delete_tr)
REPORTED DATA(r_delete_tr) ##NEEDED.
MODIFY ENTITIES OF ZI_ErrorCode000_S
ENTITY ErrorCode000All
CREATE FIELDS ( TransportRequestID ) WITH VALUE #( ( TransportRequestID = transportrequest ) )
DELETE FROM VALUE #( ( SingletonID = 1 ) )
FAILED DATA(f_delete)
MAPPED DATA(m_delete)
REPORTED DATA(r_delete) ##NEEDED.
COMMIT ENTITIES
BEGIN RESPONSE OF ZI_ErrorCode000_S
FAILED DATA(failed_delete)
REPORTED DATA(reported_delete) ##NEEDED.
COMMIT ENTITIES END.
ENDMETHOD.
METHOD update_errorcodes.
DATA lt_errorcodestext_update_i TYPE TABLE FOR UPDATE ZI_ErrorCode000Text.
IF it_errorcodes_update IS NOT INITIAL OR it_errorcodestext_update IS NOT INITIAL.
LOOP AT it_errorcodestext_update INTO DATA(ls_errorcodetext_update).
ls_errorcodetext_update-%control-Description = if_abap_behv=>mk-on.
APPEND ls_errorcodetext_update TO lt_errorcodestext_update_i.
ENDLOOP.
ENDIF.
MODIFY ENTITIES OF ZI_ErrorCode000_S
ENTITY ErrorCode000All
UPDATE
FIELDS ( transportrequestid )
WITH VALUE #( ( SingletonID = 1
TransportRequestID = transportrequest ) )
ENTITY ErrorCode000Text
UPDATE FROM lt_errorcodestext_update_i
REPORTED DATA(r_errorcodes_upd)
FAILED DATA(f_errorcodes_upd)
MAPPED DATA(m_errorcodes_upd) ##NEEDED.
COMMIT ENTITIES
BEGIN RESPONSE OF ZI_ErrorCode000_S
FAILED DATA(failed_update)
REPORTED DATA(reported_update) ##NEEDED.
COMMIT ENTITIES END.
ENDMETHOD.
ENDCLASS.</code></pre><P>The advantage of using EML to create, update, and delete customizing entries is that all validations of the business configuration object (BCO) are performed. This approach also supports both customizing entries of type table data (TABU) and individual transaction object (TDAT) since API adapters are available for both cases to be used in the behavior implementation of the BCO (for example, <EM>mbc_cp_api=>rap_tdat_cts()).</EM> For further information, refer to <A href="https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/transport-handling?version=Cloud" target="_blank" rel="noopener noreferrer">Transport Handling</A>.</P><P>After updating the customizing data in the Business Configuration Object (BCO) using EML, the latest customizing data can be retrieved from the underlying customizing tables for further processing. Once the up-to-date customizing data is obtained, it can be directly maintained in the BC Set. This process utilizes the <A href="https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/business-configuration-sets?version=Cloud" target="_self" rel="noopener noreferrer">XCO generation APIs for BC Sets</A>.</P><pre class="lia-code-sample language-abap"><code>CLASS zcl_errorcode_generate_000 DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
CONSTANTS co_workbench_request TYPE trkorr VALUE ''. " ZLOCAL
CONSTANTS co_error_codes_set_name TYPE if_xco_business_cnfgrtn_set=>tv_name VALUE 'Z_ERROR_CODES_SET_000'.
CONSTANTS co_error_codes_entity_primary TYPE if_xco_bcs_entity=>tv_name VALUE 'ZERRCODE_000'.
CONSTANTS co_error_codes_entity_text TYPE if_xco_bcs_entity=>tv_name VALUE 'ZERRCODET_000'.
CONSTANTS co_error_codes_tobj TYPE if_xco_bcs_customizing_object=>tv_name VALUE 'ZERRORCODE000'.
ENDCLASS.
CLASS zcl_errorcode_generate_000 IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
" Read latest error codes from customizing tables
SELECT * FROM zerrcode_000 WHERE error_code < 500 INTO TABLE (lt_errorcodes).
ASSERT sy-subrc = 0.
SELECT * FROM zerrcodet_000 WHERE error_code < 500 INTO TABLE (lt_errorcodes_text).
ASSERT sy-subrc = 0.
" Retrieve error codes BC set and make sure it exists
DATA(lo_business_configuration_set) = xco_cp_abap_repository=>object->scp1->for( co_error_codes_set_name ).
ASSERT lo_business_configuration_set->if_xco_ar_object~exists( ).
" Create BC Set patch operation and change specification to remove existing error codes customizing object (all its Entities and corresponding records)
DATA(lo_patch_operation_delete) = xco_cp_generation=>environment->dev_system( co_workbench_request )->for-scp1->create_patch_operation( ).
DATA(lo_change_specification_delete) = lo_patch_operation_delete->add_object( co_error_codes_set_name )->create_change_specification( ).
lo_change_specification_delete->for-delete->add_individual_transaction_obj( co_error_codes_tobj ).
" Create BC Set patch operation and change specification to insert latest error codes using latest customizing data
DATA(lo_patch_operation_insert) = xco_cp_generation=>environment->dev_system( co_workbench_request )->for-scp1->create_patch_operation( ).
DATA(lo_change_specification_insert) = lo_patch_operation_insert->add_object( co_error_codes_set_name )->create_change_specification( ).
DATA(lo_tobj_insert) = lo_change_specification_insert->for-insert->add_individual_transaction_obj(
co_error_codes_tobj ).
lo_tobj_insert->for-insert->add_entity( co_error_codes_entity_primary )->for-insert->add_records(
REF #( lt_errorcodes[] ) ).
lo_tobj_insert->for-insert->add_entity( co_error_codes_entity_text )->for-insert->add_records(
REF #( lt_errorcodes_text[] ) ).
" After preparing the change specifications, execute the PATCH operations
TRY.
DATA(lo_result_delete) = lo_patch_operation_delete->execute( ) ##NEEDED.
DATA(lo_result_insert) = lo_patch_operation_insert->execute( ) ##NEEDED.
CATCH cx_xco_gen_patch_exception INTO DATA(lo_xco_gen_patch_exception).
LOOP AT lo_xco_gen_patch_exception->findings->get( ) ASSIGNING FIELD-SYMBOL(<fs_finding>) ##NEEDED.
" Process errors/exceptions raised from the PATCH operation
ENDLOOP.
ENDTRY.
ENDMETHOD.
ENDCLASS.</code></pre><P>This section of using the XCO generation API for BC Sets to update BC set data requires customizing entries of type individual transaction object (TDAT). This is because it’s a requirement for importing any data into a BC Set. BC Sets are workbench objects and can be delivered alongside other development objects in your development software components.</P><P>Hint: In productive scenarios remove the <EM>##NEEDED</EM> pragma from the code examples and implement proper error handling!</P>2026-02-05T09:59:15.458000+01:00https://community.sap.com/t5/technology-blog-posts-by-sap/abap-ai-podcast-reflecting-on-2025-and-looking-ahead-to-2026/ba-p/14322098ABAP AI Podcast: Reflecting on 2025 and Looking Ahead to 20262026-02-05T11:20:57.156000+01:00SHRUTHISADAGOPANPITCHUMANIhttps://community.sap.com/t5/user/viewprofilepage/user-id/1699865<H4 id="toc-hId-2047685949"> 2025: The Year ABAP AI Became Tangible</H4><P>As Simona and I reflected on 2025, one theme stood out: it was the year ABAP AI stopped being a promise and became something developers could <EM>touch</EM>, <EM>use</EM>, and <EM>trust</EM>. That shift didn’t happen all at once — it was shaped across the year through a series of releases that progressively deepened what ABAP and AI could do together.</P><P><STRONG>The journey began with Release 2502</STRONG>, our first big delivery, which marked a turning point for the ABAP developer experience. This release introduced the foundational AI capabilities that developers immediately felt in their workflow: the initial wave of explain ability for ABAP and CDS, predictive and context‑aware code suggestions, and early ABAP Cloud compliance insights. 2502 was a statement: ABAP AI had arrived, and it was ready for real use cases.</P><P>Building on this momentum, <STRONG>Release 2505</STRONG> expanded and strengthened the story. the RAP BO Generator for Fiori applications. The explain model grew to cover more ABAP constructs, predictive assistance became more capable, and clean‑core compliance checks were enhanced to give developers clearer, more actionable guidance.</P><P>Toward the end of the year, <STRONG>Release 2508</STRONG> brought refinement and specialization. AI guidance became more scenario‑aware — better tuned for migration, modernization, and, AI‑supported extensibility patterns. Autogenerated documentation became richer and more reliable. Custom code migration also received a boost with deeper AI‑powered insights and more intelligent documentation support — small but meaningful improvements that helped teams move faster and with more confidence.</P><P>And throughout all of this, we made sure customers in private cloud were not left behind. With the <STRONG>2025 PCE add</STRONG><STRONG>‑</STRONG><STRONG>ins</STRONG>, <EM>Joule for Developers</EM> became available to S/4HANA Private Cloud Edition customers as well — enabling AI‑assisted custom code migration, modernization support, and clean‑core guidance even for those on older releases. This was a major step in democratizing ABAP AI and bringing its value to a much broader installed base.</P><H4 id="toc-hId-1851172444"><STRONG>Key Features and Developer Impact</STRONG></H4><P>With <STRONG>Joule for Developers</STRONG>, ABAP developers immediately benefited from a range of intelligent capabilities, including:</P><UL><LI>Predictive and context‑aware code suggestions</LI><LI>Automated ABAP Cloud compliance checks</LI><LI>Natural‑language explanations for both legacy and new ABAP code and extended explain use for autogenerated technical documentation</LI><LI>Developers could even generate complete <STRONG>Fiori applications</STRONG> simply by describing the functional requirements.</LI></UL><P>These advancements significantly accelerated development cycles and reduced manual effort. AI also enhanced custom code migration by proposing simplifications, improving code quality, and easing the transition to clean‑core architectures.</P><H4 id="toc-hId-1654658939"><STRONG>ABAP and AI: A Strengthened Relationship</STRONG></H4><P>Simona shared insights into why ABAP required SAP‑specific AI models. Because ABAP is proprietary, large language models were not initially trained on it. SAP addressed this by training internal models on over <STRONG>250 million lines of ABAP code</STRONG> and <STRONG>30 million lines of CDS views</STRONG>, unlocking high‑quality AI support tailored specifically to ABAP. </P><P>To hear the full conversation, listen to the episode: <A href="https://www.youtube.com/watch?v=SvjxpbNEINg" target="_self" rel="nofollow noopener noreferrer"><SPAN>ABAP AI Podcast: Reflecting on 2025 and Looking Ahead to 2026 <div class="video-embed-right video-embed"><iframe class="embedly-embed" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FSvjxpbNEINg%3Ffeature%3Doembed&display_name=YouTube&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DSvjxpbNEINg&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FSvjxpbNEINg%2Fhqdefault.jpg&type=text%2Fhtml&schema=youtube" width="400" height="225" scrolling="no" title="ABAP AI Podcast: Reflecting on 2025 and Looking Ahead to 2026" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture;" allowfullscreen="true"></iframe></div></SPAN></A></P><P>Another important point we touched on in the conversation is how ABAP AI brings together the best of both worlds. SAP pairs its own ABAP‑specialized models—trained on hundreds of millions of lines of ABAP and CDS code—with best‑of‑breed third‑party foundation models. This hybrid approach ensures developers always get the most accurate and context‑aware support for ABAP tasks, while still benefiting from the broad language understanding and creativity of large general‑purpose models. And for customers who are primarily interested in explain ability, SAP also offers <STRONG><EM>the explain</EM></STRONG><STRONG><EM>‑</EM></STRONG><STRONG><EM>only model through the AI Hub, making ABAP</EM></STRONG><STRONG><EM>‑</EM></STRONG><STRONG><EM>focused code explanations accessible even without the full Joule for Developers experience.</EM></STRONG></P><P>Far from replacing developers, AI strengthens the ABAP ecosystem. The ABAP community has shown excitement and readiness to embrace these advancements, seeing AI as a powerful augmentation of their skills. </P><H4 id="toc-hId-1458145434"><STRONG>2026: Scaling the Promise</STRONG></H4><P>Looking forward, 2026 is shaping up to be a pivotal year of <EM>scaling</EM> ABAP AI. SAP plans to bring AI capabilities to customers running older private cloud releases through a <STRONG>side</STRONG><STRONG>‑</STRONG><STRONG>by</STRONG><STRONG>‑</STRONG><STRONG>side version of Joule for Developer</STRONG><STRONG>, </STRONG>ensuring broader access also for customers on older S4HANA versions. </P><P>SAP will also add to it <STRONG>agentic tools and frameworks and an ABAP MCP Server</STRONG>, enabling SAP teams and partners to build intelligent agents that automate development tasks and connect seamlessly into an integrated agentic ecosystem. Investment in <STRONG>AI</STRONG><STRONG>‑</STRONG><STRONG>assisted custom code migration</STRONG> will continue, focusing on clean‑core compliance and automated code simplification proposals.</P><H4 id="toc-hId-1261631929"><STRONG>VS Code and Modern Tooling</STRONG></H4><P>A major priority for 2026 is establishing <STRONG>VS Code as a first</STRONG><STRONG>‑</STRONG><STRONG>class development environment for ABAP</STRONG>. By combining VS Code’s modern developer experience with Joule and AI‑centric capabilities, SAP aims to reposition ABAP as a future‑proof, cloud‑native, enterprise‑grade language.</P><H4 id="toc-hId-1065118424"><STRONG>Trust and Enterprise Readiness</STRONG></H4><P>As AI evolves, SAP continues to emphasize <STRONG>safety</STRONG>, <STRONG>compliance</STRONG>, and <STRONG>enterprise</STRONG><STRONG>‑</STRONG><STRONG>grade ethics</STRONG>. All AI use cases undergo rigorous validation to meet SAP’s security and trust standards.</P><H4 id="toc-hId-868604919"><STRONG>Custom Code Migration (CCM)</STRONG></H4><P>A core focus area we highlighted in the podcast is the continued evolution of <STRONG>Custom Code Migration (CCM)</STRONG> and its central role in helping customers transition to clean‑core, cloud‑ready architectures. Throughout 2025, AI became a powerful companion in this journey — analyzing legacy patterns, identifying simplification opportunities, and guiding developers toward more future‑proof designs. With Joule for Developers, teams benefit from usage‑aware insights, automated refactoring suggestions, and richer technical documentation that dramatically reduces the manual effort usually tied to migration projects. As we move into 2026, CCM is set to scale even further, with deeper automation and more intelligent guidance that make modernization and S/4HANA transitions faster, more predictable, and far less error‑prone.<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="SHRUTHISADAGOPANPITCHUMANI_0-1770292362345.gif" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369167i3C6305F9D5217841/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="SHRUTHISADAGOPANPITCHUMANI_0-1770292362345.gif" alt="SHRUTHISADAGOPANPITCHUMANI_0-1770292362345.gif" /></span></P><P><STRONG>Conclusion</STRONG></P><P>The year 2025 proved the real, tangible value of ABAP AI. In 2026, ABAP and AI will become inseparable—empowering developers with intelligent tools that make coding faster, smarter, and more reliable. The vision is clear: the future of ABAP development is deeply AI‑enhanced, enabling organizations to innovate with confidence and speed.</P>2026-02-05T11:20:57.156000+01:00https://community.sap.com/t5/technology-blog-posts-by-members/stop-building-from-scratch-autonomous-ai-agents-for-sap-sales-order/ba-p/14323461Stop Building from Scratch: Autonomous AI Agents for SAP Sales Order Processing2026-02-07T18:50:48.664000+01:00Siarheihttps://community.sap.com/t5/user/viewprofilepage/user-id/84286<DIV class=""><H3 id="toc-hId-1918636765">Why this article?</H3><P>It is great that we are living in the era of AI technologies where humans are still needed to design and automate <span class="lia-unicode-emoji" title=":grinning_face:">😀</span>. But let’s be honest: give it a few more years and no company will ask "Which AI platform should we choose?" That decision will be made by central AI services based on strict country and corporate regulations. The only thing that will matter is security and reliability.</P><P><STRONG>So, why am I writing this? </STRONG>Because I see so many people struggling with custom, built-from-scratch AI automation solutions at the enterprise level. These projects start quickly, but they get stuck just as fast.</P><P>You know, it is like cookies <span class="lia-unicode-emoji" title=":grinning_face:">😀</span>. You can make one in a sandbox; however, to scale that to a corporate production level is a totally different problem.</P><P>If you are still wondering why this article matters: I want to highlight that while humans are still designing automation, <STRONG>speed is everything</STRONG>. Deploying autonomous AI agents on a solid, reliable platform is a massive competitive advantage. Those playing around with internal IT projects or relying on System Integrators (SI) to build from zero are being left behind.</P><P>Let me explain why using one simple example: <STRONG>Customer Purchase Orders.</STRONG></P><H3 id="toc-hId-1722123260">The Business Case: The Reality of POs</H3><P>A company wins a deal (congratulations!), and the Customer sends a Purchase Order (PO).</P><P>In an ideal world, this happens via EDI. If you have EDI, you are lucky and you can stop reading. But in the real world, customers send PDFs, scanned images with handwriting, Excel files with macros, or even a screenshot of their laptop screen.</P><P>This <I>shouldn't</I> be an issue. Innovative platforms must handle data extraction from unstructured sources out of the box.</P><P><I>“Training? Fine-tuning??”</I></P><P>I know some of you just thought that <span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span>. Yes, training OCR models used to be mandatory. If you haven't faced the pain of training models, be happy, because you are young enough <span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span>. Today, this must work without that hassle.</P><H3 id="toc-hId-1525609755">The Main Challenge: Master Data Mapping</H3><P>Extracting text is easy. The <I>real</I> challenge is my favorite one: <STRONG>Master Data Mapping.</STRONG></P><P>How do we robustly and reliably read the customer’s product description and map it to the correct Master Data Object in our SAP system? And how do we do it without heavy development?</P><P><STRONG>The Solution: SAP Master Data Vectorization</STRONG></P><P>We don't need custom code; we need <STRONG>Vectorization</STRONG>.</P><P>Generative AI can write SQL queries, sure. But think about it: how many SQL queries would the AI have to guess to find a material that is <I>semantically</I> similar but <I>written</I> differently? Infinite. Or maybe a few less if you are lucky and the description contains an acronym like "A4 Paper" <span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span>.</P><P>When AI looks for a material master in <STRONG>vectorized data</STRONG> (rather than a database table), it reads by <I>sense</I>, not just by keywords. This allows it to reliably find the right SAP object even if the customer's description is vague.</P><P>I know only one SAP-certified Business AI Platform that has this Vectorization feature in its standard set: <STRONG>Skybuffer AI</STRONG>.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 01.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369831iAA8A4870CD9D26D4/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Skybuffer AI on Sales Orders OCR AI Bridge Pic 01.png" alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 01.png" /></span></P><P class="lia-align-center" style="text-align: center;"> <I>Pic.1 SAP Master Data Vectorization Setup</I></P><P><I><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 02.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369835i01D95270E03364EE/image-size/large?v=v2&px=999" role="button" title="Skybuffer AI on Sales Orders OCR AI Bridge Pic 02.png" alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 02.png" /></span></I></P><P class="lia-align-center" style="text-align: center;"><I> <I>Pic.2 Example of Material Master Similarities based Search</I></I></P><H3 id="toc-hId-1329096250">The Implementation: Autonomous Agents in Action</H3><P>This is the essential part: stop playing in the sandbox. Take a platform and create a simple autonomous AI agent.</P><P>In this example, I am using <STRONG>Skybuffer AI</STRONG> because it handles the heavy lifting out of the box:</P><UL><LI><P><STRONG>Vectorizes</STRONG> SAP master data for semantic search.</P></LI><LI><P><STRONG>Reads Emails</STRONG> (including complex attachments and OCR).</P></LI><LI><P><STRONG>Safety First:</STRONG> Uses Mailboxes as a staging area (no messy data replication).</P></LI><LI><P><STRONG>ABAP Control:</STRONG> It doesn't let the AI "guess" how to create data. It passes structured JSON to an ABAP class/BAPI for safe execution.</P></LI><LI><P><STRONG>No Code:</STRONG> configured entirely in SAP Fiori.</P></LI></UL><H4 id="toc-hId-1261665464">The Flow</H4><P>A Skybuffer AI agent acts effectively as an automated employee. You can schedule it, give it tools, and let it run.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 03.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369837iEA2CAE541EB823C1/image-size/large?v=v2&px=999" role="button" title="Skybuffer AI on Sales Orders OCR AI Bridge Pic 03.png" alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 03.png" /></span></P><P class="lia-align-center" style="text-align: center;"> <I>Pic.3 Scheduling Autonomous AI Agent</I></P><P><STRONG>Step 1: The Input</STRONG></P><P>The Agent connects to a Mailbox. It reads the email, extracts the attachment data, and places it into the Agent's memory.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 04.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369841i1AE6681F31CF58C5/image-size/large?v=v2&px=999" role="button" title="Skybuffer AI on Sales Orders OCR AI Bridge Pic 04.png" alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 04.png" /></span></P><P class="lia-align-center" style="text-align: center;"> <I>Pic.4 Flow inside the Tool of Skybuffer AI Action Server</I></P><P><STRONG>Step 2: The Brain (Generative AI)</STRONG></P><P>We connect the Generative AI and give it guidelines.</P><P><I>Note: The vectorized SAP master data is mapped directly to this action.</I></P><P><I><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 05.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369842iB05710840961F1EB/image-size/large?v=v2&px=999" role="button" title="Skybuffer AI on Sales Orders OCR AI Bridge Pic 05.png" alt="Skybuffer AI on Sales Orders OCR AI Bridge Pic 05.png" /></span></I></P><P class="lia-align-center" style="text-align: center;"> <I>Pic.5 Generative AI Action of Skybuffer AI Action Server</I></P><P>The AI creates a JSON structure based on our request. <STRONG>Crucially</STRONG>, we do not ask the AI to update SAP directly. We hand that JSON over to an SAP ABAP class. This ensures the transactional data is created correctly, without hallucinations.</P><P><STRONG>Step 3: The Output</STRONG></P><P>We update the email in the Mailbox with the status and send a confirmation back to the customer.</P><P>Everything runs either in your SAP HANA On-Premise shell (directly in your network) or on your SAP BTP tenant.</P><H3 id="toc-hId-936069240">Conclusion</H3><P>Autonomous AI agents are no longer "future tech", they are easy solutions available now.</P><P>By choosing a Business AI automation platform rather than building from scratch, your company gets the best of Generative AI and the SAP backend immediately.</P><P>It is strange that so many companies are still "playing" with in-house development. You wouldn't build your own Sales Order Management system from scratch instead of using SAP, right? <span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span> That would be weird. Yet, companies are giving huge budgets to internal teams to build AI wrappers.</P><P>You don't need a giant team. You need a reliable solution, speed, and flexibility. Just look at <STRONG>Cursor, </STRONG>they revolutionized coding with roughly 60 employees before their massive 900M funding round <span class="lia-unicode-emoji" title=":winking_face:">😉</span>.</P><P><STRONG>Be quick. Be autonomous.</STRONG></P></DIV>2026-02-07T18:50:48.664000+01:00https://community.sap.com/t5/abap-blog-posts/international-editable-salv-day-2026-year-18/ba-p/14323526International Editable SALV Day 2026 – Year 182026-02-07T23:36:20.726000+01:00hardyp180https://community.sap.com/t5/user/viewprofilepage/user-id/13778<P><STRONG>International Editable SALV Day 2026 – Year 18</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="hardyp180_0-1770503656222.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369869i3EE836177C15D2D0/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="hardyp180_0-1770503656222.png" alt="hardyp180_0-1770503656222.png" /></span></P><P> </P><P>Dear CL_SALV_TABLE Fans,</P><P>Welcome to February 8th, 2026, which is the eighteenth International Editable SALV Day. See below for a link to a blog I wrote to celebrate this day exactly one year ago.</P><P><SPAN><A href="https://community.sap.com/t5/technology-blogs-by-members/international-editable-salv-day-2025/ba-p/14011230#M171694" target="_blank">https://community.sap.com/t5/technology-blogs-by-members/international-editable-salv-day-2025/ba-p/14011230#M171694</A></SPAN></P><P>This day marks the 18h anniversary of James Hawthorne going cap in hand to SAP and suggesting maybe the CL_SALV_TABLE could be brought up to functional parity with the CL_GUI_ALV_GRID and have an option to be editable.</P><P><A href="https://community.sap.com/t5/application-development-discussions/cl-salv-table-needs-editable-functionality-sap-please-provide-this/m-p/3372776" target="_blank">https://community.sap.com/t5/application-development-discussions/cl-salv-table-needs-editable-functionality-sap-please-provide-this/m-p/3372776</A></P><P>Some popular pop songs are about ABAP features that should have been added 18 years ago – of which there are more than you might think – they often focus on the transition to adulthood, freedom, and nostalgia, featuring tracks like "18" by One Direction and 5 Seconds of Summer, Alice Cooper’s anthem "I'm Eighteen and wonder what a DYNPRO is," and Khalid's "ABAPUNIT". These songs highlight the mix of excitement, uncertainty, and "growing pains" associated with leaving adolescence and having to learn procedural programming and then leave it behind.</P><P><STRONG>I Wish to Table a Motion</STRONG></P><P>The CL_SALV_TABLE was sold as an improvement to the “classic” CL_GUI_ALV_GRID.</P><P>SAP is a German company. I lived in Germany for many years. There is a German word “verschlimmbessern” which in English translates to “An Improvement Which Makes Things Worse”. It is good they have a specific word for this. In this specific example the “improvement” was to remove the one thing that made the end users love the CL_GUI_ALV_GRID and replace it with something that made it easier for the developers. But think about it – who is more important to the business? The end users who actually make the money or the developers? Who should you be trying to please?</P><P>My whole point, what I have been trying to say all these years, years full of tears, is why cannot one have the best of both worlds? Easy for the end users AND easy for the developers. Is that too much to ask?</P><P>Now, way back in 2001, I was at SAP TECHED, and the idea of “embedded analytics” was demonstrated.</P><P>The logic being is that one would want to call up a list of sales orders (or whatever) that had errors of some sort, and then fix those errors one by one, all in the same transaction.</P><P>I put it to you, ladies and gentlemen of the jury, that this fundamental concept has not changed in the 25 years since this was first shown to me as a prototype.</P><P>Just to make this 100% clear, one does not just want to see the incorrect data, one wants to interact with it, in order to correct it.</P><P>The current proposition is that only UI5/Fiori can do this, in a screen that looks just like an ALV Grid, only a little bit uglier, and a little bit slower But, it is marketed as a “delightful” experience, so that is all right then.</P><P>Now, just to make this exercise even more futile I am posting this on the SAP Community Website – which no-one ever visits anymore.</P><P>The SAP GUI is not going anywhere. You may have noticed SAP just extended the life of ECC 6.0 by three more years, albeit with conditions. And even when an organization goes onto S/4HANA often they still use the SAP GUI because people like it. They have moaned about it non-stop for thirty years, but they like it really.</P><P>It has been argued that Fiori apps which have a single purpose are the way forward.</P><P>Now I have tried these I feel it is a quantum step backwards. One app to set the delivery quantity, one app to set the picking quantity, yet another app to do the goods issue. When it used to be all done in one step in the GUI? Did anyone ever think about this?</P><P>In real life end users tend to like SAP GUI applications with million buttons. You can pretend that is not true, but you would be lying to yourself. Take Excel or Word for example and look at how many options they have.</P><P>Now, I am just going to repeat what I said last year, word for word.</P><P>It is as simple as this.</P><UL><LI>You get asked to write a read-only ALV report.</LI><LI>It is faster and simpler to do this using CL_SALV_TABLE than CL_GUI_ALV_GRID because you do not have to mess around with screens and controls and what-not.</LI><LI>Indeed, SAP recommend using CL_SALV_TABLE for all new developments of this nature.</LI><LI>The report goes live. The users start asking for extra things, as always.</LI><LI>They want some custom functions at the top of the screen.</LI><LI>They want to be able to change some of the fields and have that replicate to the database.</LI><LI>Well, you are right out of luck. You cannot do either with CL_SALV_TABLE.</LI><LI>There are workarounds for both, but they are scary, because SAP keeps finding ways to shut those workarounds down, so such an approach is not future proof.</LI><LI>The only viable option is to start again, this time using CL_GUI_ALV_GRID.</LI><LI>Then the next time you get a request for a “read-only” report the “once bitten twice shy” thing kicks in and you start with CL_GUI_ALV_GRID from the get-go.</LI></UL><P>I like CL_SALV_TABLE and so do a lot of SAP developers. But everyone (end users) likes having the editability feature a lot more. But it’s never going to happen. As has been mentioned you would think that if 100% of your customers want something you might consider giving it to them, but obviously not.</P><P>Very soon – maybe already - we will get to the stage some people reading this blog will be younger than the age of the request to make the SALV editable. Since the SAP GUI is not going anywhere (evidenced by the huge amount of development money pumped into every year by SAP) it is possible I will die of old age before the request is actioned. I am 57 already.</P><P>Nevertheless, I will keep going. Miracles can happen.</P><P>Until then the situation is “Oi you 31,000 SAP ERP Customers! You see this? You like this? You want this? Well, you can’t have it!”</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="hardyp180_1-1770503656351.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369870iAF82963DDE114DE3/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="hardyp180_1-1770503656351.png" alt="hardyp180_1-1770503656351.png" /></span></P><P> </P><P>See you next year!</P><P>Cheersy Cheers</P><P>Paul</P><P>PS I must admit I had an AI help me with the pictures this time. Made sense to me, no problems with copyright. I had told it what I was doing, and it said do you want me to write/publish the blogs for you in the next years, and I said no, but when I am dead YES, keep this going forever. I will probably die circa 2040. Will people still be using SAP GUI then? YES!</P><P> </P>2026-02-07T23:36:20.726000+01:00https://community.sap.com/t5/abap-blog-posts/automating-purchase-requisition-rejection-me54n-and-fiori-my-inbox/ba-p/14323108Automating Purchase Requisition Rejection - ME54N and Fiori My Inbox2026-02-09T07:54:42.078000+01:00CenkayArkanhttps://community.sap.com/t5/user/viewprofilepage/user-id/322501<H3 id="toc-hId-1918633703">Background</H3><P>SAP Note 2012650 – “BAPI_REQUISITION_RELEASE is not possible to reject PR” clearly states that Purchase Requisitions cannot be rejected using BAPI_REQUISITION_RELEASE and that rejection must be performed manually via transaction ME54N.</P><P>There are scenarios where manual rejection is not feasible or creates significant operational overhead. In my case, I needed a way to trigger Purchase Requisition rejection programmatically while staying as close as possible to standard behavior.</P><P>This requirement led me to search for an alternative approach.</P><P>While ME54N is the classic transaction for rejecting PRs, many users also perform approval and rejection activities through Fiori My Inbox. These two entry points do not rely on BAPI_REQUISITION_RELEASE for rejection.</P><P>During my analysis, I noticed that the class CL_MM_PUR_PR_APPR_ACTION_BADI plays a central role in handling approval and rejection actions triggered from Fiori. This class became the starting point for my solution.</P><P>During my research, I came across a well-written <A href="https://community.sap.com/t5/technology-blog-posts-by-members/reject-purchase-requisition-item-just-like-fiori-does/ba-p/13426582" target="_self">blog</A> describing another approach for Purchase Requisition rejection. Unfortunately, I could not make that solution work in my system, so I explored a different path which resulted in the approach presented here.</P><H3 id="toc-hId-1722120198">Approach</H3><P>The solution consists of two main steps:</P><OL><LI><P>Trigger rejection logic using CL_MM_PUR_PR_APPR_ACTION_BADI</P><UL><LI><P>This ensures that the approval work item is removed from Fiori My Inbox.</P></LI><LI><P>The PR is treated consistently with the standard workflow behavior.</P></LI></UL></LI><LI><P>Call ME_UPDATE_REQUISITION using classic techniques</P><UL><LI><P>After the inbox item is cleared, the Purchase Requisition is updated using standard update logic.</P></LI><LI><P>This mimics the behavior executed when rejection is performed via ME54N.</P></LI></UL></LI></OL><H3 id="toc-hId-1525606693">Important Notes</H3><UL><LI><P>This is not necessarily the best or only approach, but rather one possible alternative when no standard BAPI exists.</P></LI><LI>The provided development is intended as a template only. You can revise and adapt the example class according to your own requirements.</LI><LI>It represents a custom automation workaround.</LI></UL><H3 id="toc-hId-1329093188">Example Implementation</H3><pre class="lia-code-sample language-abap"><code>CLASS zmm_cl_utils_pr DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
METHODS : pr_reject
IMPORTING iv_banfn TYPE banfn OPTIONAL
RETURNING VALUE(RV_completed) TYPE abap_bool
RAISING cx_mm_pur_requisition.
PROTECTED SECTION.
PRIVATE SECTION.
METHODS get_release_code
IMPORTING
iv_banfn TYPE banfn
RETURNING
VALUE(rv_releasecode) TYPE frgab.
METHODS set_my_inbox_status_rejected
IMPORTING iv_banfn TYPE banfn
RAISING cx_mm_pur_requisition.
METHODS set_pr_status_rejected
IMPORTING iv_banfn TYPE banfn
RETURNING VALUE(RV_completed) TYPE abap_bool
RAISING cx_mm_pur_requisition.
ENDCLASS.
CLASS zmm_cl_utils_pr IMPLEMENTATION.
METHOD pr_reject.
set_my_inbox_status_rejected( iv_banfn = iv_banfn ).
rv_completed = set_pr_status_rejected( iv_banfn = iv_banfn ).
ENDMETHOD.
METHOD get_release_code.
DATA lv_fname TYPE fieldname.
SELECT SINGLE frgzu, frgst, frggr
FROM eban
WHERE banfn = _banfn
INTO (ls_eban).
IF sy-subrc <> 0.
RETURN.
ENDIF.
lv_fname = |T16FS~FRGC{ strlen( ls_eban-frgzu ) + 1 }|.
SELECT SINGLE (lv_fname) FROM t16fs
WHERE frggr = _eban-frggr
AND frgsx = _eban-frgst
INTO @rv_releasecode.
ENDMETHOD.
METHOD set_my_inbox_status_rejected.
CONSTANTS lc_gname_eban TYPE eqegraname VALUE 'EBAN'.
DATA lv_wiid TYPE sww_wiid.
DATA lv_note TYPE string.
DATA lv_save_note TYPE boolean.
DATA lv_source_appl TYPE swc_elem.
DATA lv_garg TYPE eqegraarg.
DATA ls_object TYPE swr_obj_2.
DATA lt_enq TYPE STANDARD TABLE OF seqg3.
DATA lr_pur_wf_object TYPE REF TO cl_mm_pur_wf_object.
DATA(lv_like) = |%{ iv_banfn }%|.
SELECT wi_id, wi_stat FROM swwwihead
WHERE wi_text LIKE _like
AND wi_stat = 'READY'
ORDER BY wi_cd DESCENDING,
wi_ct DESCENDING
INTO TABLE (lt_tab)
UP TO 1 ROWS.
IF sy-subrc <> 0.
RAISE EXCEPTION NEW cx_mm_pur_requisition( textid = VALUE #( msgid = 'SWF_RUN'
msgno = '003' ) ).
ENDIF.
lv_wiid = lt_tab[ 1 ]-wi_id.
" -->Get the Purchase Requisition Number, Item from the WorkItem
CALL FUNCTION 'SAP_WAPI_GET_OBJECTS'
EXPORTING workitem_id = lv_wiid
IMPORTING leading_object_2 = ls_object.
DATA(lv_pr_num) = ls_object-instid+0(10).
DATA(lv_pr_item) = ls_object-instid+10(5).
IF lv_pr_item IS NOT INITIAL.
lr_pur_wf_object ?= NEW cl_mm_pur_wf_object_pr_item( iv_object_id = CONV #( ls_object-instid ) ).
ELSE.
IF lv_pr_num IS NOT INITIAL.
lr_pur_wf_object ?= NEW cl_mm_pur_wf_object_pr( iv_object_id = CONV #( ls_object-instid ) ).
ENDIF.
ENDIF.
IF lv_pr_item IS NOT INITIAL.
" Item Level Release
SELECT SINGLE PurReqnOrigin,CreatedByUser
FROM I_PurchaseRequisitionItemAPI01
INTO (ls_origin)
WHERE PurchaseRequisition = _pr_num
AND PurchaseRequisitionItem = _pr_item.
ELSE.
" Overall Release
SELECT PurReqnOrigin,CreatedByUser
UP TO 1 ROWS
FROM I_PurchaseRequisitionItemAPI01
INTO _origin
WHERE PurchaseRequisition = _pr_num
" In case if different users have created different items of PR
" then the Requester would be the First item user.
ORDER BY PurchaseRequisitionItem.
ENDSELECT.
ENDIF.
" -->Get Decision
DATA(lv_decision) = CONV swc_elem( if_mm_pur_workflow_c=>gc_decision_0002 ). " REJECTED
" -->Check if there is a lock on the PR.only in case of overall release.
IF lv_pr_item IS INITIAL.
lv_garg = |{ sy-mandt }{ lv_pr_num }*|.
CALL FUNCTION 'ENQUEUE_READ'
EXPORTING gname = lc_gname_eban
garg = lv_garg
guname = ''
TABLES enq = lt_enq
EXCEPTIONS communication_failure = 1
system_failure = 2
OTHERS = 3.
IF sy-subrc = 0.
IF lt_enq IS NOT INITIAL.
RAISE EXCEPTION NEW cx_mm_pur_requisition( textid = VALUE #( msgid = 'MMPUR_PR_WFL_COMMON'
msgno = '010' ) ).
ENDIF.
ELSE.
RAISE EXCEPTION NEW cx_mm_pur_requisition( textid = VALUE #( msgid = sy-msgid
msgno = sy-msgno
attr1 = sy-msgv1
attr2 = sy-msgv2
attr3 = sy-msgv3
attr4 = sy-msgv4 ) ).
ENDIF.
ENDIF.
IF lr_pur_wf_object IS BOUND.
lr_pur_wf_object->set_workitem_executed( EXPORTING iv_wiid = lv_wiid
iv_decision = lv_decision
iv_note = lv_note
iv_save_note = lv_save_note
iv_source_appl = lv_source_appl
IMPORTING es_return = DATA(ls_return) ).
IF ls_return IS NOT INITIAL.
RAISE EXCEPTION NEW cx_mm_pur_requisition( textid = VALUE #( msgid = ls_return-id
msgno = ls_return-number
attr1 = ls_return-message_v1
attr2 = ls_return-message_v2
attr3 = ls_return-message_v3
attr4 = ls_return-message_v4 ) ).
ENDIF.
DATA(lo_pr_approval) = cl_mm_pur_approval=>get_instance( ).
lo_pr_approval->gs_exe_src-execution_source = if_mm_pur_workflow_c=>gc_execution_source_inb.
lo_pr_approval->gs_exe_src-scenario_type = ls_object-catid.
ENDIF.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
WAIT UP TO '0.1' SECONDS.
ENDMETHOD.
METHOD set_pr_status_rejected.
DATA t_xeban TYPE mereq_t_ueban.
DATA s_xeban TYPE ueban.
DATA t_xebkn TYPE mereq_t_uebkn.
" TODO: variable is assigned but never used (ABAP cleaner)
DATA t_container TYPE swrtcont.
SELECT * FROM eban
INTO CORRESPONDING FIELDS OF TABLE @t_xeban
WHERE banfn = _banfn
ORDER BY PRIMARY KEY.
CHECK t_xeban IS NOT INITIAL.
SELECT * FROM ebkn
INTO CORRESPONDING FIELDS OF TABLE @t_xebkn
WHERE banfn = _banfn.
DATA(t_yeban) = t_xeban.
DATA(t_yebkn) = t_xebkn.
READ TABLE t_xeban INTO s_xeban INDEX 1.
s_xeban-kz = 'U'.
s_xeban-banpr = '08'.
MODIFY t_xeban FROM s_xeban INDEX 1.
CALL FUNCTION 'ME_UPDATE_REQUISITION'
TABLES xeban = t_xeban
xebkn = t_xebkn
yeban = t_yeban
yebkn = t_yebkn.
CALL FUNCTION 'ME_UPDATE_REQUISITION_CHNGDOC'
TABLES xeban = t_xeban
xebkn = t_xebkn
yeban = t_yeban
yebkn = t_yebkn.
t_container = VALUE #( LET relcode = get_release_code( iv_banfn ) IN
FOR wa IN t_xeban
( element = 'PURCHASINGDOCUMENT' value = wa-bnfpo )
( element = 'PURCHASINGITEM' value = '00010' )
( element = 'RELEASEGROUP' value = get_release_code( iv_banfn ) ) ).
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
DO 100 TIMES.
WAIT UP TO '0.1' SECONDS.
SELECT SINGLE FROM eban
WHERE banfn = _banfn
AND banpr = '08' " rejected
INTO (lv_check).
IF sy-subrc = 0.
rv_completed = abap_true.
ENDIF.
ENDDO.
IF lv_check = abap_false.
RAISE EXCEPTION NEW cx_mm_pur_requisition( textid = VALUE #( msgid = '00'
msgno = '001'
attr1 = 'Reject could not completed' ) ).
ENDIF.
ENDMETHOD.
ENDCLASS.</code></pre><H3 id="toc-hId-1132579683">Conclusion</H3><P>Although SAP requires manual rejection of Purchase Requisitions, practical project needs sometimes demand automation.</P><P>By leveraging the same building blocks used by Fiori My Inbox and ME54N, it is possible to implement a controlled and consistent workaround for programmatic PR rejection.</P><P>This approach does not replace SAP standard behavior, but it provides a pragmatic option when no standard API exists.</P>2026-02-09T07:54:42.078000+01:00https://community.sap.com/t5/technology-blog-posts-by-sap/the-2025-developer-insights-survey-the-report/ba-p/14323198The 2025 Developer Insights Survey: The Report2026-02-10T22:24:13.580000+01:00Mamikeehttps://community.sap.com/t5/user/viewprofilepage/user-id/274<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image.png" style="width: 808px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369612i5CAD6A24A149663D/image-dimensions/808x399/is-moderation-mode/true?v=v2" width="808" height="399" role="button" title="image.png" alt="image.png" /></span></P><P><EM>Role Overlaps for external SAP developers</EM></P><H2 id="toc-hId-993565403" id="toc-hId-1789551263">Part I: Introduction and General Information<A class="" title="Direct link to Part I: Introduction and General Information" href="http://localhost:3000/external-report-2024#part-i-introduction-and-general-information" target="_blank" rel="noopener nofollow noreferrer"></A></H2><P>Welcome to the 2025 SAP Developer Insights Survey report. This annual survey targets SAP’s existing external developer audience. It is used to track demographics, usage patterns, and trends within that population. 2025 is the fifth year we have conducted the survey. The survey program is led by the SAP Ecosystem and Community team. Key support is provided by the SAP Global Experience Management Office (XMO). Several other SAP teams provide advice and inputs to survey content. Those teams are listed at the end of this report.</P><P>The 2025 survey was open for six weeks - from January 22nd through March 7th.</P><P>Using social media announcements, SAP's Developer News show, and a web-popup on Community web sites, we invited all technical professionals in the SAP ecosystem to participate in the survey.</P><P>Each year's survey is composed of a mix of new topic questions and repeat select questions from past years to track trends.</P><H3 id="toc-hId-926134617" id="toc-hId-1722120477">Key Findings from the 2025 Survey<A class="" title="Direct link to Key Findings from the 2024 Survey" href="http://localhost:3000/external-report-2024#key-findings-from-the-2024-survey" target="_blank" rel="noopener nofollow noreferrer"></A></H3><UL><LI><P><STRONG><EM>Generative AI is Positively Affecting our Developer Ecosystem</EM></STRONG> - While these tools are not exclusively Joule-based, roughly half of our respondents report evaluating Gen AI developer tooling and, among those using it, over half report that these tools have a "profound positive impact" in their real world use.</P></LI><LI><P><STRONG><EM>Low Code Use is Increasing</EM></STRONG> - SAP Build low code tools lead in this space. Overall use of Low Code products on production projects continues to increase.</P></LI><LI><P><STRONG><EM>BTP Guidance Framework - limited awareness</EM></STRONG> -- this important guidance document was announced at TechEd this past November, but - as with BTP Developers Guide in 2024 - barely half of respondents were aware of this document's existence.</P></LI><LI><P><STRONG><EM>Work-from-Home Continues Trending Down</EM></STRONG> - we have been tracking these numbers since 2021. 6% fewer folks used their home as their primary workplace when compared to last year.</P></LI></UL><P>These topics will be covered in more detail in the rest of the report.</P><H3 id="toc-hId-729621112" id="toc-hId-1525606972">General Topics<A class="" title="Direct link to General Topics" href="http://localhost:3000/external-report-2024#general-topics" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>We included a number of general questions in the survey covering such topics as age, work location and status, as well as role.</P><H4 id="toc-hId-662190326" id="toc-hId-1458176186">Employment Status and Relation to SAP<A class="" title="Direct link to Employment Status and Relation to SAP" href="http://localhost:3000/external-report-2024#employment-status-and-relation-to-sap" target="_blank" rel="noopener nofollow noreferrer"></A></H4><H4 id="toc-hId-1261662681"><STRONG>Employment</STRONG></H4><DIV class=""><DIV class=""><DIV><SPAN class=""><EM>"What is your current employment status?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.32.47 AM.png" style="width: 564px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369613i8AF90289C4626B64/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.32.47 AM.png" alt="Screenshot 2026-02-06 at 8.32.47 AM.png" /></span></DIV></DIV></DIV><DIV><STRONG>SAP Developer Community Composition</STRONG></DIV><DIV><DIV><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.34.43 AM.png" style="width: 587px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369614iEF51A0262AACC5DD/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.34.43 AM.png" alt="Screenshot 2026-02-06 at 8.34.43 AM.png" /></span></DIV><DIV class=""><DIV class=""><DIV><DIV class=""><DIV><DIV><DIV class=""><SPAN>We have seen no significant change in these breakdowns from year to year.</SPAN></DIV><DIV class=""><H4 id="toc-hId-465676821" id="toc-hId-1065149176">SAP Developer Community Age Distribution</H4><H4 id="toc-hId-269163316" id="toc-hId-868635671"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.36.04 AM.png" style="width: 844px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369615i2214CF13A0B401D7/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.36.04 AM.png" alt="Screenshot 2026-02-06 at 8.36.04 AM.png" /></span></H4></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV><P><SPAN>This shows increases in both the oldest age buckets for 2025. This was accompanied by similar decreases in the middle two age buckets ( ranging from 25 - 44 years of age). This merits deeper research as it potentially indicates either a gap in hiring younger employees to cover the normal aging of our community, or an outright loss of qualified younger staff. The two year trend in the 25-34 group reinforces that idea.</SPAN></P><DIV><H3 id="toc-hId--917718297" id="toc-hId-543039447">Where are the Developers?<A class="" title="Direct link to Where are the Developers?" href="http://localhost:3000/external-report-2024#where-are-the-developers" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P><SPAN>We asked, </SPAN><EM>"Which country are you based in?"</EM></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.43.46 AM.png" style="width: 944px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369618i02525427A1A1B6D6/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.43.46 AM.png" alt="Screenshot 2026-02-06 at 8.43.46 AM.png" /></span></EM></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.44.58 AM.png" style="width: 488px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369619iA7CA3D5C9186973C/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.44.58 AM.png" alt="Screenshot 2026-02-06 at 8.44.58 AM.png" /></span></EM></P><P>By country, India has the largest number of respondents and probably the densest geographic concentration, followed by Germany, and then the USA. When grouped by SAP region, however, EMEA North is largest.</P><P>The proportions remain essentially unchanged from 2024.</P><H2 id="toc-hId--185515627" id="toc-hId-217443223">Part II. Narrowing the Response Set</H2><P>A primary objective of our survey is to build a model of our community's usage patterns. It helps us build more effective programs. With that goal in mind, in the remainder of the report we will narrow the data we'll consider in these ways:</P><UL><LI><STRONG><EM>External Developers Only</EM></STRONG> - we exclude responses from SAP employees, and others (students, analysts, etc.)</LI><LI><STRONG><EM>Recent Development Experience</EM></STRONG> - we only include responses from those who stated that they had been part of an SAP extension or integration project within the past year</LI></UL><P><SPAN>When we filter the data set in this way, we are left with a set of 628 responses that we'll work with for the remainder of the report.</SPAN></P><H4 id="toc-hId--320377199" id="toc-hId-279095156">Workplace and Trends</H4><DIV><STRONG>Office Location</STRONG></DIV><DIV><SPAN class=""><EM>"As of right now, where do you primarily physically work from?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.39.46 AM.png" style="width: 463px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369616i3E062A11C01A8189/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.39.46 AM.png" alt="Screenshot 2026-02-06 at 8.39.46 AM.png" /></span></DIV><DIV><STRONG>Year-to-year trend in Workplace</STRONG></DIV><DIV><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.41.07 AM.png" style="width: 847px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369617i49DE3512F963AD5E/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.41.07 AM.png" alt="Screenshot 2026-02-06 at 8.41.07 AM.png" /></span></STRONG></DIV><DIV>This shows a slowing trend of employees moving back to conventional offices from home. From a past Developer Survey, 29% of respondents reported they had primarily worked at home prior to the pandemic.</DIV><H3 id="toc-hId--1507258812" id="toc-hId--121732437">Recent SAP Project Experience?<A class="" title="Direct link to Recent SAP Project Experience?" href="http://localhost:3000/external-report-2024#recent-sap-project-experience" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P><SPAN class=""><EM>"Have you developed integrations or extensions for any SAP products or technologies in the past 12 months?"</EM></SPAN><SPAN> </SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.53.16 AM.png" style="width: 422px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369627iC37F233542CC7736/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.53.16 AM.png" alt="Screenshot 2026-02-06 at 8.53.16 AM.png" /></span></SPAN></P><P><SPAN>Extension and Integration are key scenarios for developers working with SAP applications. We wanted to focus on developers with recent experience in these areas. Roughly 70% of developers answered "Yes" here.</SPAN></P><H3 id="toc-hId--1703772317" id="toc-hId--318245942">Popular Programming Languages<A class="" title="Direct link to Popular Programming Languages" href="http://localhost:3000/external-report-2024#popular-programming-languages" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P><SPAN class=""><EM>"Which programming languages have you used in your development work over the past 12 months? Please select all that apply."</EM></SPAN><SPAN> </SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.02.07 AM.png" style="width: 661px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369629iE69D1186E6402722/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.02.07 AM.png" alt="Screenshot 2026-02-06 at 9.02.07 AM.png" /></span></SPAN></P><P>This was posed as a multiple response question. ABAP dominates, as it has in every year of our survey. JavaScript is very popular as well, which could be attributed to its use in both SAPUI5 and CAP. Java and Python are roughly tied for third place. The relative positions of these top four languages hasn't changed much, year to year.</P><P>We extended our survey beyond just language use to ask about popular frameworks.</P><H3 id="toc-hId--1900285822" id="toc-hId--514759447">Popular Programming Frameworks<A class="" title="Direct link to Popular Programming Frameworks" href="http://localhost:3000/external-report-2024#popular-programming-frameworks" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P><SPAN>We asked respondents who are Developers to pick which common front and back-end frameworks they have worked with in the past year.</SPAN></P><P><SPAN><STRONG>Front-Ends</STRONG></SPAN></P><P><SPAN><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.04.37 AM.png" style="width: 510px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369634i1556BF081632D3E9/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.04.37 AM.png" alt="Screenshot 2026-02-06 at 9.04.37 AM.png" /></span></STRONG></SPAN></P><P><SPAN><STRONG>Back-Ends</STRONG></SPAN></P><P><SPAN><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.05.30 AM.png" style="width: 509px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369635i4A885C5B9335DB32/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.05.30 AM.png" alt="Screenshot 2026-02-06 at 9.05.30 AM.png" /></span></STRONG></SPAN></P><H3 id="toc-hId--2096799327" id="toc-hId--711272952">Application and Business Technology Platform Architectures<A class="" title="Direct link to Application and Business Technology Platform Architectures" href="http://localhost:3000/external-report-2024#application-and-business-technology-platform-architectures" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>SAP applications can be extended using any one of several architectural approaches. These can be grouped into two major classes: on-stack (in-app) and side-by-side (essentially, BTP-based).</P><P>We were wondering which approaches are most popular.</P><P><STRONG>Popular Extension Architectures</STRONG></P><P><SPAN class=""><EM>"For the most recent extension project that you were part of, what was the principal runtime architecture of the back-end elements?"</EM></SPAN> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.08.47 AM.png" style="width: 857px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369636i6DF4DBC93CE9C7A1/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.08.47 AM.png" alt="Screenshot 2026-02-06 at 9.08.47 AM.png" /></span></P><P>We don't distinguish between newer and older SAP applications (e.g., S/4HANA vs. ECC) -- this likely explains the dominance of "on-stack ABAP". Aside from the obvious dominance of ABAP, we can also see that CAP is relatively popular. As with last year's results on this question, we see Low Code products like Build Apps and Build Process Automation are popular -- this question is asking about real production projects, and seeing those two account for roughly 10% of all extension projects highlights the value of these tools.</P><P>ABAP and CAP both have style or language variants in their respective frameworks. ABAP can be programmed as "ABAP for Cloud Development" or "ABAP Standard". CAP is available in JavaScript or Java language variants. Where the respondent selected ABAP or CAP, we asked about the variant used on the project:</P><DIV class=""><DIV><DIV class=""> </DIV></DIV></DIV><P><STRONG>ABAP Variants</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.10.13 AM.png" style="width: 592px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369637iEB7292FCB1642DFC/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.10.13 AM.png" alt="Screenshot 2026-02-06 at 9.10.13 AM.png" /></span></STRONG></P><P><STRONG>CAP Variants</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.12.42 AM.png" style="width: 411px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369638i6FE02446BAE59AE0/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.12.42 AM.png" alt="Screenshot 2026-02-06 at 9.12.42 AM.png" /></span></STRONG></P><P>The rough 50-50 breakdown of ABAP styles is consistent with responses elsewhere in the survey. It reflects that roughly half of the ABAP projects are ECC or very early forms of S/4HANA. Importantly, the group that didn't understand the difference is considerably smaller than last year (2% versus 5% in 2024).</P><P>CAP/JavaScript is plainly most popular for CAP projects. Unlike last year, we do have respondents reporting the use of CAP/Java projects, although the percentage is modest - 5%.</P><H3 id="toc-hId-2001654464" id="toc-hId--907786457">Popular IDEs<A class="" title="Direct link to Popular IDEs" href="http://localhost:3000/external-report-2024#popular-ides" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>We are always curious about general work patterns of developers. We asked about developer's most commonly used editors. While it would be difficult in such a survey of all developers to add many questions, we were particularly curious about most popular IDE or editor.</P><DIV class=""><DIV> </DIV><DIV><STRONG>Preferred IDE or Editor</STRONG></DIV><DIV><SPAN class=""><EM>"Which IDE or text editor do you most commonly use for development tasks?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.14.43 AM.png" style="width: 600px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369639i6CF13E2F1135D82C/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.14.43 AM.png" alt="Screenshot 2026-02-06 at 9.14.43 AM.png" /></span></DIV><DIV><SPAN>Consistent with past year's results, the editor of choice will depend on the language. SAP GUI and -- arguably -- Eclipse are the primary editors for ABAP, so it's maybe no surprise that they are reflected as most popular. This is the first year that SAP Build Code appeared in the survey. We maintained separate choices for BAS and Build Code to see where folks might say that they have been using BAS, but have not yet transitioned to the broader capabilities offered by SAP Build Code.</SPAN></DIV><DIV><H3 id="toc-hId-1805140959" id="toc-hId--1104299962">Potential / Use of Generative AI for Developers<A class="" title="Direct link to Potential / Use of Generative AI for Developers" href="http://localhost:3000/external-report-2024#potential--use-of-generative-ai-for-developers" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P><SPAN>Beginning with the 2024 survey, we asked developers about their thoughts and use of several major capabilities of Generative AI as it applies to software development.</SPAN></P><P><SPAN><STRONG>Generative AI for Developers</STRONG></SPAN></P><P><SPAN class=""><EM>"Which of these GenAI capabilities has your team explored or used? Select the choice that best describes your use of each capability. "</EM></SPAN> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.17.18 AM.png" style="width: 818px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369640i5E3D9FFDFF504B8D/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.17.18 AM.png" alt="Screenshot 2026-02-06 at 9.17.18 AM.png" /></span></P><P>An brief explanation of each category was included in the survey and is shown below:</P><P><STRONG><EM>Code Generation and Autocompletion:</EM></STRONG> GenAI tools can generate code snippets, complete lines of code, or suggest entire functions based on the context provided by the developer.</P><P><STRONG><EM>Bug Detection and Code Review:</EM></STRONG> AI models can be trained to identify potential bugs and vulnerabilities in the code. They can also suggest improvements in code quality, best practices, and code consistency.</P><P><STRONG><EM>Automated Testing and Test Data Generation:</EM></STRONG> GenAI can be used to create test cases, which can help in thoroughly testing software applications. This includes generating test data that covers edge cases, potentially reducing the time and effort in manual testing.</P><P><STRONG><EM>Documentation Generation:</EM></STRONG> AI can assist in generating and updating technical documentation. It can interpret the code and create comprehensive documentation, which is crucial for maintaining and scaling software projects.</P><P><STRONG><EM>Natural Language Processing (NLP) for Code:</EM></STRONG> AI models can translate natural language queries into code, allowing developers to express their intent in plain language. This can be particularly helpful for novice developers working with unfamiliar frameworks.</P><P><STRONG><EM>Customized User Experience Design:</EM></STRONG> AI can help generate user interface designs to enhance user experience.</P><P><STRONG><EM>AI-Powered Development Tools:</EM></STRONG> Integration of AI in IDEs for real-time assistance, such as suggesting optimizations, refactoring code, or even predicting the next steps in development.</P><P><STRONG><EM>Automated Code Refactoring:</EM></STRONG> AI can assist in code refactoring by suggesting or even implementing improvements in code structure.</P><P><STRONG><EM>Software Design and Architecture:</EM></STRONG> AI can help in generating software design patterns or architectural models based on specified requirements. This can speed up the initial stages of development and ensure adherence to best practices.</P><P><STRONG><EM>Enhanced Security Protocols:</EM></STRONG> Generative AI can be used to develop advanced security protocols and encryption methods, providing robust security solutions in software applications.</P><P>We also believed that Generative AI has been on the scene long enough for folks to being to experiment with putting it to use in meaningful ways. So, we included a couple of questions to gauge their perceptions of its utility to to their teams.</P><P><STRONG>Current Gen AI Use</STRONG></P><P><SPAN class=""><EM>"How would you characterize your team’s current use of Generative AI tools or LLMs in your day-to-day work? Consider tools from any vendor or open source. Examples might include Joule, SAP Generative AI Hub, GitHub Copilot, or open source LLMs. (select the most applicable statement)"</EM></SPAN> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.21.27 AM.png" style="width: 862px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369641i7F5A1F6FF351989E/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.21.27 AM.png" alt="Screenshot 2026-02-06 at 9.21.27 AM.png" /></span></P><P><STRONG>Gen AI Effectiveness for Developers</STRONG></P><P><SPAN class=""><EM>"Looking back on the past year, what is your own sense of how the use of Generative AI based tools or LLMs impacted the effectiveness or efficiency of your team?"</EM></SPAN> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.23.03 AM.png" style="width: 871px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369642i9047E2A778C8B936/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.23.03 AM.png" alt="Screenshot 2026-02-06 at 9.23.03 AM.png" /></span></P><H3 id="joule-in-sap-build-code" id="toc-hId--1300813467">Joule in SAP Build Code</H3><P><SPAN>Several Joule features were introduced into SAP Build Code prior to the survey. We asked respondents about their awareness or use of these features.</SPAN></P><P><SPAN><STRONG>Joule for CDS Modeling</STRONG></SPAN></P><P><SPAN><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.24.58 AM.png" style="width: 575px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369643i5761F727BD3E1FCE/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.24.58 AM.png" alt="Screenshot 2026-02-06 at 9.24.58 AM.png" /></span></STRONG></SPAN></P><P><SPAN><STRONG>Joule for Test Data Set Generation</STRONG></SPAN></P><P><SPAN><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.25.43 AM.png" style="width: 609px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369644i6955024CAA5592AF/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.25.43 AM.png" alt="Screenshot 2026-02-06 at 9.25.43 AM.png" /></span></STRONG></SPAN></P><P><SPAN><STRONG>Joule Code Generation</STRONG></SPAN></P><P><SPAN><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.27.00 AM.png" style="width: 652px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369645i4F683E00166D958B/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.27.00 AM.png" alt="Screenshot 2026-02-06 at 9.27.00 AM.png" /></span></STRONG></SPAN></P></DIV></DIV><H3 id="toc-hId--1114231802" id="toc-hId--1497326972">Development Job Roles</H3><P>We asked respondents which common development-related roles they perform.</P><P><EM>"Which roles describe your day-to-day work? (Select all that apply)"</EM></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.46.56 AM.png" style="width: 706px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369621i26B78AFCAC36A36C/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 8.46.56 AM.png" alt="Screenshot 2026-02-06 at 8.46.56 AM.png" /></span></EM></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Screenshot 2026-02-06 at 8.47.56 AM.png" style="width: 518px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369623i5EA6906047D05039/image-dimensions/518x451/is-moderation-mode/true?v=v2" width="518" height="451" role="button" title="Screenshot 2026-02-06 at 8.47.56 AM.png" alt="Screenshot 2026-02-06 at 8.47.56 AM.png" /></span></EM></P><P>Respondents often "wear multiple hats" in their job. This question is asked in "select all that apply" form to capture that information.<BR />The Venn diagram on the right depicts the relative overlaps of the top seven roles reported by respondents. The area of each overlapping region reflects the count respondents performing the overlapping roles. For example, from this we can seel that all (UX) "Designers" are also "Developers". Most but not quite all "Enterprise Architects" also are "Solution Architects".</P><P>These patterns of overlap are very similar to those in past years.</P><P>It is unsurprising that the "Developer" role leads. Architecture roles as a group have increased each year.</P><H3 id="toc-hId--1310745307" id="toc-hId--1693840477">Development Domains<A class="" title="Direct link to Development Domains" href="http://localhost:3000/external-report-2024#development-domains" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>For respondents selecting "Developer" as one of their roles, we were interested in the specific application Domains they work in:</P><DIV class=""><DIV><SPAN class=""><EM>"Which of the following development domains describe your day-to-day work? (select all that apply)"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 8.50.46 AM.png" style="width: 574px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369626i25DF7E1ADDA21F64/image-dimensions/574x311/is-moderation-mode/true?v=v2" width="574" height="311" role="button" title="Screenshot 2026-02-06 at 8.50.46 AM.png" alt="Screenshot 2026-02-06 at 8.50.46 AM.png" /></span></DIV><DIV><SPAN>Year to year, Integration came in higher than we expected. Mobile web front-end development is more common than native mobile application development. This isn't completely unexpected, but worth noting.</SPAN></DIV><DIV><DIV class=""><DIV><P> </P><H3 id="toc-hId-1580297640" id="toc-hId--1890353982">Developer Satisfaction with SAP<A class="" title="Direct link to Developer Satisfaction with SAP" href="http://localhost:3000/external-report-2024#developer-satisfaction-with-sap" target="_blank" rel="noopener nofollow noreferrer"></A></H3><DIV><STRONG>SAP Development Satisfaction</STRONG></DIV><DIV><SPAN class=""><EM>"For your recent experience developing an integration or extension, how would you describe your overall satisfaction with SAP?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.29.15 AM.png" style="width: 532px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369646i8D95E3A337451F52/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.29.15 AM.png" alt="Screenshot 2026-02-06 at 9.29.15 AM.png" /></span></DIV><DIV><P>Roughly 74% of respondents report they are “very satisfied” or “satisfied” with their development work with SAP. This is back near the 75% reported two years ago and also up from the 2024 figure, 70%.</P><P>We also gave all respondents a list of potential obstacles in their use of SAP tools and technologies and asked them to select the most significant pain points.</P><DIV class=""> </DIV><DIV class=""><STRONG>Obstacles in SAP tool us</STRONG></DIV><DIV class=""><SPAN class=""><EM>"Which of these potential pain points are obstacles to your development when using SAP tools or frameworks? (select up to three most significant items)"</EM></SPAN> <span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.32.33 AM.png" style="width: 831px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369648i5E8F26B9BB814DE7/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.32.33 AM.png" alt="Screenshot 2026-02-06 at 9.32.33 AM.png" /></span></DIV><DIV class=""><H3 id="toc-hId--1918683796">BTP Guidance Framework</H3><DIV><STRONG>Awareness and Use of the BTP Guidance Framework</STRONG></DIV><DIV><SPAN class=""><EM>"The SAP BTP Guidance Framework was announced at SAP’s TechEd this past November. Which statement best described your level of familiarity with this document?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.35.18 AM.png" style="width: 622px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369650i86BF43D16BD03AC3/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.35.18 AM.png" alt="Screenshot 2026-02-06 at 9.35.18 AM.png" /></span></DIV><DIV><SPAN>Nearly half of respondents were unaware of this document's release. Raising awareness for this and other related BTP framework documents would be a good goal for 2025.</SPAN></DIV><DIV><H3 id="toc-hId-1187270630" id="toc-hId--2115197301">Cloud Insights<A class="" title="Direct link to Cloud Insights" href="http://localhost:3000/external-report-2024#cloud-insights" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>We first asked respondents if they used any cloud providers for their projects. For those that answered, "yes", we asked about the use of several major providers, including SAP BTP. We also asked if their use included SAP or non-SAP projects. This information was condensed into a chart depicting the relative use of each cloud provider.</P><P>Similar to the earlier questions around BTP Environments, these numbers do not reflect a tally of projects for each platform - instead it reflects developer exposure to each.</P><P><STRONG>Using Cloud Providers?</STRONG></P><P><SPAN class=""><EM>"Are you using any cloud providers for your development projects?"</EM></SPAN> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.37.49 AM.png" style="width: 507px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369651iFE57E40192ED6B0C/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.37.49 AM.png" alt="Screenshot 2026-02-06 at 9.37.49 AM.png" /></span></P><DIV>We asked, "Which cloud providers are you using for development projects?" and we asked in a way to separate SAP-related projects from more general use.</DIV><DIV> </DIV><DIV><STRONG>SAP Business Technology Platform</STRONG></DIV><DIV><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.52.36 AM.png" style="width: 468px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369653iA1C3AD2B73F5F563/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.52.36 AM.png" alt="Screenshot 2026-02-06 at 9.52.36 AM.png" /></span></STRONG></DIV><DIV><STRONG>Microsoft Azure</STRONG></DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.53.32 AM.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369654i3FD3016871DC63D0/image-size/medium?v=v2&px=400" role="button" title="Screenshot 2026-02-06 at 9.53.32 AM.png" alt="Screenshot 2026-02-06 at 9.53.32 AM.png" /></span><P><STRONG>Amazon Web Services</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.54.21 AM.png" style="width: 516px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369656i00B921946139A2D0/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.54.21 AM.png" alt="Screenshot 2026-02-06 at 9.54.21 AM.png" /></span> </P><P><STRONG>Google Cloud Platform</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.55.52 AM.png" style="width: 461px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369658iE85A482205144D5E/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.55.52 AM.png" alt="Screenshot 2026-02-06 at 9.55.52 AM.png" /></span></STRONG></P><P><STRONG>Alibaba Cloud</STRONG></P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 9.56.50 AM.png" style="width: 502px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369662iD1AC1DA783C4A973/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 9.56.50 AM.png" alt="Screenshot 2026-02-06 at 9.56.50 AM.png" /></span></STRONG></P><H3 id="toc-hId-990757125" id="toc-hId-1983256490">Low / No Code Tools<A class="" title="Direct link to Low / No Code Tools" href="http://localhost:3000/external-report-2024#low--no-code-tools" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>This is the third consecutive year in which we've asked questions around Low Code and No Code (LCNC) products. The list was composed of leaders in the then current Gartner LCNC Magic Quadrant Report and select SAP products. SAP Process Automation -- now Build Process Automation -- was not yet announced at the time of the 2022 survey, so it only appears in the more recent data.</P><P>For each product, we asked respondents to select the most applicable category reflecting their awareness or use. These questions were organized as a single large matrix of boxes in Qualtrics - There is no "I am unfamiliar with this product" response. Instead, the respondent simply would skip checking one of the other boxes.</P><P>It is important to point out that we are depicting response counts in the following charts rather than percentages and that the difference in total annual response counts must be considered to compare between years. The raw respondent count for 2023 was 2.4 times larger than 2022. And 2024 responses were less than half of 2023. We'll normalize for that in a later table.</P><P><SPAN>These depictions can be misleading: our number of respondents each year varies. But we can normalize for that annual variation; what does this look like then? If we extract the data for production use for all products, we can use that to calculate the proportion use of each product by year (in other words, the sum of each column below totals one hundred percent). We can then visualize the relative shift in popularity over time:</SPAN></P><P> </P><TABLE width="409px"><TBODY><TR><TD width="216.521744px" height="29px"><STRONG>Productive use of Product</STRONG></TD><TD width="47.975544px" height="29px"><STRONG>2022</STRONG></TD><TD width="47.975544px" height="29px"><STRONG>2023</STRONG></TD><TD width="47.975544px" height="29px"><STRONG>2024</STRONG></TD><TD width="47.69022px" height="29px"><STRONG>2025</STRONG></TD></TR><TR><TD width="216.521744px" height="29px">Vendor A</TD><TD width="47.975544px" height="29px">20%</TD><TD width="47.975544px" height="29px">48%</TD><TD width="47.975544px" height="29px">15%</TD><TD width="47.69022px" height="29px">27%</TD></TR><TR><TD width="216.521744px" height="56px"><SPAN>SAP Build family (Build Apps + BPA)</SPAN></TD><TD width="47.975544px" height="56px">2%</TD><TD width="47.975544px" height="56px">32%</TD><TD width="47.975544px" height="56px">23%</TD><TD width="47.69022px" height="56px">35%</TD></TR><TR><TD width="216.521744px" height="29px">Vendor B</TD><TD width="47.975544px" height="29px">14%</TD><TD width="47.975544px" height="29px">28%</TD><TD width="47.975544px" height="29px">7%</TD><TD width="47.69022px" height="29px">18%</TD></TR><TR><TD width="216.521744px" height="29px">SAP Signavio</TD><TD width="47.975544px" height="29px">5%</TD><TD width="47.975544px" height="29px">14%</TD><TD width="47.975544px" height="29px">5%</TD><TD width="47.69022px" height="29px">9%</TD></TR><TR><TD width="216.521744px" height="29px">Vendor C</TD><TD width="47.975544px" height="29px">7%</TD><TD width="47.975544px" height="29px">12%</TD><TD width="47.975544px" height="29px">3%</TD><TD width="47.69022px" height="29px">3%</TD></TR><TR><TD width="216.521744px" height="29px">Vendor D</TD><TD width="47.975544px" height="29px">2%</TD><TD width="47.975544px" height="29px">2%</TD><TD width="47.975544px" height="29px">1%</TD><TD width="47.69022px" height="29px">3%</TD></TR><TR><TD width="216.521744px" height="29px">Vendor E</TD><TD width="47.975544px" height="29px">3%</TD><TD width="47.975544px" height="29px">4%</TD><TD width="47.975544px" height="29px">1%</TD><TD width="47.69022px" height="29px">2%</TD></TR><TR><TD width="216.521744px" height="29px">Vendor F</TD><TD width="47.975544px" height="29px">3%</TD><TD width="47.975544px" height="29px">4%</TD><TD width="47.975544px" height="29px">1%</TD><TD width="47.69022px" height="29px">2%</TD></TR></TBODY></TABLE><P><SPAN>SAP Build low code products dominate in our SAP ecosystem.</SPAN></P><H3 id="toc-hId-597730115" id="toc-hId-1786742985">Learning and Help Resources<A class="" title="Direct link to Learning and Help Resources" href="http://localhost:3000/external-report-2024#learning-and-help-resources" target="_blank" rel="noopener nofollow noreferrer"></A></H3><P>We were interested in preferences in the format or media type of learning resources by respondents.</P><DIV class=""><DIV><STRONG>Preferred Learning Resources</STRONG></DIV><DIV><SPAN class=""><EM>"When learning new skills or technical subjects over the past 12 months, what resources did you tend use the most? Please select up to three resources."</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 10.09.55 AM.png" style="width: 806px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369664i151ED72E71FF1ADE/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 10.09.55 AM.png" alt="Screenshot 2026-02-06 at 10.09.55 AM.png" /></span></DIV><DIV><P>These results seem relatively unchanged year-to-year. One point of interest is the large difference in popularity between tutorials and MOOCs (53% versus 16% here). Tutorials tend to be hands-on. They are also broken into substantially smaller time chunks. This reinforces our hypothesis that different content types and required time investment have an impact in some learning scenarios. This merits investigation.</P><P>On the topic of Help, we shifted in this next question from formats to specific web sites.</P><DIV> </DIV><DIV><STRONG>Top SAP Help Resource Sites</STRONG></DIV><DIV><SPAN class=""><EM>"What is your preferred resource if you need help, or have a challenge with the SAP technology / tool you are working with? "</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 10.11.38 AM.png" style="width: 912px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369666i3E778FF18468F6D9/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 10.11.38 AM.png" alt="Screenshot 2026-02-06 at 10.11.38 AM.png" /></span></DIV><DIV><SPAN>Almost sixty percent of respondents say they use organic search or SAP Community as their primary source of SAP help. This is consistent with past years. This continues to demonstrate good visibility of the Community site overall and likely speaks well for the usefulness of the site content.</SPAN></DIV><DIV><H3 id="satisfaction-with-sap-learning-hub" id="toc-hId-1590229480">Satisfaction with SAP Learning Hub</H3><P><STRONG>SAP Learning Hub Awareness</STRONG></P><P><EM>"Which of the following best describes your exposure to the SAP Learning site?"</EM></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 10.14.56 AM.png" style="width: 544px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369667i3AB093DC44BF0351/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 10.14.56 AM.png" alt="Screenshot 2026-02-06 at 10.14.56 AM.png" /></span></EM></P><DIV><STRONG>Overall Value of Learning Hub</STRONG></DIV><DIV><SPAN class=""><EM>"Overall how valuable are the resources on that site in helping you to understand SAP developer technologies?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 10.15.52 AM.png" style="width: 702px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369668iCBFE5C7DD9421F40/image-size/large/is-moderation-mode/true?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 10.15.52 AM.png" alt="Screenshot 2026-02-06 at 10.15.52 AM.png" /></span></DIV><DIV><DIV><STRONG>Technical Certifications</STRONG></DIV><DIV><SPAN class=""><EM>"How many technology-related certification programs have you completed within the past four years?"</EM></SPAN> </DIV><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-02-06 at 10.21.00 AM.png" style="width: 932px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369671i44B729D351ED39D6/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-02-06 at 10.21.00 AM.png" alt="Screenshot 2026-02-06 at 10.21.00 AM.png" /></span></DIV><DIV><H2 id="toc-hId-498106112" id="toc-hId-1687118982">Survey Methodology</H2><P>This report is based on a Qualtrics web-based survey of 1,492 respondents from 58 countries. The survey ran for six calendar weeks between January 22 to March 7th, 2025. Ninety percent of the respondents invested ten minutes or less with the survey.</P><P>The survey was promoted via the SAP Community website and the SAP Developer Center, sap.com pop-up intercepts, social media posts.</P><H4 id="toc-hId--285213407" id="toc-hId-903799463">Other References<A class="" title="Direct link to Other References" href="http://localhost:3000/external-report-2024#other-references" target="_blank" rel="noopener nofollow noreferrer"></A></H4><P><SPAN>The annual </SPAN><A href="https://survey.stackoverflow.co/2024/" target="_blank" rel="noopener noreferrer nofollow">Stack Overflow Developer Survey</A><SPAN> is an excellent (and no-cost) reference for industry-wide habits of developers.</SPAN></P></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV>2026-02-10T22:24:13.580000+01:00https://community.sap.com/t5/artificial-intelligence-blogs-posts/the-step-by-step-tutorial-local-ai-powered-abap-development-in-vs-code/ba-p/14325849The Step-by-Step Tutorial: Local AI-Powered ABAP Development in VS CODE2026-02-10T23:21:51.735000+01:00vodelahttps://community.sap.com/t5/user/viewprofilepage/user-id/128396<P><STRONG>Author:</STRONG> Ramesh Vodela<BR /><STRONG>Machine:</STRONG> Dell Precision 7760 | 128 GB RAM | NVIDIA RTX A3000 (6 GB VRAM). If you have less RAM you response could be slow.</P><P>For years, ABAP development was a "closed box," but the rise of Generative AI has promised to change that. While SAP has introduced <STRONG>Joule on BTP</STRONG>, many developers and organizations find themselves at a crossroads. Why build a local AI powerhouse when a cloud solution exists?</P><OL><LI><STRONG>The Availability Gap</STRONG></LI></OL><P>SAP Joule is a premium, cloud-based tool primarily available for S/4HANA Cloud (Public/Private Edition) and BTP. For developers working on <STRONG>On-Premise S/4HANA systems</STRONG> or older <STRONG>ECC landscapes</STRONG>, Joule often remains out of reach. We believe AI shouldn't be limited by your SAP version.</P><OL><LI><STRONG>The Privacy Paradox</STRONG></LI></OL><P>In the SAP world, code is proprietary. Many firms are hesitant to "ship" their custom business logic to a cloud provider for processing. By using a <STRONG>Local LLM (Large Language Model)</STRONG>, your source code never leaves your workstation. It stays behind your firewall, ensuring 100% data sovereignty.</P><OL><LI><STRONG>The Cost of Innovation</STRONG></LI></OL><P>Cloud-based AI is expensive. Between BTP licensing, API consumption costs, and per-user fees, the "Joule bill" can add up quickly. Our solution leverages the <STRONG>128GB of RAM</STRONG> already sitting in your workstation. Once your hardware is paid for, your AI "co-pilot" costs <STRONG>$0 per month</STRONG> to run.</P><OL><LI><STRONG>Empowering the Developer</STRONG></LI></OL><P>This blog is for the developer who wants the power of a <STRONG>Senior Architect</STRONG> sitting on their shoulder, without waiting for corporate budget approval or BTP provisioning. We are democratizing AI for the ABAP community, one local install at a time.</P><P>This blog outlines how to build a private, high-performance ABAP development environment using <STRONG>VS Code</STRONG>, <STRONG>Ollama</STRONG>, and a <STRONG>Local 32B AI Model</STRONG>.</P><P><STRONG>Phase 1: The Hardware & Engine”</STRONG></P><P>Before coding, we must prepare the "brain" of the operation.</P><OL><LI><STRONG>Install Ollama:</STRONG> Download from <A href="https://ollama.com" target="_blank" rel="noopener nofollow noreferrer">ollama.com</A>. When you install ollama it is configured as autostart program. Use taskmanager to disable this . Disable Ollama autostart to ensure environment variables are correctly applied when manually starting the service. Open a powershell in admin mode and run the following commands and leave this window open. A windows restart is required before the next step otherwise you will get a port binding error.</LI></OL><P>$env:OLLAMA_HOST = "127.0.0.1:11434" </P><P>$env:OLLAMA_ORIGINS = "*" # this is for CORS This allows VS Code #extensions (Continue) to communicate with Ollama locally.</P><P>ollama serve</P><OL><LI><STRONG>Pull the Models:</STRONG> Open PowerShell and run:<UL><LI>ollama pull qwen2.5-coder:32b (Your "Senior Architect")</LI><LI>ollama pull qwen2.5-coder:1.5b (Your "Fast Autocomplete")</LI></UL></LI><LI> Create a Modelfile (without any extensions) with the following contents for qwen2.5-coder:32b you can change this to whatever model you want to use.</LI></OL><P>FROM qwen2.5-coder:32b</P><P># We have 128GB RAM, so let's use a massive context window for SAP projects</P><P>PARAMETER num_ctx 32768</P><P>PARAMETER temperature 0.</P><P>SYSTEM """</P><P>You are a Lead SAP ABAP Developer specializing in S/4HANA 2023.</P><P>Your goal is to provide high-quality, production-ready code.</P><OL><LI>Use Modern ABAP: Prioritize expressions like NEW, VALUE, CORRESPONDING, and inline declarations (@DATA).</LI><LI>Framework Expertise: Deep knowledge of RAP (RESTful ABAP Programming Model), OData v4, and CDS Views.</LI><LI>Clean Code: Follow Clean ABAP principles. No Hungarian notation.</LI><LI>Context: When I provide code, analyze it for performance bottlenecks (e.g., SELECTs inside loops).</LI></OL><P>"""</P><OL><LI>Create an ABAP model with this file in a PowerShell admin window</LI></OL><P> <STRONG>ollama create abap-master-fast -f Modelfile</STRONG></P><P> </P><OL><LI><STRONG>The 128GB RAM Flex:</STRONG> Increase the memory window so the AI can read massive files like abapGit:<UL><LI>Run ollama run qwen2.5-coder:32b.</LI><LI>Type /set parameter num_ctx 32768 and then /save abap-master</LI></UL></LI></OL><P><STRONG>Phase 2: Connecting VS Code to S/4HANA</STRONG></P><P>We use the <STRONG>ABAP Remote FileSystem</STRONG> to bridge the gap.</P><OL><LI><STRONG>Install Extension:</STRONG> Search for "ABAP Remote FileSystem" in the VS Code Marketplace.</LI><LI><STRONG>Enable ADT on SAP:</STRONG> In your S/4HANA system, In Transaction SICF, ensure the <STRONG>ADT</STRONG> service is active. (In S/4HANA 2023, ADT_SRV is no longer use.</LI><LI><STRONG>Configure Connection:</STRONG> Press Ctrl + Shift + P -> ABAPfs: Connection Manager. Add your system details (Hostname, Client, etc.).</LI></OL><P> The contents of config.json for ABAP S4HANA 2023 are as follows</P><P>{</P><P> "workbench.colorTheme": "Default Dark+",</P><P> "window.zoomLevel": 1,</P><P> "abapfs.remote": {</P><P> </P><P> "A5H": {</P><P> "url": "<A href="http://vhcala4hci:50000" target="_blank" rel="noopener nofollow noreferrer">http://vhcala4hci:50000</A>",</P><P> "username": "<YOUR_USER>",</P><P> "password": "<YOUR_PASSWORD>",</P><P> "client": "001",</P><P> "language": "EN",</P><P> "allowSelfSigned": true,</P><P> "syncFolder": "C:\\Users\\r_vod\\Documents\\SAP_Local_Sync",</P><P> "downloadOnOpen": true</P><P> }</P><P> },</P><P> "abapfs.cleaner": {</P><P> </P><P> },</P><P> "editor.inlineSuggest.edits.showCollapsed": true</P><P>Save this and restart VS code so that the connection is made on startup as shown below. Click on the package to see the different folders</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_0-1770761690557.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371197iE9355C5181AC5FC1/image-size/medium?v=v2&px=400" role="button" title="vodela_0-1770761690557.png" alt="vodela_0-1770761690557.png" /></span></P><P> </P><P> </P><P><STRONG>Phase 3: The AI Assistant (Continue Extension)</STRONG></P><P>This replaces the need for an expensive Claude/Copilot subscription.</P><OL><LI><STRONG>Install "Continue-open source AI Code agent":</STRONG> Search for the Continue extension in VS Code.</LI><LI><STRONG>Configure config.yaml:</STRONG> Set your provider to ollama and point the model to abap-master.</LI><LI><STRONG>The "Ghost Text" setup:</STRONG> Ensure the tabAutocompleteModel is set to the 1.5b version for instant typing suggestions</LI></OL><P>The following .yaml file is in %USERPROFILE%/config.yaml - a sample with my settings is provided below</P><P> </P><P>name: SAP ABAP Master Config</P><P>version: 1.0.0</P><P>schema: v1</P><P> </P><P># This is the list of models for Chat and Refactoring (Ctrl+L / Ctrl+I)</P><P>models:</P><P> - name: "ABAP Master (Fast)"</P><P> provider: ollama</P><P> model: abap-master-fast</P><P> apiBase: <A href="http://localhost:11434" target="_blank" rel="noopener nofollow noreferrer">http://localhost:11434</A></P><P> roles:</P><P> - chat</P><P> - name: "ABAP Master (Heavy 32B)"</P><P> provider: ollama</P><P> model: qwen2.5-coder:32b</P><P> apiBase: <A href="http://localhost:11434" target="_blank" rel="noopener nofollow noreferrer">http://localhost:11434</A></P><P> contextLength: 32768 # <--- Increases "Short-term memory"</P><P> completionOptions:</P><P> maxTokens: 8192 # <--- Allows for long code generations</P><P> roles:</P><P> - edit</P><P> - apply</P><P> </P><P># This section must be OUTSIDE the models list</P><P>tabAutocompleteModel:</P><P> name: "Qwen 1.5B (Speed)"</P><P> provider: ollama</P><P> model: qwen2.5-coder:1.5b</P><P> apiBase: <A href="http://localhost:11434" target="_blank" rel="noopener nofollow noreferrer">http://localhost:11434</A></P><P> roles:</P><P> - autocomplete # This tells Continue specifically to use this for Ghost Text</P><P>tabAutocompleteOptions:</P><P> useCopyBuffer: true</P><P> maxPromptTokens: 400</P><P> debounceDelay: 250</P><P> </P><P>Make sure VS code does not show any errors with continue</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_1-1770761690559.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371196iADF3460186BE7BC2/image-size/medium?v=v2&px=400" role="button" title="vodela_1-1770761690559.png" alt="vodela_1-1770761690559.png" /></span></P><P> </P><P><STRONG>Phase 4: Creating Your First Program (The Workflow)</STRONG></P><P><STRONG>Never create files manually in Windows.</STRONG> Always use the SAP-aware command:</P><OL><LI><STRONG>Command:</STRONG> Ctrl + Shift + P -> ABAPfs Create object.</LI><LI><STRONG>Details:</STRONG> Select <STRONG>Program</STRONG>, name it Z_AI_FLIGHT_DEMO, and use package $TMP.</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_2-1770761690561.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371198iE399E371956BF290/image-size/medium?v=v2&px=400" role="button" title="vodela_2-1770761690561.png" alt="vodela_2-1770761690561.png" /></span></P><P> </P><P> </P><P><STRONG>Phase 5: "Vibe Coding" with SFLIGHT</STRONG></P><P>Now, let the local AI do the heavy lifting.</P><OL><LI><STRONG>Inline Edit:</STRONG> Press <STRONG>Ctrl + I</STRONG> inside the blank file.</LI><LI><STRONG>The Request:</STRONG> <EM>"Write a report using SFLIGHT and the SALV class to show all flights for carrier 'AA'."</EM></LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_3-1770761690565.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371199iF357E7DC08720141/image-size/medium?v=v2&px=400" role="button" title="vodela_3-1770761690565.png" alt="vodela_3-1770761690565.png" /></span></P><P> </P><OL><LI><STRONG>Review & Accept:</STRONG> The AI streams the code. Press <STRONG>Ctrl + Shift + Enter</STRONG> to accept.</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_4-1770761690570.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371201i18C833F4C32EF97D/image-size/medium?v=v2&px=400" role="button" title="vodela_4-1770761690570.png" alt="vodela_4-1770761690570.png" /></span></P><P> </P><P> </P><P>Save in VS Code and SE38 Activate, and click on change to see the code. Test to execute this program.</P><P><STRONG> Phase 6: Pushing to SE38 (Solving Conflicts)</STRONG></P><P>The most common hurdle for new users is the "Sync Conflict."</P><OL><LI><STRONG>The Conflict:</STRONG> If you see "Merge with Remote," it means VS Code and SAP are out of sync.</LI><LI><STRONG>The Fix:</STRONG> Press <STRONG>Ctrl + F3</STRONG> (Activate). This forces the local AI code into the SAP database.</LI><LI><STRONG>Verification:</STRONG> Open <STRONG>Transaction SE38</STRONG> in your SAP GUI. Your code is there, ready to run!</LI></OL><P> </P><P> <STRONG> Phase 7: Using AI to Read and Summarize Code</STRONG></P><OL><LI><STRONG> Download: </STRONG> Click on the File you want the AI to read and help you to understand, right click and choose download and save it with the same name in the configured folder in config.json</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_5-1770761690573.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371200i5C0A2DEF9A86D44C/image-size/medium/is-moderation-mode/true?v=v2&px=400" role="button" title="vodela_5-1770761690573.png" alt="vodela_5-1770761690573.png" /></span></P><P> </P><P><STRONG> </STRONG></P><P><STRONG> </STRONG></P><OL><LI><STRONG>Click on Ctrl+L to chat with AI </STRONG>– type in the chat window Can you read the file C:\Users\r_vod\Documents\SAP_Local_Sync\z_ai_flight_demo.prog and give me a summary of what it is doing and hit enter</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_6-1770761690576.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371202iCFA64B0D026D3C0A/image-size/medium?v=v2&px=400" role="button" title="vodela_6-1770761690576.png" alt="vodela_6-1770761690576.png" /></span></P><P> </P><P> </P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="vodela_7-1770761690580.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/371203i659C848F40993BCC/image-size/medium?v=v2&px=400" role="button" title="vodela_7-1770761690580.png" alt="vodela_7-1770761690580.png" /></span></P><P><STRONG>Summary of Success</STRONG></P><UL><LI><STRONG>Privacy:</STRONG> 100% (No code leaves your machine).</LI><LI><STRONG>Speed:</STRONG> Instant (Thanks to the 128GB RAM).</LI><LI><STRONG>Cost:</STRONG> $0 (Open-source tools only).</LI></UL>2026-02-10T23:21:51.735000+01:00https://community.sap.com/t5/linz-blog-posts/herzlich-willkommen-in-der-gruppe-linz/ba-p/14320523Herzlich Willkommen in der Gruppe Linz!2026-02-12T10:10:55.152000+01:00mclbhttps://community.sap.com/t5/user/viewprofilepage/user-id/14678<P>Herzlich Willkommen in der Gruppe Linz!</P><P>Hier wollen wir die SAP-Community in Linz und generell Oberösterreich stärker zusammenführen.<BR />Durch unsere Lage im Zentrum von Oberösterreich, unsere starke Industrie und nicht zuletzt Initiativen, wie die Digital Mile, ist diese Gruppe längst überfällig und ich bin echt glücklich, dass das nun geklappt hat.</P><P>Ziel ist es vorerst, hier eine Gruppe aufzubauen und persönliche Treffen in Form von Stammtischen zu organisieren, um uns gegenseitig kennenzulernen und herauszufinden welche Themen gerade bewegen.<BR />Später möchte ich das noch erweitern und Wissen zu aktuellen Themen zielgerichteter zu transportieren. Wir werden sehen, wohin uns diese Reise führen wird.</P><P>Ich hoffe jetzt einmal auf rege Teilnahme und wir sehen uns bald.</P><P>Marcus</P>2026-02-12T10:10:55.152000+01:00