SAP AI

/

feb 16, 2025

SAP S/4HANA document grounding with SAP AI Core (real use case)

AI doesnt just collect data - it transforms it into actionable steps that grow your business.

/

AUTHOR

/

AUTHOR

/

AUTHOR

Mateusz Kwaśniewski

Enabling Intelligent Knowledge Transfer Assistance through SAP AI Core and ABAP

In today’s enterprise landscape, the volume of business documentation - policies, standard operating procedures, and system manuals - continues to grow exponentially. Navigating and extracting insights from these documents efficiently becomes critical for onboarding new team members, supporting knowledge transfer (KT), and driving process compliance.

This is where SAP AI Core integration with ABAP comes into play. By orchestrating AI-powered document grounding within the SAP landscape, organizations can create an intelligent assistance framework that enables employees to interact naturally with enterprise knowledge. Imagine a scenario during onboarding where a new User can simply ask:

“I want to understand what are all possible existing errors in our custom process?”

and instantly receive a contextual, document-grounded response sourced from internal repositories such as SharePoint and business process documentation.

This real use case leverages SAP AI Core’s orchestration capabilities to deploy and manage machine learning or large language model (LLM)-based workloads that connect seamlessly with SAP S/4HANA on premise with ABAP.

https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/initial-setup?locale=en-US

Technical Prerequisites

To implement this orchestration-based document grounding scenario, the following components and configurations are required:

  1. SAP AI Core

    • A fully configured SAP AI Core tenant for managing orchestration pipelines, models, and deployment runtimes.

    • Ensure connection setup between SAP AI Core and AI Launchpad for monitoring and lifecycle management

      https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/initial-setup?locale=en-US


  2. SAP S/4HANA System

    • Active OData or REST APIs for data retrieval and process integration.

    • RFC or Cloud Connector configuration (if applicable) to bridge communication between on-premise and AI Core environments.

  3. SAP AIF (Application Interface Framework)

    • Installed and configured to handle message processing, mapping, and error handling between AI Core services and S/4HANA.

    • Useful for defining custom message structures for AI requests and responses.

  4. SharePoint Connection for Document Repository

    • SharePoint (or an equivalent enterprise repository) integrated for storing and managing business process documents.

    • Connection established via REST API or Microsoft Graph API to allow retrieval of reference materials during document grounding.

Use Case: Knowledge Assistance for Onboarding

When new employees join a department, they often spend significant time exploring multiple sources to understand workflows, transactions, and documentation. With the SAP AI Core–S/4HANA integration:

  • The AI model indexes and grounds data from connected document repositories (SharePoint, internal manuals).

  • Users interact through a chat-based interface or SAP Fiori application, querying about tasks, rules, or steps.

  • SAP AIF handles the structured communication between the AI orchestration layer and the S/4HANA system, ensuring data security and compliance.

This architecture not only enhances knowledge accessibility but also reduces onboarding time and improves process accuracy by aligning answers with organizational standards.

Custom Development in SAP HANA

The integration between SAP AI Core and S/4HANA can be achieved through custom ABAP development on SAP HANA. The key idea is to wrap the AI Core API interaction within a custom class, and expose it via a custom report with an interactive UI.

1. Wrapper Class for SAP AI Core Connection

Create a custom ABAP class (e.g., ZCL_AI_CORE_WRAPPER) that acts as an interface between S/4HANA and SAP AI Core.
This class:

  • Performs HTTP calls to the AI Core REST API,

  • Handles authentication (OAuth 2.0 or token-based),

  • Sends document context or user queries to the AI model,

  • Parses and returns the AI-generated responses.

Example (simplified ABAP pseudo-code):

2. Custom Report with HTML and JavaScript Integration

Next, develop a custom report (transaction or Fiori-style screen) that uses HTML viewer elements and JavaScript to create an interactive chatbot-like UI.

  • The HTML container displays the conversation and responses.

  • JavaScript handles dynamic user input and calls back to the ABAP layer for AI responses.

  • The ABAP backend (via the wrapper class) sends queries to SAP AI Core and returns the grounded answers.


*&---------------------------------------------------------------------*
*& Report Z_LLM_HTML_INTERFACE
*&---------------------------------------------------------------------*
*& Proof of Concept: LLM Interface with HTML Display
*&---------------------------------------------------------------------*
REPORT zyb4_mk_agent2.

*----------------------------------------------------------------------*
* CLASS DEFINITIONS
*----------------------------------------------------------------------*
CLASS zcl_api DEFINITION.
  PUBLIC SECTION.
    METHODS execute
      IMPORTING
        iv_prompt        TYPE string
      RETURNING
        VALUE(rv_result) TYPE string.
ENDCLASS.

CLASS zcl_api IMPLEMENTATION.
  METHOD execute.
    " This is a wrapper method that should call your actual LLM API
    " For POC purposes, returning a mock response
    rv_result = |Mock LLM Response for: { iv_prompt }|.

    " TODO: Implement actual API call to LLM service here
    " Example structure:
    " - Prepare HTTP client
    " - Set endpoint and authentication
    " - Send prompt as JSON payload
    " - Parse response and return result
  ENDMETHOD.
ENDCLASS.

*----------------------------------------------------------------------*
* CLASS lcl_event_handler - Handle HTML events
*----------------------------------------------------------------------*
CLASS lcl_event_handler DEFINITION.
  PUBLIC SECTION.
    METHODS on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
      IMPORTING action frame getdata postdata query_table.
ENDCLASS.

CLASS lcl_event_handler IMPLEMENTATION.
  METHOD on_sapevent.
    DATA: lv_prompt TYPE string,
          lv_result TYPE string,
          lv_action TYPE string,
          lo_api    TYPE REF TO zcl_api.

    " Get the action type
    lv_action = action.

    CASE lv_action.
      WHEN 'SUBMIT'.
        " Extract the prompt from the query table
        READ TABLE query_table WITH KEY name = 'PROMPT' INTO DATA(ls_query).
        IF sy-subrc = 0.
          lv_prompt = ls_query-value.

          " URL decode the prompt
          lv_prompt =  cl_http_utility=>unescape_url( escaped = lv_prompt ).

          " Call the API wrapper class
          "CREATE OBJECT lo_api.
          DATA(ls_result) = NEW zcl_zyb4_genai_http_query( )->execute( lv_prompt ).

          DATA(ls_response) =  ls_result-final_result-choices[ 1 ]-message-content.

          " Update the HTML with the result
          PERFORM update_html_result USING ls_response.
        ENDIF.

      WHEN 'CLEAR'.
        " Clear both input and output
        PERFORM clear_interface.

      WHEN 'COPY'.
        " Copy result to clipboard (show confirmation)
        PERFORM show_message USING 'Result copied to clipboard!'.

    ENDCASE.
  ENDMETHOD.
ENDCLASS.

*----------------------------------------------------------------------*
* GLOBAL DATA
*----------------------------------------------------------------------*
DATA: go_container   TYPE REF TO cl_gui_custom_container,
      go_html_viewer TYPE REF TO cl_gui_html_viewer,
      go_event       TYPE REF TO lcl_event_handler,
      gv_html        TYPE char255,
      gt_html        TYPE STANDARD TABLE OF  char255,
      gt_html2       TYPE STANDARD TABLE OF  char255,
      gv_last_result TYPE string.

*----------------------------------------------------------------------*
* SELECTION SCREEN
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF SCREEN 100 AS WINDOW.
SELECTION-SCREEN END OF SCREEN 100.

*----------------------------------------------------------------------*
* START-OF-SELECTION
*----------------------------------------------------------------------*
START-OF-SELECTION.
  CALL SCREEN 101.

*----------------------------------------------------------------------*
* MODULE STATUS_0100 OUTPUT
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'MAIN100'.
  SET TITLEBAR 'TITLE100'.

  IF go_container IS INITIAL.
    " Create container
    CREATE OBJECT go_container
      EXPORTING
        container_name = 'HTML_CONTAINER'
      EXCEPTIONS
        OTHERS         = 1.

    " Create HTML viewer
    CREATE OBJECT go_html_viewer
      EXPORTING
        parent = go_container
      EXCEPTIONS
        OTHERS = 1.

    " Create event handler
    CREATE OBJECT go_event.

    " Register event handler
    SET HANDLER go_event->on_sapevent FOR go_html_viewer.

    " Enable SAPEVENT handling
    go_html_viewer->set_registered_events(
      EXPORTING
        events = VALUE #( ( eventid = go_html_viewer->m_id_sapevent appl_event = 'X' ) ) ).

    " Generate initial HTML
    PERFORM generate_html USING ''.

    APPEND gv_html TO gt_html.

    DATA: lv_url TYPE char255..



    " Load HTML into viewer
    go_html_viewer->load_data(
      EXPORTING
        type         = 'text'
        subtype      = 'html'
      IMPORTING
        assigned_url = lv_url
      CHANGING
        data_table   = gt_html
      EXCEPTIONS
        OTHERS       = 1 ).

    go_html_viewer->show_url( url = lv_url ).
  ENDIF.
ENDMODULE.

*----------------------------------------------------------------------*
* MODULE USER_COMMAND_0100 INPUT
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
  CASE sy-ucomm.
    WHEN 'EXIT' OR 'BACK' OR 'CANCEL'.
      LEAVE TO SCREEN 0.
  ENDCASE.
ENDMODULE.

*----------------------------------------------------------------------*
* FORM GENERATE_HTML
*----------------------------------------------------------------------*
FORM generate_html USING lv_result TYPE string .
  DATA: lv_line TYPE w3_html.

  lv_line = '<!DOCTYPE html>'.
  APPEND lv_line TO gt_html.
  lv_line = '<html>'.
  APPEND lv_line TO gt_html.
  lv_line = '<head>'.
  APPEND lv_line TO gt_html.
  lv_line = '<meta charset="UTF-8">'.
  APPEND lv_line TO gt_html.
  lv_line = '<style>'.
  APPEND lv_line TO gt_html.

  " CSS Styles
  lv_line = '  body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f5f5f5; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar { background-color: #2c3e50; padding: 10px 20px; display: flex; gap: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.2); }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button { background-color: #3498db; color: white; padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 5px; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button:hover { background-color: #2980b9; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button:disabled { background-color: #95a5a6; cursor: not-allowed; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button.clear { background-color: #e74c3c; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button.clear:hover { background-color: #c0392b; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button.success { background-color: #27ae60; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .toolbar button.success:hover { background-color: #229954; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .container { max-width: 1200px; margin: 20px auto; background-color: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }'.
  APPEND lv_line TO gt_html.
  lv_line = '  h1 { color: #333; border-bottom: 2px solid #3498db; padding-bottom: 10px; margin-top: 0; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .input-section { margin-bottom: 20px; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  label { display: block; font-weight: bold; margin-bottom: 5px; color: #555; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  textarea { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; resize: vertical; box-sizing: border-box; font-family: Arial, sans-serif; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  textarea:focus { outline: none; border-color: #3498db; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .output-section { margin-top: 20px; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .result-box { width: 100%; min-height: 200px; padding: 12px; border: 1px solid #ddd; border-radius: 4px; background-color: #f9f9f9; white-space: pre-wrap; box-sizing: border-box; font-family: Arial, sans-serif; line-height: 1.6; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .action-buttons { margin-top: 10px; display: flex; gap: 10px; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .action-buttons button { background-color: #3498db; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .action-buttons button:hover { background-color: #2980b9; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .action-buttons button:disabled { background-color: #ccc; cursor: not-allowed; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .loading { display: none; color: #3498db; margin-top: 10px; font-weight: bold; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .status-message { display: none; padding: 10px; margin-top: 10px; border-radius: 4px; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }'.
  APPEND lv_line TO gt_html.
  lv_line = '  .icon { font-size: 16px; }'.
  APPEND lv_line TO gt_html.

  lv_line = '</style>'.
  APPEND lv_line TO gt_html.
  lv_line = '</head>'.
  APPEND lv_line TO gt_html.
  lv_line = '<body>'.
  APPEND lv_line TO gt_html.

  " Toolbar
  lv_line = '<div class="toolbar">'.
  APPEND lv_line TO gt_html.
  lv_line = '  <button onclick="submitPrompt()" id="submitToolbar" title="Execute Prompt"><span class="icon">&#9654;</span> Execute</button>'.
  APPEND lv_line TO gt_html.
  lv_line = '  <button onclick="clearInterface()" class="clear" title="Clear All"><span class="icon">&#10006;</span> Clear</button>'.
  APPEND lv_line TO gt_html.
  lv_line = '  <button onclick="copyResult()" id="copyBtn" title="Copy Result"><span class="icon">&#128203;</span> Copy</button>'.
  APPEND lv_line TO gt_html.
  lv_line = '  <button onclick="saveResult()" id="saveBtn" class="success" title="Save Result"><span class="icon">&#128190;</span> Save</button>'.
  APPEND lv_line TO gt_html.
  lv_line = '  <button onclick="exportResult()" id="exportBtn" title="Export Result"><span class="icon">&#128228;</span> Export</button>'.
  APPEND lv_line TO gt_html.
  lv_line = '</div>'.
  APPEND lv_line TO gt_html.

  " Main Container
  lv_line = '<div class="container">'.
  APPEND lv_line TO gt_html.
  lv_line = '  <h1>Agent for KT data</h1>'.
  APPEND lv_line TO gt_html.

  " Input Section
  lv_line = '  <div class="input-section">'.
  APPEND lv_line TO gt_html.
  lv_line = '    <label for="prompt">Input Prompt:</label>'.
  APPEND lv_line TO gt_html.
  lv_line = '    <textarea id="prompt" rows="6" placeholder="Enter your prompt here..."></textarea>'.
  APPEND lv_line TO gt_html.
  lv_line = '    <div class="action-buttons">'.
  APPEND lv_line TO gt_html.
  lv_line = '      <button onclick="submitPrompt()" id="submitBtn">Submit Prompt</button>'.
  APPEND lv_line TO gt_html.
  lv_line = '    </div>'.
  APPEND lv_line TO gt_html.
  lv_line = '    <div class="loading" id="loading">&#8987; Processing your request...</div>'.
  APPEND lv_line TO gt_html.
  lv_line = '    <div class="status-message" id="statusMsg"></div>'.
  APPEND lv_line TO gt_html.
  lv_line = '  </div>'.
  APPEND lv_line TO gt_html.

  " Output Section
  lv_line = '  <div class="output-section">'.
  APPEND lv_line TO gt_html.
  lv_line = '    <label for="result">Agent response:</label>'.
  APPEND lv_line TO gt_html.
  lv_line = '    <div class="result-box" id="result">Results will appear here...</div>'.
  APPEND lv_line TO gt_html.
  lv_line = '  </div>'.
  APPEND lv_line TO gt_html.
  lv_line = '</div>'.
  APPEND lv_line TO gt_html.

  " JavaScript
  lv_line = '<script>'.
  APPEND lv_line TO gt_html.
  lv_line = '  function submitPrompt() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    var prompt = document.getElementById("prompt").value;'.
  APPEND lv_line TO gt_html.
  lv_line = '    if (!prompt.trim()) {'.
  APPEND lv_line TO gt_html.
  lv_line = '      alert("Please enter a prompt");'.
  APPEND lv_line TO gt_html.
  lv_line = '      return;'.
  APPEND lv_line TO gt_html.
  lv_line = '    }'.
  APPEND lv_line TO gt_html.
  lv_line = '    setButtonsState(true);'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("loading").style.display = "block";'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("result").innerText = "Processing...";'.
  APPEND lv_line TO gt_html.
  lv_line = '    hideStatusMessage();'.
  APPEND lv_line TO gt_html.
  lv_line = '    var encodedPrompt = encodeURIComponent(prompt);'.
  APPEND lv_line TO gt_html.
  lv_line = '    location.href = "SAPEVENT:SUBMIT?PROMPT=" + encodedPrompt;'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function clearInterface() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    if (confirm("Clear all content?")) {'.
  APPEND lv_line TO gt_html.
  lv_line = '      location.href = "SAPEVENT:CLEAR";'.
  APPEND lv_line TO gt_html.
  lv_line = '    }'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function copyResult() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    var result = document.getElementById("result").innerText;'.
  APPEND lv_line TO gt_html.
  lv_line = '    if (result && result !== "Results will appear here...") {'.
  APPEND lv_line TO gt_html.
  lv_line = '      navigator.clipboard.writeText(result).then(function() {'.
  APPEND lv_line TO gt_html.
  lv_line = '        location.href = "SAPEVENT:COPY";'.
  APPEND lv_line TO gt_html.
  lv_line = '      });'.
  APPEND lv_line TO gt_html.
  lv_line = '    } else {'.
  APPEND lv_line TO gt_html.
  lv_line = '      alert("No result to copy");'.
  APPEND lv_line TO gt_html.
  lv_line = '    }'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function saveResult() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    var result = document.getElementById("result").innerText;'.
  APPEND lv_line TO gt_html.
  lv_line = '    if (result && result !== "Results will appear here...") {'.
  APPEND lv_line TO gt_html.
  lv_line = '      location.href = "SAPEVENT:SAVE";'.
  APPEND lv_line TO gt_html.
  lv_line = '    } else {'.
  APPEND lv_line TO gt_html.
  lv_line = '      alert("No result to save");'.
  APPEND lv_line TO gt_html.
  lv_line = '    }'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function exportResult() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    var result = document.getElementById("result").innerText;'.
  APPEND lv_line TO gt_html.
  lv_line = '    if (result && result !== "Results will appear here...") {'.
  APPEND lv_line TO gt_html.
  lv_line = '      location.href = "SAPEVENT:EXPORT";'.
  APPEND lv_line TO gt_html.
  lv_line = '    } else {'.
  APPEND lv_line TO gt_html.
  lv_line = '      alert("No result to export");'.
  APPEND lv_line TO gt_html.
  lv_line = '    }'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function updateResult(result) {'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("result").innerText = result;'.
  APPEND lv_line TO gt_html.
  lv_line = '    setButtonsState(false);'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("loading").style.display = "none";'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function clearAll() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("prompt").value = "";'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("result").innerText = "Results will appear here...";'.
  APPEND lv_line TO gt_html.
  lv_line = '    hideStatusMessage();'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function showStatusMessage(message) {'.
  APPEND lv_line TO gt_html.
  lv_line = '    var msgEl = document.getElementById("statusMsg");'.
  APPEND lv_line TO gt_html.
  lv_line = '    msgEl.innerText = message;'.
  APPEND lv_line TO gt_html.
  lv_line = '    msgEl.style.display = "block";'.
  APPEND lv_line TO gt_html.
  lv_line = '    setTimeout(function() { hideStatusMessage(); }, 3000);'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function hideStatusMessage() {'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("statusMsg").style.display = "none";'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  lv_line = '  function setButtonsState(disabled) {'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("submitBtn").disabled = disabled;'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("submitToolbar").disabled = disabled;'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("copyBtn").disabled = disabled;'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("saveBtn").disabled = disabled;'.
  APPEND lv_line TO gt_html.
  lv_line = '    document.getElementById("exportBtn").disabled = disabled;'.
  APPEND lv_line TO gt_html.
  lv_line = '  }'.
  APPEND lv_line TO gt_html.
  IF lv_result IS NOT INITIAL.
    lv_line = lv_result.
    APPEND lv_line TO gt_html.
  ENDIF.

  lv_line = '</script>'.
  APPEND lv_line TO gt_html.

  lv_line = '</body>'.
  APPEND lv_line TO gt_html.
  lv_line = '</html>'.
  APPEND lv_line TO gt_html.

ENDFORM.

*----------------------------------------------------------------------*
* FORM UPDATE_HTML_RESULT
*----------------------------------------------------------------------*
FORM update_html_result USING iv_result TYPE string.
  DATA: lv_script TYPE string,
        lv_index type i,
        lv_index2 type i value 0,
        lt_html   TYPE TABLE OF w3_html.

  " Store the last result
  gv_last_result = iv_result.
 lt_html = gt_html.
  " Escape any quotes in the result
  DATA(lv_escaped_result) = iv_result.
  " REPLACE ALL OCCURRENCES OF '*' IN lv_escaped_result WITH ''.
  REPLACE ALL OCCURRENCES OF '\' IN lv_escaped_result WITH '\\'.
  REPLACE ALL OCCURRENCES OF '''' IN lv_escaped_result WITH '\'''.
  REPLACE ALL OCCURRENCES OF '"' IN lv_escaped_result WITH '\"'.
  REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN lv_escaped_result WITH '\n'.

  " Create JavaScript to update the result
  lv_script = |<html><body><script>parent.updateResult("{ lv_escaped_result }");</script></body></html>|.
  "  lv_script = |<html><body><script>parent.updateResult("test");</script></body></html>|.

  DATA(lv_len) = strlen( lv_script ).
  data(lv_mod) = ( lv_len mod 255 ).
  data(lv_counter) = conv i( ( lv_len - lv_mod ) / 255 ).
  data(lv_str_left) = lv_len - ( 255 * lv_mod ).

  IF lv_len > 255.

    lv_index = 0.

    WHILE lv_index2 < lv_counter.
      data(lv_script_part) = lv_script+lv_index(255). " Take 255 characters from current offset
      APPEND lv_script_part TO gt_html.
      lv_index = lv_index + 255.
      add 1 to lv_index2.
    ENDWHILE.

    if lv_mod > 0.
       lv_script_part = lv_script+lv_index(lv_mod). " Take 255 characters from current offset
      APPEND lv_script_part TO gt_html.
      endif.

  ELSE.
    APPEND lv_script TO gt_html.
  ENDIF.
  " Execute the script in the HTML viewer
  go_html_viewer->load_data(
    EXPORTING
      type         = 'text'
      subtype      = 'html'
    IMPORTING
      assigned_url = lv_url
    CHANGING
      data_table   = gt_html
    EXCEPTIONS
      OTHERS       = 1 ).

  go_html_viewer->show_url( url = lv_url ).
ENDFORM.

*----------------------------------------------------------------------*
* FORM CLEAR_INTERFACE
*----------------------------------------------------------------------*
FORM clear_interface.
  DATA: lv_script TYPE string,
        lt_html   TYPE TABLE OF w3html.

  " Clear the stored result
  CLEAR gv_last_result.

  " Create JavaScript to clear the interface
  lv_script = '<html><body><script>parent.clearAll();</script></body></html>'.

  APPEND lv_script TO lt_html.

  " Execute the script
  go_html_viewer->load_data(
    EXPORTING
      type         = 'text'
      subtype      = 'html'
    IMPORTING
      assigned_url = lv_url
    CHANGING
      data_table   = gt_html
    EXCEPTIONS
      OTHERS       = 1 ).

  go_html_viewer->show_url( url = lv_url ).
ENDFORM.

*----------------------------------------------------------------------*
* FORM SHOW_MESSAGE
*----------------------------------------------------------------------*
FORM show_message USING iv_message TYPE string.
  DATA: lv_script TYPE string,
        lt_html   TYPE TABLE OF w3html.

  " Escape the message
  DATA(lv_escaped_msg) = iv_message.
  REPLACE ALL OCCURRENCES OF '"' IN lv_escaped_msg WITH '\"'.

  " Create JavaScript to show the message
  lv_script = |<html><body><script>parent.showStatusMessage("{ lv_escaped_msg }");</script></body></html>|.

  APPEND lv_script TO lt_html.

  " Execute the script
  go_html_viewer->load_data(
    EXPORTING
      type         = 'text'
      subtype      = 'html'
    IMPORTING
      assigned_url = lv_url
    CHANGING
      data_table   = gt_html
    EXCEPTIONS
      OTHERS       = 1 ).

  go_html_viewer->show_url( url = lv_url ).
ENDFORM

/

BLOG

/

BLOG

/

BLOG

SAP AIF

/

Oct 10, 2025

SAP AIF custom ABAP framework

Learn how to modernize your SAP AIF implementations with object-oriented ABAP and clean architecture. Discover best practices for building modular, reusable, and scalable AIF actions that simplify integration and long-term maintenance.

SAP AIF

/

Oct 10, 2025

SAP AIF custom ABAP framework

Learn how to modernize your SAP AIF implementations with object-oriented ABAP and clean architecture. Discover best practices for building modular, reusable, and scalable AIF actions that simplify integration and long-term maintenance.

SAP AIF

/

Oct 10, 2025

SAP AIF custom ABAP framework

Learn how to modernize your SAP AIF implementations with object-oriented ABAP and clean architecture. Discover best practices for building modular, reusable, and scalable AIF actions that simplify integration and long-term maintenance.

SAP AIF

/

Jun 13, 2024

SAP AIF Mapping Conditions - How to Apply Conditional Logic in Interface Mappings

Discover how to use mapping conditions in SAP AIF to apply dynamic logic, value mappings, and checks during message processing. Learn practical configuration steps and examples from Codemine’s SAP integration experts.

SAP AIF

/

Jun 13, 2024

SAP AIF Mapping Conditions - How to Apply Conditional Logic in Interface Mappings

Discover how to use mapping conditions in SAP AIF to apply dynamic logic, value mappings, and checks during message processing. Learn practical configuration steps and examples from Codemine’s SAP integration experts.

SAP AIF

/

Jun 13, 2024

SAP AIF Mapping Conditions - How to Apply Conditional Logic in Interface Mappings

Discover how to use mapping conditions in SAP AIF to apply dynamic logic, value mappings, and checks during message processing. Learn practical configuration steps and examples from Codemine’s SAP integration experts.

SAP AIF

/

May 16, 2024

Enable Editable Fields in SAP AIF Monitor

Learn how to enable editable fields in SAP AIF to fix incorrect inbound data directly in the monitoring tool. Step-by-step setup for Business Partner and S/4HANA integration from Codemine’s SAP experts.

SAP AIF

/

May 16, 2024

Enable Editable Fields in SAP AIF Monitor

Learn how to enable editable fields in SAP AIF to fix incorrect inbound data directly in the monitoring tool. Step-by-step setup for Business Partner and S/4HANA integration from Codemine’s SAP experts.

SAP AIF

/

May 16, 2024

Enable Editable Fields in SAP AIF Monitor

Learn how to enable editable fields in SAP AIF to fix incorrect inbound data directly in the monitoring tool. Step-by-step setup for Business Partner and S/4HANA integration from Codemine’s SAP experts.